/*
15.5/EBF 17340 SMP/P/x86_64/Enterprise Linux/ase155/2391/64-bit/OPT/Mon Nov  9 14:15:35 2009

Confidential property of Sybase, Inc.
Copyright 1987, 2009
Sybase, Inc.  All rights reserved.
Unpublished rights reserved under U.S. copyright laws.

This software contains confidential and trade secret information of Sybase,
Inc.   Use,  duplication or disclosure of the software and documentation by
the  U.S.  Government  is  subject  to  restrictions set forth in a license
agreement  between  the  Government  and  Sybase,  Inc.  or  other  written
agreement  specifying  the  Government's rights to use the software and any
applicable FAR provisions, for example, FAR 52.227-19.
Sybase, Inc. One Sybase Drive, Dublin, CA 94568, USA
*/
declare @script_versnum int
select @script_versnum = 15500
if (@@version_number < @script_versnum)
begin
	print "'installmaster' is being run on an older ASE installation. ASE version '%1!', install scripts version '%2!'.",
		@@version_number, @script_versnum
	select syb_quit()
end
go

declare @do_quit int
select @do_quit = 0
if (check_db_upgrade('master') = 0)
begin
	print "'installmaster' cannot continue, because 'master' database is not upgraded to correct version."
	select @do_quit = 1
end
if (@do_quit = 1)
	select syb_quit()
go

use master
go
select @@version
go
declare @size_needed int
select @size_needed = (3072 - sum(size)) * (@@maxpagesize / 1024) / 1024
from sysusages where dbid = 1
if (@size_needed = 1)
begin
	alter database master on master = 1
end
else if (@size_needed = 2)
begin
	alter database master on master = 2
end
else if (@size_needed = 3)
begin
	alter database master on master = 3
end
else if (@size_needed = 4)
begin
	alter database master on master = 4
end
else if (@size_needed = 5)
begin
	alter database master on master = 5
end
else if (@size_needed = 6)
begin
	alter database master on master = 6
end
go
use master
go

declare @size_needed int
select @size_needed = (1024 - sum(size)) * (@@maxpagesize / 1024) / 1024
from sysusages where dbid = db_id('tempdb')
if (@size_needed = 1)
begin
	alter database tempdb on master = 1
end
go

declare @size_needed int
select @size_needed = (1024 - sum(size)) * (@@maxpagesize / 1024) / 1024
from sysusages where dbid = db_id('model')
if (@size_needed = 1)
begin
	alter database model on master = 1
end
go

declare @size_needed int
select @size_needed = (1024 - sum(size)) * (@@maxpagesize / 1024) / 1024
from sysusages where dbid = db_id('sybsystemdb')
if (@size_needed = 1)
begin
        alter database sybsystemdb on master = 1
end
go


declare @allow_update int
select @allow_update = value from syscurconfigs
	where config = 102
if (@allow_update = 0)
begin
	select config_admin(1, 102, 1, 0, NULL, NULL)
end
go
use master
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dboption')
begin
	print 'Dropping sp_dboption'
	dump tran master with truncate_only
	drop procedure sp_dboption
	dump tran master with truncate_only
end
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_configure')
begin
	print 'Dropping sp_configure'
	dump tran master with truncate_only
	drop procedure sp_configure
	dump tran master with truncate_only
end
go
set proc_return_status OFF
go
if exists (select *
        from sysdatabases
                where name = 'sybsystemprocs')
begin
        use sybsystemprocs
end
else
        use master
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_object')
begin
	drop procedure sp_drop_object
end
go
print "Installing sp_drop_object"
go

/*
** This procedure is used to drop the objects. Main purpose of this procedure 
** is to replace the "if" clause in the install scripts with a call to this 
** procedure. 
**
** Arguments:
**	@objname = Name of the object to be dropped.
**	@objtype = Type of the object (procedure, table, view, trigger,
**			instead of trigger,...etc)
**
** Returns:
**	0	- Successful execution.
**	1	- If @objname IS NULL.
** 
** Usage:
**	sp_drop_object @objname, @objtype
**
*/

create procedure sp_drop_object
	@objname	varchar(255)	= NULL,
	@objtype 	varchar(30)	= "procedure"
as

declare @type1 char(2)
/*
** Check whether the procedure @objname is already exists.
** If exists drop the procedure
*/	

if (@objname IS NULL)
begin
	raiserror 18001
	return (1)
end
else
begin
	select @type1 = type from sysobjects where name = @objname
		and @objtype = "trigger"

	if exists (select 1 from sysobjects
		where name = @objname
		  and type = case @objtype
				when "default" then 'D'	
				when "function" then 'F'
				when "procedure" then 'P'
				when "table"	then 'U'
				when "trigger" then @type1	
				when "view"	then 'V'
				else 'P'
			end)
	begin
		print "Dropping %1! %2!", @objtype, @objname
		
		/*
		** exec drop procedure 'proc_name'
		*/
		exec ("drop " + @objtype + " " + @objname)
	end
end
go

grant execute on sp_drop_object to public
go

dump tran master with truncate_only
go
exec sp_drop_object 'sp_instmsg', 'procedure'
go

exec sp_drop_object 'sp_addconf', 'procedure'
go

exec sp_drop_object 'sp_procxmode', 'procedure'
go

exec sp_drop_object 'sp_validlang', 'procedure'
go

exec sp_drop_object 'sp_getmessage', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_aux_getsize', 'procedure'
go

exec sp_drop_object 'sp_namecrack', 'procedure'
go

exec sp_drop_object 'sp_autoformat', 'procedure'
go

exec sp_drop_object 'sp_remotesql', 'procedure'
go

exec sp_drop_object 'sp_check_remote_tempdb', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_configure', 'procedure'
go

exec sp_drop_object 'sp_dboption', 'procedure'
go

exec sp_drop_object 'sp_dropdevice', 'procedure'
go

exec sp_drop_object 'sp_loaddbupgrade', 'procedure'
go

exec sp_drop_object 'sp_prtsybsysmsgs', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ha_check_certified', 'procedure'
go

exec sp_drop_object 'sp_procxmode', 'procedure'
go

exec sp_drop_object 'sp_validlang', 'procedure'
go

exec sp_drop_object 'sp_getmessage', 'procedure'
go

exec sp_drop_object 'sp_aux_getsize', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_namecrack', 'procedure'
go

exec sp_drop_object 'sp_autoformat', 'procedure'
go

exec sp_drop_object 'sp_remotesql', 'procedure'
go

exec sp_drop_object 'sp_check_remote_tempdb', 'procedure'
go

exec sp_drop_object 'sp_configure', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_dboption', 'procedure'
go

exec sp_drop_object 'sp_dropdevice', 'procedure'
go

exec sp_drop_object 'sp_version', 'procedure'
go

exec sp_drop_object 'sp_validaltlang', 'procedure'
go

exec sp_drop_object 'sp_chklangparam', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_helpgroup', 'procedure'
go

exec sp_drop_object 'sp_helpuser', 'procedure'
go

exec sp_drop_object 'sp_locklogin', 'procedure'
go

exec sp_drop_object 'sp_displaylogin', 'procedure'
go

exec sp_drop_object 'sp_is_dbo', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_dbxt_recreate_proc', 'procedure'
go

exec sp_drop_object 'sp_split_string', 'procedure'
go

exec sp_drop_object 'sp_substring_count', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_replace_string_plus', 'procedure'
go

exec sp_drop_object 'sp_versioncrack', 'procedure'
go

exec sp_drop_object 'sp_getopts', 'procedure'
go

exec sp_drop_object 'sp_addalias', 'procedure'
go

exec sp_drop_object 'sp_addgroup', 'procedure'
go

exec sp_drop_object 'sp_exec_SQL', 'procedure'
go

exec sp_drop_object 'sp_password', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_gen_login_id', 'procedure'
go

exec sp_drop_object 'sp_addlogin', 'procedure'
go

exec sp_drop_object 'sp_addtype', 'procedure'
go

exec sp_drop_object 'sp_addumpdevice', 'procedure'
go

exec sp_drop_object 'sp_addthreshold', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_modifythreshold', 'procedure'
go

exec sp_drop_object 'sp_adduser', 'procedure'
go

exec sp_drop_object 'sp_addremotelogin', 'procedure'
go

exec sp_drop_object 'sp_addsegment', 'procedure'
go

exec sp_drop_object 'sp_addserver', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_addlanguage', 'procedure'
go

exec sp_drop_object 'sp_defaultlanguage', 'procedure'
go

exec sp_drop_object 'sp_helplanguage', 'procedure'
go

exec sp_drop_object 'sp_droplanguage', 'procedure'
go

exec sp_drop_object 'sp_setlangalias', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_bindefault', 'procedure'
go

exec sp_drop_object 'sp_bindrule', 'procedure'
go

exec sp_drop_object 'sp_changedbowner', 'procedure'
go

exec sp_drop_object 'syb_aux_expandbitmap', 'procedure'
go

exec sp_drop_object 'syb_aux_privexor', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'syb_aux_privnots', 'procedure'
go

exec sp_drop_object 'syb_aux_privsand', 'procedure'
go

exec sp_drop_object 'syb_aux_privunion', 'procedure'
go

exec sp_drop_object 'syb_aux_colbit', 'procedure'
go

exec sp_drop_object 'syb_aux_printprivs', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_aux_computeprivs', 'procedure'
go

exec sp_drop_object 'sp_aux_text', 'procedure'
go

exec sp_drop_object 'sp_aux_encr_lookup', 'procedure'
go

exec sp_drop_object 'sp_aux_encrkey_lookup', 'procedure'
go

exec sp_drop_object 'sp_aux_sys_encr_passwd_lookup', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_aux_encrkey_info', 'procedure'
go

exec sp_drop_object 'sp_aux_encr_verify_downgrade', 'procedure'
go

exec sp_drop_object 'sp_checksource', 'procedure'
go

exec sp_drop_object 'sp_column_privileges', 'procedure'
go

exec sp_drop_object 'sp_table_privileges', 'procedure'
go

exec sp_drop_object 'sp_changegroup', 'procedure'
go

exec sp_drop_object 'sp_commonkey', 'procedure'
go

exec sp_drop_object 'sp_cursorinfo', 'procedure'
go

exec sp_drop_object 'sp_deviceattr', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_defaultdb', 'procedure'
go

exec sp_drop_object 'sp_databases', 'procedure'
go

exec sp_drop_object 'sp_dbremap', 'procedure'
go

exec sp_drop_object 'sp_remap', 'procedure'
go

exec sp_drop_object 'sp_depends_cols', 'procedure'
go

exec sp_drop_object 'sp_depends', 'procedure'
go

exec sp_drop_object 'sp_diskdefault', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_is_valid_user', 'procedure'
go

exec sp_drop_object 'sp_dropalias', 'procedure'
go

exec sp_drop_object 'sp_dropgroup', 'procedure'
go

exec sp_drop_object 'sp_dropkey', 'procedure'
go

exec sp_drop_object 'sp_droplogin', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_dropthreshold', 'procedure'
go

exec sp_drop_object 'sp_droptype', 'procedure'
go

exec sp_drop_object 'sp_dropuser', 'procedure'
go

exec sp_drop_object 'sp_addextendedproc', 'procedure'
go

exec sp_drop_object 'sp_dropextendedproc', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_freedll', 'procedure'
go

exec sp_drop_object 'sp_helpextendedproc', 'procedure'
go

exec sp_drop_object 'sp_aux_sargs_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_aux_get_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_add_qpgroup', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_drop_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_export_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_import_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_rename_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_help_qplan', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_help_qpgroup', 'procedure'
go

exec sp_drop_object 'sp_drop_qplan', 'procedure'
go

exec sp_drop_object 'sp_find_qplan', 'procedure'
go

exec sp_drop_object 'sp_cmp_qplans', 'procedure'
go

exec sp_drop_object 'sp_copy_qplan', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_copy_all_qplans', 'procedure'
go

exec sp_drop_object 'sp_drop_all_qplans', 'procedure'
go

exec sp_drop_object 'sp_set_qplan', 'procedure'
go

exec sp_drop_object 'sp_cmp_all_qplans', 'procedure'
go

exec sp_drop_object 'sp_dropremotelogin', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_dropsegment', 'procedure'
go

exec sp_drop_object 'sp_dropserver', 'procedure'
go

exec sp_drop_object 'sp_dumpoptimize', 'procedure'
go

exec sp_drop_object 'sp_querysmobj', 'procedure'
go

exec sp_drop_object 'sp_deletesmobj', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_estspace', 'procedure'
go

exec sp_drop_object 'sp_extendsegment', 'procedure'
go

exec sp_drop_object 'sp_fixindex', 'procedure'
go

exec sp_drop_object 'sp_fkeys', 'procedure'
go

exec sp_drop_object 'sp_help_metrics', 'procedure'
go

exec sp_drop_object 'sp_drop_metrics', 'procedure'
go

exec sp_drop_object 'sp_backup_metrics', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_show_metrics', 'procedure'
go

exec sp_drop_object 'sp_filter_metrics', 'procedure'
go

exec sp_drop_object 'sp_flushmetrics', 'procedure'
go

exec sp_drop_object 'sp_metrics', 'procedure'
go

exec sp_drop_object 'sp_help_query_tuning', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_flush_query_tuning', 'procedure'
go

exec sp_drop_object 'sp_drop_query_tuning', 'procedure'
go

exec sp_drop_object 'sp_show_query_tuning', 'procedure'
go

exec sp_drop_object 'sp_query_tuning', 'procedure'
go

exec sp_drop_object 'sp_flushstats', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_foreignkey', 'procedure'
go

exec sp_drop_object 'sp_helpcomputedcolumn', 'procedure'
go

exec sp_drop_object 'sp_helpconstraint', 'procedure'
go

exec sp_drop_object 'sp_helpdb', 'procedure'
go

exec sp_drop_object 'sp_helpdevice', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_helplog', 'procedure'
go

exec sp_drop_object 'sp_helpindex', 'procedure'
go

exec sp_drop_object 'sp_helpjoins', 'procedure'
go

exec sp_drop_object 'sp_helpkey', 'procedure'
go

exec sp_drop_object 'sp_objectsegment', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_indsuspect', 'procedure'
go

exec sp_drop_object 'sp_helpartition', 'procedure'
go

exec sp_drop_object 'sp_tab_suspectptn', 'procedure'
go

exec sp_drop_object 'sp_help_params', 'procedure'
go

exec sp_drop_object 'sp_help', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_helprotect', 'procedure'
go

exec sp_drop_object 'sp_showtext_usage', 'procedure'
go

exec sp_drop_object 'sp_showtext_print_line', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_showtext_check_print', 'procedure'
go

exec sp_drop_object 'sp_showtext_sproc_tagline', 'procedure'
go

exec sp_drop_object 'sp_showtext_output', 'procedure'
go

exec sp_drop_object 'sp_showtext', 'procedure'
go

exec sp_drop_object 'sp_helptext_usage', 'procedure'
go

exec sp_drop_object 'sp_helptext', 'procedure'
go

exec sp_drop_object 'sp_helpthreshold', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_lock', 'procedure'
go

exec sp_drop_object 'sp_logdevice', 'procedure'
go

exec sp_drop_object 'sp_lookup', 'procedure'
go

exec sp_drop_object 'sp_helpremotelogin', 'procedure'
go

exec sp_drop_object 'sp_helpsegment', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_helpsort', 'procedure'
go

exec sp_drop_object 'sp_helpserver', 'procedure'
go

exec sp_drop_object 'sp_hidetext', 'procedure'
go

exec sp_drop_object 'sp_markreport', 'procedure'
go

exec sp_drop_object 'sp_dbxt_recreate_proc', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_check_permission', 'procedure'
go

exec sp_drop_object 'sp_monitor_help', 'procedure'
go

exec sp_drop_object 'sp_monitor_server', 'procedure'
go

exec sp_drop_object 'sp_monitor', 'procedure'
go

exec sp_drop_object 'sp_pkeys', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_placeobject', 'procedure'
go

exec sp_drop_object 'sp_primarykey', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_recompile', 'procedure'
go

exec sp_drop_object 'sp_remoteoption', 'procedure'
go

exec sp_drop_object 'sp_rename', 'procedure'
go

exec sp_drop_object 'sp_renamedb', 'procedure'
go

exec sp_drop_object 'sp_serveroption', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_serverinfo', 'procedure'
go

exec sp_drop_object 'sp_server_info', 'procedure'
go

exec sp_drop_object 'sp_inform', 'procedure'
go

exec sp_drop_object 'sp_setreplicate', 'procedure'
go

exec sp_drop_object 'sp_spaceused', 'procedure'
go

exec sp_drop_object 'sp_sproc_columns', 'procedure'
go

exec sp_drop_object 'sp_statistics', 'procedure'
go

exec sp_drop_object 'sp_sendmsg', 'procedure'
go

exec sp_drop_object 'sp_stored_procedures', 'procedure'
go

exec sp_drop_object 'sp_unbindefault', 'procedure'
go

exec sp_drop_object 'sp_unbindrule', 'procedure'
go

exec sp_drop_object 'sp_who', 'procedure'
go

exec sp_drop_object 'sp_client_addr', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_transactions', 'procedure'
go

exec sp_drop_object 'sp_dtx_purge_completedxacts', 'procedure'
go

exec sp_drop_object 'sp_fix_dtm_ha_roles', 'procedure'
go

exec sp_drop_object 'sp_create_syscoordinations', 'procedure'
go

exec sp_drop_object 'sp_procqmode', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_reportstats', 'procedure'
go

exec sp_drop_object 'sp_clearstats', 'procedure'
go

exec sp_drop_object 'sp_datatype_info', 'procedure'
go

exec sp_drop_object 'sp_addmessage', 'procedure'
go

exec sp_drop_object 'sp_dropmessage', 'procedure'
go

exec sp_drop_object 'sp_bindmsg', 'procedure'
go

exec sp_drop_object 'sp_unbindmsg', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_altermessage', 'procedure'
go

exec sp_drop_object 'sp_role', 'procedure'
go

exec sp_drop_object 'sp_logintrigger', 'procedure'
go

exec sp_drop_object 'sp_modifylogin', 'procedure'
go

exec sp_drop_object 'sp_encryption', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_passwordpolicy', 'procedure'
go

exec sp_drop_object 'sp_update_authmech_value', 'procedure'
go

exec sp_drop_object 'sp_inst15015msg_config', 'procedure'
go

exec sp_drop_object 'sp_inst15015msg_us_mesg', 'procedure'
go

exec sp_drop_object 'sp_inst15015msg_addlimsg', 'procedure'
go

exec sp_drop_object 'sp_inst15015msg_oth_mesg', 'procedure'
go

exec sp_drop_object 'sp_inst15015msg_all_us_mesgs', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_inst15015msg_all_oth_mesgs', 'procedure'
go

exec sp_drop_object 'sp_inst15015msg', 'procedure'
go

exec sp_drop_object 'sp_downgrade_durability', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_downgrade_sysobjects', 'procedure'
go

exec sp_drop_object 'sp_downgrade', 'procedure'
go

exec sp_drop_object 'sp_ssladmin', 'procedure'
go

exec sp_drop_object 'sp_ldapadmin', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_escapeliteralforlike', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ijdbc_datatype_info', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_columns', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_tables', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_mda', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_convert_datatype', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ijdbc_function_escapes', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_fkeys', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_exportkey', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_importkey', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getcrossreferences', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ijdbc_getschemas', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_aux_computeprivs', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getcolumnprivileges', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_gettableprivileges', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getcatalogs', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ijdbc_primarykey', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_sql_type_name', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getbestrowidentifier', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getisolationlevels', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getindexinfo', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ijdbc_stored_procedures', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getprocedurecolumns', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getversioncolumns', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_default_charset', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_classes_in_jar', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ijdbc_getudts', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_getxacoordinator', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_jar_by_name', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_jar_for_class', 'procedure'
go

exec sp_drop_object 'sp_ijdbc_class_for_name', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_volchanged', 'procedure'
go

exec sp_drop_object 'sp_checkreswords', 'procedure'
go

exec sp_drop_object 'sp_tables', 'procedure'
go

exec sp_drop_object 'sp_special_columns', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_columns', 'procedure'
go

exec sp_drop_object 'sp_aux_parse_entity', 'procedure'
go

exec sp_drop_object 'sp_cachestrategy', 'procedure'
go

exec sp_drop_object 'sp_optimal_text_space', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_chgattribute', 'procedure'
go

exec sp_drop_object 'sp_cacheconfig', 'procedure'
go

exec sp_drop_object 'sp_bindcache', 'procedure'
go

exec sp_drop_object 'sp_do_poolconfig', 'procedure'
go

exec sp_drop_object 'sp_poolconfig', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_unbindcache', 'procedure'
go

exec sp_drop_object 'sp_unbindcache_all', 'procedure'
go

exec sp_drop_object 'sp_setrepcol', 'procedure'
go

exec sp_drop_object 'sp_setrepproc', 'procedure'
go

exec sp_drop_object 'sp_setreptable', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_logiosize', 'procedure'
go

exec sp_drop_object 'sp_sqlrep_check_syntax', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_setrepdefmode', 'procedure'
go

exec sp_drop_object 'sp_displaylevel', 'procedure'
go

exec sp_drop_object 'sp_setlockpromote', 'procedure'
go

exec sp_drop_object 'sp_droplockpromote', 'procedure'
go

exec sp_drop_object 'sp_familylock', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_setpglockpromote', 'procedure'
go

exec sp_drop_object 'sp_dropglockpromote', 'procedure'
go

exec sp_drop_object 'sp_setrowlockpromote', 'procedure'
go

exec sp_drop_object 'sp_droprowlockpromote', 'procedure'
go

exec sp_drop_object 'sp_sysmon_kernel', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_sysmon_wpm', 'procedure'
go

exec sp_drop_object 'sp_sysmon_parallel', 'procedure'
go

exec sp_drop_object 'sp_sysmon_taskmgmt', 'procedure'
go

exec sp_drop_object 'sp_sysmon_appmgmt', 'procedure'
go

exec sp_drop_object 'sp_sysmon_esp', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_sysmon_hk', 'procedure'
go

exec sp_drop_object 'sp_sysmon_maccess', 'procedure'
go

exec sp_drop_object 'sp_sysmon_xactsum', 'procedure'
go

exec sp_drop_object 'sp_sysmon_xactmgmt', 'procedure'
go

exec sp_drop_object 'sp_sysmon_index', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_sysmon_locks', 'procedure'
go

exec sp_drop_object 'sp_sysmon_dcache_dtl', 'procedure'
go

exec sp_drop_object 'sp_sysmon_dcache_sum', 'procedure'
go

exec sp_drop_object 'sp_sysmon_dcache', 'procedure'
go

exec sp_drop_object 'sp_sysmon_pcache', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_sysmon_memory', 'procedure'
go

exec sp_drop_object 'sp_sysmon_recovery', 'procedure'
go

exec sp_drop_object 'sp_sysmon_diskio', 'procedure'
go

exec sp_drop_object 'sp_sysmon_netio', 'procedure'
go

exec sp_drop_object 'sp_sysmon_repagent', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_addengine', 'procedure'
go

exec sp_drop_object 'sp_addexeclass', 'procedure'
go

exec sp_drop_object 'sp_bindexeclass', 'procedure'
go

exec sp_drop_object 'sp_clearpsexe', 'procedure'
go

exec sp_drop_object 'sp_dropengine', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_dropexeclass', 'procedure'
go

exec sp_drop_object 'sp_setpsexe', 'procedure'
go

exec sp_drop_object 'sp_showcontrolinfo', 'procedure'
go

exec sp_drop_object 'sp_showexeclass', 'procedure'
go

exec sp_drop_object 'sp_showpsexe', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_unbindexeclass', 'procedure'
go

exec sp_drop_object 'sp_activeroles', 'procedure'
go

exec sp_drop_object 'sp_displayroles', 'procedure'
go

exec sp_drop_object 'sp_validateconfigname', 'procedure'
go

exec sp_drop_object 'sp_countmetadata', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitorconfig', 'procedure'
go

exec sp_drop_object 'sp_helpconfig', 'procedure'
go

exec sp_drop_object 'sp_sysmon_mdcache', 'procedure'
go

exec sp_drop_object 'sp_sysmon_collect', 'procedure'
go

exec sp_drop_object 'sp_sysmon_analyze', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_shmdumpsize', 'procedure'
go

exec sp_drop_object 'sp_shmdumpdrop', 'procedure'
go

exec sp_drop_object 'sp_shmdumpdisp', 'procedure'
go

exec sp_drop_object 'sp_shmdumpconfig_config', 'procedure'
go

exec sp_drop_object 'sp_shmdumpconfig', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_sysmon', 'procedure'
go

exec sp_drop_object 'sp_memlog', 'procedure'
go

exec sp_drop_object 'sp_add_resource_limit', 'procedure'
go

exec sp_drop_object 'sp_gen_timerange_id', 'procedure'
go

exec sp_drop_object 'sp_add_time_range', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_drop_resource_limit', 'procedure'
go

exec sp_drop_object 'sp_drop_time_range', 'procedure'
go

exec sp_drop_object 'sp_help_resource_limit', 'procedure'
go

exec sp_drop_object 'sp_modify_resource_limit', 'procedure'
go

exec sp_drop_object 'sp_modify_time_range', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_showplan', 'procedure'
go

exec sp_drop_object 'sp_listsuspect_page', 'procedure'
go

exec sp_drop_object 'sp_forceonline_page', 'procedure'
go

exec sp_drop_object 'sp_makesuspect_obj', 'procedure'
go

exec sp_drop_object 'sp_forceonline_db', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_listsuspect_db', 'procedure'
go

exec sp_drop_object 'sp_listsuspect_object', 'procedure'
go

exec sp_drop_object 'sp_forceonline_object', 'procedure'
go

exec sp_drop_object 'sp_setsuspect_error', 'procedure'
go

exec sp_drop_object 'sp_setsuspect_granularity', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_setsuspect_threshold', 'procedure'
go

exec sp_drop_object 'sp_dbrecovery_order', 'procedure'
go

exec sp_drop_object 'sp_dbcc_scale_factor', 'procedure'
go

exec sp_drop_object 'sp_plan_dbccdb', 'procedure'
go

exec sp_drop_object 'sp_reptostandby', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_setrepdbmode', 'procedure'
go

exec sp_drop_object 'sp_config_rep_agent', 'procedure'
go

exec sp_drop_object 'sp_help_rep_agent', 'procedure'
go

exec sp_drop_object 'sp_start_rep_agent', 'procedure'
go

exec sp_drop_object 'sp_stop_rep_agent', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_object_stats', 'procedure'
go

exec sp_drop_object 'sp_modifystats', 'procedure'
go

exec sp_drop_object 'sp_maplogin', 'procedure'
go

exec sp_drop_object 'sp_helpmaplogin', 'procedure'
go

exec sp_drop_object 'sp_helpjava', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_rebuild_text', 'procedure'
go

exec sp_drop_object 'sp_extengine', 'procedure'
go

exec sp_drop_object 'sp_engine', 'procedure'
go

exec sp_drop_object 'sp_errorlog_showhelp', 'procedure'
go

exec sp_drop_object 'sp_errorlog', 'procedure'
go

exec sp_drop_object 'sp_multdb_creategroup', 'procedure'
go

exec sp_drop_object 'sp_multdb_dropgroup', 'procedure'
go

exec sp_drop_object 'sp_multdb_addtogroup', 'procedure'
go

exec sp_drop_object 'sp_multdb_removefromgroup', 'procedure'
go

exec sp_drop_object 'sp_multdb_bind', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_multdb_unbind', 'procedure'
go

exec sp_drop_object 'sp_multdb_unbindall_db', 'procedure'
go

exec sp_drop_object 'sp_multdb_unbindall_gr', 'procedure'
go

exec sp_drop_object 'sp_multdb_show', 'procedure'
go

exec sp_drop_object 'sp_tempdb', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_listener', 'procedure'
go

exec sp_drop_object 'sp_dcachestats_obj_details', 'procedure'
go

exec sp_drop_object 'sp_rjs_register', 'procedure'
go

exec sp_drop_object 'sp_rjs_retrieve', 'procedure'
go

exec sp_drop_object 'sp_rjs_unregister', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_show_options', 'procedure'
go

exec sp_drop_object 'sp_tran_dumpable_status', 'procedure'
go

exec sp_drop_object 'sp_lmconfig', 'procedure'
go

exec sp_drop_object 'sp_post_xpload', 'procedure'
go

exec sp_drop_object 'sp_index_row_size_est', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_index_space_est', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_paramcheck', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_processusing', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_runcmd', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_showhelp_display', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_spaceusage_showhelp_report', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_showhelp_archive', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_showhelp_all', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_showhelp', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_cnvtounit', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_spaceusage_object_init', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_object_populate', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_object_genoutput', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_object_archdata', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_spaceusage_object', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_tranlog_init', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_tranlog_genoutput', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_tranlog_archdata', 'procedure'
go

exec sp_drop_object 'sp_spaceusage_tranlog', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_spaceusage', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_helpapptrace', 'procedure'
go

exec sp_drop_object 'sp_options', 'procedure'
go

exec sp_drop_object 'sp_compatmode', 'procedure'
go

exec sp_drop_object 'sp_setup_table_transfer', 'procedure'
go

exec sp_drop_object 'sp_iqdbcheck', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_addexternlogin', 'procedure'
go

exec sp_drop_object 'sp_addobjectdef', 'procedure'
go

exec sp_drop_object 'sp_addtabledef', 'procedure'
go

exec sp_drop_object 'sp_autoconnect', 'procedure'
go

exec sp_drop_object 'sp_defaultloc', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_dropexternlogin', 'procedure'
go

exec sp_drop_object 'sp_dropobjectdef', 'procedure'
go

exec sp_drop_object 'sp_droptabledef', 'procedure'
go

exec sp_drop_object 'sp_helpexternlogin', 'procedure'
go

exec sp_drop_object 'sp_helpobjectdef', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_passthru', 'procedure'
go

exec sp_drop_object 'sp_checknames', 'procedure'
go

exec sp_drop_object 'sp_ddlgen_help', 'procedure'
go

exec sp_drop_object 'sp_ddlgen_permissions', 'procedure'
go

exec sp_drop_object 'sp_ddlgen_db_print_with_clause', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_ddlgen_db_print_alterdb', 'procedure'
go

exec sp_drop_object 'sp_ddlgen_database', 'procedure'
go

exec sp_drop_object 'sp_ddlgen', 'procedure'
go

exec sp_drop_object 'sp_addlogin_rep', 'procedure'
go

exec sp_drop_object 'sp_password_rep', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_set_password_rep', 'procedure'
go

exec sp_drop_object 'sp_sysmon_dcachestats', 'procedure'
go

exec sp_drop_object 'sp_sysmon_collect_mda', 'procedure'
go

exec sp_drop_object 'sp_sysmon_analyze_mda', 'procedure'
go

exec sp_drop_object 'sp_monitor_crt_mon_config', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_getcfgval', 'procedure'
go

exec sp_drop_object 'sp_monitor_getcfgnum', 'procedure'
go

exec sp_drop_object 'sp_monitor_verify_setup', 'procedure'
go

exec sp_drop_object 'sp_monitor_verify_cfgval', 'procedure'
go

exec sp_drop_object 'sp_monitor_enable_usage', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_enable', 'procedure'
go

exec sp_drop_object 'sp_monitor_disable_usage', 'procedure'
go

exec sp_drop_object 'sp_monitor_disable', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_trace', 'procedure'
go

exec sp_drop_object 'sp_monitor_trace_level', 'procedure'
go

exec sp_drop_object 'sp_monitor_archive_usage', 'procedure'
go

exec sp_drop_object 'sp_mon_gen_columnlist', 'procedure'
go

exec sp_drop_object 'sp_mon_archive_genSQL', 'procedure'
go

exec sp_drop_object 'sp_mon_archive_data', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_mon_archive_monTable', 'procedure'
go

exec sp_drop_object 'sp_mon_archive_deadlock', 'procedure'
go

exec sp_drop_object 'sp_monitor_parse_archive_cmd', 'procedure'
go

exec sp_drop_object 'sp_monitor_archive', 'procedure'
go

exec sp_drop_object 'sp_monitor_report_usage', 'procedure'
go

exec sp_drop_object 'sp_monitor_report', 'procedure'
go

exec sp_drop_object 'sp_monitor_connection_usage', 'procedure'
go

exec sp_drop_object 'sp_monitor_connection', 'procedure'
go

exec sp_drop_object 'sp_monitor_event', 'procedure'
go

exec sp_drop_object 'sp_monitor_procedure', 'procedure'
go

exec sp_drop_object 'sp_monitor_statement', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_deadlock_usage', 'procedure'
go

exec sp_drop_object 'sp_monitor_deadlock_getopts', 'procedure'
go

exec sp_drop_object 'sp_monitor_deadlock_count_by', 'procedure'
go

exec sp_drop_object 'sp_monitor_deadlock_verbose', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_deadlock_driver', 'procedure'
go

exec sp_drop_object 'sp_monitor_deadlock', 'procedure'
go

exec sp_drop_object 'sp_monitor_procstack_usage', 'procedure'
go

exec sp_drop_object 'sp_monitor_procstack', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_monitor_list_montypes', 'procedure'
go

exec sp_drop_object 'sp_monitor_list', 'procedure'
go

exec sp_drop_object 'sp_helpcache', 'procedure'
go

exec sp_drop_object 'sp_jdbc_datatype_info_cts', 'procedure'
go

exec sp_drop_object 'sp_jdbc_datatype_info', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_drv_column_default', 'procedure'
go

exec sp_drop_object 'sp_drv_typeinfo', 'procedure'
go

exec sp_drop_object 'sp_localtypename', 'procedure'
go

exec sp_drop_object 'sp_jdbc_columns', 'procedure'
go

exec sp_drop_object 'sp_jdbc_tables', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_mda', 'procedure'
go

exec sp_drop_object 'sp_jdbc_convert_datatype', 'procedure'
go

exec sp_drop_object 'sp_jdbc_function_escapes', 'procedure'
go

exec sp_drop_object 'sp_jdbc_fkeys', 'procedure'
go

exec sp_drop_object 'sp_jdbc_exportkey', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_jdbc_importkey', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getcrossreferences', 'procedure'
go

exec sp_drop_object 'sp_drv_bcpmetadata', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getschemas_cts', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getschemas', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_jdbc_getcolumnprivileges', 'procedure'
go

exec sp_drop_object 'sp_jdbc_computeprivs', 'procedure'
go

exec sp_drop_object 'sp_jdbc_gettableprivileges', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getcatalogs_cts', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getcatalogs', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_jdbc_primarykey', 'procedure'
go

exec sp_drop_object 'sp_sql_type_name', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getbestrowidentifier', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getisolationlevels', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getindexinfo', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_jdbc_stored_procedures', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getprocedurecolumns', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getversioncolumns', 'procedure'
go

exec sp_drop_object 'sp_default_charset', 'procedure'
go

exec sp_drop_object 'sp_jdbc_getudts', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_jdbc_getxacoordinator', 'procedure'
go

exec sp_drop_object 'sp_jdbc_class_for_name', 'procedure'
go

exec sp_drop_object 'sp_jdbc_jar_for_class', 'procedure'
go

exec sp_drop_object 'sp_jdbc_jar_by_name', 'procedure'
go

exec sp_drop_object 'sp_jdbc_classes_in_jar', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_odbc_computeprivs', 'procedure'
go

exec sp_drop_object 'sp_odbc_server_info', 'procedure'
go

exec sp_drop_object 'sp_odbc_databases', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_odbc_columns', 'procedure'
go

exec sp_drop_object 'sp_odbc_datatype_info', 'procedure'
go

exec sp_drop_object 'sp_odbc_getversioncolumns', 'procedure'
go

exec sp_drop_object 'sp_odbc_getcolumnprivileges', 'procedure'
go

exec sp_drop_object 'sp_odbc_tables', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_odbc_gettableprivileges', 'procedure'
go

exec sp_drop_object 'sp_odbc_getindexinfo', 'procedure'
go

exec sp_drop_object 'sp_odbc_primarykey', 'procedure'
go

exec sp_drop_object 'sp_odbc_fkeys', 'procedure'
go

exec sp_drop_object 'sp_odbc_stored_procedures', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_odbc_getprocedurecolumns', 'procedure'
go

exec sp_drop_object 'sp_oledb_computeprivs', 'procedure'
go

exec sp_drop_object 'sp_oledb_datatype_info', 'procedure'
go

exec sp_drop_object 'sp_oledb_gettableprivileges', 'procedure'
go

exec sp_drop_object 'sp_oledb_tables', 'procedure'
go

exec sp_drop_object 'sp_oledb_statistics', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_oledb_stored_procedures', 'procedure'
go

exec sp_drop_object 'sp_oledb_getprocedurecolumns', 'procedure'
go

exec sp_drop_object 'sp_oledb_getindexinfo', 'procedure'
go

exec sp_drop_object 'sp_oledb_primarykey', 'procedure'
go

exec sp_drop_object 'sp_oledb_fkeys', 'procedure'
go

if ((select db_name()) = "master") 
	dump tran master with truncate_only
else
    if ((select db_name()) = "sybsystemprocs") 
	dump tran sybsystemprocs with truncate_only
    else
        if ((select db_name()) = "dbccdb") 
	    dump tran dbccdb with truncate_only
        else
            if ((select db_name()) = "dbccalt") 
	        dump tran dbccalt with truncate_only
go

exec sp_drop_object 'sp_oledb_columns', 'procedure'
go

exec sp_drop_object 'sp_oledb_getcolumnprivileges', 'procedure'
go

exec sp_drop_object 'sp_oledb_databases', 'procedure'
go

exec sp_drop_object 'sp_oledb_views', 'procedure'
go

use master
go

set nocount on
go
use master
go
if exists (select *
	from sysobjects
		where name = "spt_values")
begin
	drop table spt_values
end
go

/* 
** Langid is filled in by langinstall
*/
create table spt_values (


name	varchar(28) NULL,

number	int,
type	char(2),
ansi_w  tinyint NULL,
low	int NULL,
high	int NULL,
msgnum	int NULL) lock allpages on system
go
create clustered index spt_valuesclust on spt_values(number, type) on system
go
set nocount on
go
/* number 0 - 7 */
insert spt_values(low, high, number, type) values (1, 1, 0, 'P')
insert spt_values(low, high, number, type) values (1, 2, 1, 'P')
insert spt_values(low, high, number, type) values (1, 4, 2, 'P')
insert spt_values(low, high, number, type) values (1, 8, 3, 'P')
insert spt_values(low, high, number, type) values (1, 16, 4, 'P')
insert spt_values(low, high, number, type) values (1, 32, 5, 'P')
insert spt_values(low, high, number, type) values (1, 64, 6, 'P')
insert spt_values(low, high, number, type) values (1, 128, 7, 'P')
go
/* 8 - 15 */
insert spt_values(low, high, number, type)
select low + 1, high, number + 8, 'P'
from spt_values
where number < 8 and number >= 0
go
/* 16 - 31 */
insert spt_values(low, high, number, type)
select low + 2, high, number + 16, 'P'
from spt_values
where number < 16 and number >= 0
go
/* 32 - 63 */
insert spt_values(low, high, number, type)
select low + 4, high, number + 32, 'P'
from spt_values
where number < 32 and number >= 0
go
/* 64 - 127 */
insert spt_values(low, high, number, type)
select low + 8, high, number + 64, 'P'
from spt_values
where number < 64 and number >= 0
go
/* 128 - 255 */
insert spt_values(low, high, number, type)
select low + 16, high, number + 128, 'P'
from spt_values
where number < 128 and number >= 0
go
/* 256 - 511 */
insert spt_values(low, high, number, type)
select low + 32, high, number + 256, 'P'
from spt_values
where number < 256 and number >= 0
go
/* 512 - 1023 */
insert spt_values(low, high, number, type)
select low + 64, high, number + 512, 'P'
from spt_values
where number < 512 and number >= 0
go
/* 1024 */
insert spt_values(low, high, number, type)
select 129, 1, 1024, 'P'
go

/*
**  Configuration options.
** 
** Be sure to add new message values in a_messages
*/
insert spt_values(name, number, type)
  values ("CONFIGURATION OPTIONS", -1, 'C')
insert spt_values(name, number, type, low, high, msgnum)
  values ("recovery interval", 101, 'C', 1, 32767, 17015)
insert spt_values(name, number, type, low, high, msgnum)
  values ("allow updates", 102, 'C', 0, 1, 17016)
insert spt_values(name, number, type, low, high, msgnum)
  values ("user connections", 103, 'C', 5, 2147483647, 17017)
insert spt_values(name, number, type, low, high, msgnum)
  values ("memory", 104, 'C', 1000, 2147483647, 17018)
insert spt_values(name, number, type, low, high, msgnum)
  values ("open databases", 105, 'C', 5, 2147483647, 17019)
insert spt_values(name, number, type, low, high, msgnum)
  values ("locks", 106, 'C', 5000, 2147483647, 17020)
insert spt_values(name, number, type, low, high, msgnum)
  values ("open objects", 107, 'C', 100, 2147483647, 17021)
insert spt_values(name, number, type, low, high, msgnum)
  values ("procedure cache", 108, 'C', 1, 99, 17022)
go
insert spt_values(name, number, type, low, high, msgnum)
  values ("fill factor", 109, 'C', 0, 100, 17023)
insert spt_values(name, number, type, low, high, msgnum)
  values ("time slice", 110, 'C', 50, 1000, 17024)
insert spt_values(name, number, type, low, high, msgnum)
  values ("database size", 111, 'C', 2, 10000, 17025)
insert spt_values(name, number, type, low, high, msgnum)
  values ("tape retention", 112, 'C', 0, 365, 17026)
insert spt_values(name, number, type, low, high, msgnum)
  values ("recovery flags", 113, 'C', 0, 1, 17027)
insert spt_values(name, number, type, low, high, msgnum)
  values ("nested triggers", 115, 'C', 0, 1, 17029)
insert spt_values(name, number, type, low, high, msgnum)
  values ("devices", 116, 'C', 4, 256, 17030)
insert spt_values(name, number, type, low, high, msgnum)
  values ("remote access", 117, 'C', 0, 1, 17031)
insert spt_values(name, number, type, low, high, msgnum)
  values ("remote logins", 118, 'C', 0, 2147483647, 17032)
go
insert spt_values(name, number, type, low, high, msgnum)
  values ("remote sites", 119, 'C', 0, 2147483647, 17033)
insert spt_values(name, number, type, low, high, msgnum)
  values ("remote connections", 120, 'C', 0, 2147483647, 17034)
insert spt_values(name, number, type, low, high, msgnum)
  values ("pre-read packets", 121, 'C', 0, 2147483647, 17035)
insert spt_values(name, number, type, low, high, msgnum)
  values ("upgrade version", 122, 'C', 0, 2147483647, 17036)
insert spt_values(name, number, type, low, high, msgnum)
  values ("default sortorder id", 123, 'C', 0, 255, 17037)
insert spt_values(name, number, type, low, high, msgnum)
  values ("default language", 124, 'C', 0, 2147483647, 17038)
insert spt_values(name, number, type, low, high, msgnum)
  values ("language in cache", 125, 'C', 3, 100, 17039)
insert spt_values(name, number, type, low, high, msgnum)
  values ("max online engines", 126, 'C', 1, 32, 17040)
insert spt_values(name, number, type, low, high, msgnum)
  values ("min online engines", 127, 'C', 1, 32, 17041)
insert spt_values(name, number, type, low, high, msgnum)
  values ("engine adjust interval", 128, 'C', 1, 32, 17042)
go
insert spt_values(name, number, type, low, high, msgnum)
	values ("cpu flush", 129, 'C', 1, 2147483647, 17043)
insert spt_values(name, number, type, low, high, msgnum)
	values ("i/o flush", 130, 'C', 1, 2147483647, 17044)
insert spt_values(name, number, type, low, high, msgnum)
  values ("default character set id", 131, 'C', 0, 255, 17045)
/* 132 is reserved by the 4.9 group; with msgnum = 17046 */
insert spt_values(name, number, type, low, high, msgnum)
  values ("stack size", 134, 'C', 20480, 2147483647, 17046)
insert spt_values(name, number, type, low, high, msgnum)
	values ("password expiration interval", 135, 'C', 0, 32767, 17047)
insert spt_values(name, number, type, low, high, msgnum)
	values ("audit queue size", 136, 'C', 1, 65535, 17048)
insert spt_values(name, number, type, low, high, msgnum)
        values ("additional netmem", 137, 'C', 0, 2147483647, 17064)
insert spt_values(name, number, type, low, high, msgnum)
        values ("default network packet size", 138, 'C', 512, 524288, 17065)
insert spt_values(name, number, type, low, high, msgnum)
        values ("maximum network packet size", 139, 'C', 512, 524288, 17066)
insert spt_values(name, number, type, low, high, msgnum)
        values ("extent i/o buffers", 140, 'C', 0, 2147483647, 17067)
insert spt_values(name, number, type, low, high, msgnum)
        values ("identity burning set factor", 141, 'C', 1, 9999999, 17068)
insert spt_values(name, number, type, low, high, msgnum)
        values ("size of auto identity", 142, 'C', 1, 38, 17143)
insert spt_values(name, number, type, low, high, msgnum)
        values ("identity grab size", 143, 'C', 0, 2147483647, 17146)
insert spt_values(name, number, type, low, high, msgnum)
        values ("lock promotion threshold", 144, 'C', 200, 2147483647, 17147)
go

/*
** Entering the password complexity/login option values.
*/
insert spt_values(name, number, type, low, high, msgnum)
	values ("disallow simple passwords", 201, 'PC', 0, 1, 19425)
insert spt_values(name, number, type, low, high, msgnum)
	values ("min digits in password", 202, 'PC', -1, 16, 19426)
insert spt_values(name, number, type, low, high, msgnum)
	values ("min alpha in password", 203, 'PC', -1, 16, 19427)
insert spt_values(name, number, type, low, high, msgnum)
	values ("min special char in password", 204, 'PC', -1, 16, 19430)
insert spt_values(name, number, type, low, high, msgnum)
	values ("min upper char in password", 205, 'PC', -1, 16, 19428)
insert spt_values(name, number, type, low, high, msgnum)
	values ("min lower char in password", 206, 'PC', -1, 16, 19429)
insert spt_values(name, number, type, low, high, msgnum)
	 values ("password exp warn interval", 207, 'PC', 0, 365, 19431)
insert spt_values(name, number, type, low, high, msgnum)
	values ("password expiration", 208, 'PC', 0, 32767, 10472)
insert spt_values(name, number, type, low, high, msgnum)
	 values ("minimum password length", 209, 'PC', 0, 30, 10698)
insert spt_values(name, number, type, low, high, msgnum)
	values ("maximum failed logins", 210, 'PC', -1, 32767, 10697)
insert spt_values(name, number, type, low, high, msgnum)
	values ("expire login", 211, 'PC', 0, 1, 19432)
go

/* Entering "enable last login updates" value. */
insert spt_values(name, number, type, low, high, msgnum)
	values ("enable last login updates", 1, 'LG', 0, 1, 19635)
go

/* Entering "allow password downgrade" value. */
insert spt_values(name, number, type, low, high, msgnum)
	values ("allow password downgrade", 1, 'PT', 0, 1, 19636)
go

/*
** These values translate sysobjects.objaudflags, sysdatabases.deftabaud,
** sysdatabases.defviewaud, and sysdatabases.defpraud column bits into the
** actual text description of the bits.
*/
insert spt_values (name, number, type) values ("OBJECT/SPROC/TRIGGER", -1, "M")
insert spt_values (name, number, type) values ("successful deletes", 1, "M")
insert spt_values (name, number, type) values ("failed deletes", 2, "M")
insert spt_values (name, number, type) values ("successful updates", 4, "M")
insert spt_values (name, number, type) values ("failed updates", 8, "M")
insert spt_values (name, number, type) values ("successful selects", 16, "M")
insert spt_values (name, number, type) values ("failed selects", 32, "M")
insert spt_values (name, number, type) values ("successful inserts", 64, "M")
insert spt_values (name, number, type) values ("failed inserts", 128, "M")

insert spt_values (name, number, type) values
	("successful sproc/trigger", 256, "M")
insert spt_values (name, number, type) values
	("failed sproc/trigger", 512, "M")


go

/* These values translate sysdatabases.dbaudflags bits into text. */

insert spt_values (name, number, type) values ("DATABASE AUDITING", -1, "Q")
insert spt_values (name, number, type) values ("successful drop", 1, "Q")
insert spt_values (name, number, type) values ("failed drop", 2, "Q")
insert spt_values (name, number, type) values ("successful use", 4, "Q")
insert spt_values (name, number, type) values ("failed use", 8, "Q")
insert spt_values (name, number, type) values
	("successful outside access", 16, "Q")
insert spt_values (name, number, type) values ("failed outside access", 32, "Q")
insert spt_values (name, number, type) values ("successful grant", 64, "Q")
insert spt_values (name, number, type) values ("failed grant", 128, "Q")
insert spt_values (name, number, type) values ("successful revoke", 256, "Q")
insert spt_values (name, number, type) values ("failed revoke", 512, "Q")
insert spt_values (name, number, type) values ("successful truncate", 1024, "Q")
insert spt_values (name, number, type) values ("failed truncate", 2048, "Q")

insert spt_values (name, number, type) values ("successful remove", 16384, "Q")
insert spt_values (name, number, type) values ("failed remove", 32768, "Q")
go

/* These values translate syslogins.lgaudflags bits into text. */

insert spt_values (name, number, type) values ("LOGIN AUDITING", -1, "U")
insert spt_values (name, number, type) values ("successful table ref", 1, "U")
insert spt_values (name, number, type) values ("failed table ref", 2, "U")
insert spt_values (name, number, type) values ("successful view ref", 4, "U")
insert spt_values (name, number, type) values ("failed view ref", 8, "U")
insert spt_values (name, number, type) values ("command batch text", 16, "U")
go

/*
** These values are for sp_audit stored procedure.
** "Zs" are the valid settings.
** "Zu" are user specific audit options, they correspond to the AULG_
** defines in audit.h.
** "Zd" are database specific audit options, they correspond to the
** AUDB_ defines in audit.h.
** "Zo" are object specific audit options, they correspond to the
** AUOB_ for tables and views, AUPR_ for stored procedures, and 
** AUTR_ for triggers in audit.h.
** For the audit options which have both "pass" and "fail" settings,
** only the bit position for the "pass" have entries. The corresponding
** "fail" bit is gotten by multiplying by 2, and the "both" bits is
** gotten by multiplying by 3.
*/

insert spt_values (name, number, type) values ("off", 0, "Zs")
insert spt_values (name, number, type) values ("pass", 1, "Zs")
insert spt_values (name, number, type) values ("fail", 2, "Zs")
insert spt_values (name, number, type) values ("on", 3, "Zs")
insert spt_values (name, number, type)
  values ("table_access", hextoint("0x00000001"), "Zu") /* syslogins */
insert spt_values (name, number, type)
  values ("view_access", hextoint("0x00000004"), "Zu") /* syslogins */
insert spt_values (name, number, type)
  values ("cmdtext", hextoint("0x00000010"), "Zu") /* syslogins */
insert spt_values (name, number, type)
  values ("all", hextoint("0x00000040"), "Zu") /* syslogins */
insert spt_values (name, number, type)
  values ("drop", hextoint("0x00000001"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("dbaccess", hextoint("0x00000004"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("grant", hextoint("0x00000040"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("revoke", hextoint("0x00000100"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("truncate", hextoint("0x00000400"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("alter", hextoint("0x00001000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("bind", hextoint("0x00004000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("unbind", hextoint("0x00010000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("create", hextoint("0x00040000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("bcp", hextoint("0x00100000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("dump", hextoint("0x00400000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("load", hextoint("0x01000000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("setuser", hextoint("0x04000000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("func_dbaccess", hextoint("0x10000000"), "Zd") /* sysdatabases */

insert spt_values (name, number, type)
  values ("delete", hextoint("0x00000001"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("update", hextoint("0x00000004"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("select", hextoint("0x00000010"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("insert", hextoint("0x00000040"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("exec_procedure", hextoint("0x00000100"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("trusted_exec_procedure", hextoint("0x00000400"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("exec_trigger", hextoint("0x00001000"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("trusted_exec_trigger", hextoint("0x00004000"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("func_obj_access", hextoint("0x00010000"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("install", hextoint("0x00000010"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("remove", hextoint("0x40000000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("reference", hextoint("0x00040000"), "Zo") /* sysobjects */
insert spt_values (name, number, type)
  values ("encryption_key", hextoint("0x40000000"), "Zd") /* sysdatabases */
insert spt_values (name, number, type)
  values ("transfer_table", hextoint("0x00100000"), "Zo") /* sysobjects */
go

/* Token values */
insert spt_values(name, number, type)
  values ("TOKEN VALUES", -1, 'T')
insert spt_values(name, number, type)
  values ("References", 151, 'T')
insert spt_values(name, number, type)
  values ("Set Proxy", 167, 'T')
insert spt_values(name, number, type)
  values ("Update", 197, 'T')
insert spt_values(name, number, type)
  values ("Delete", 196, 'T')
insert spt_values(name, number, type)
  values ("Select", 193, 'T')
insert spt_values(name, number, type)
  values ("Insert", 195, 'T')
insert spt_values(name, number, type)
  values ("Execute", 224, 'T')
insert spt_values(name, number, type)
  values ("Grant", 205, 'T')
insert spt_values(name, number, type)
  values ("Revoke", 206, 'T')
go
insert spt_values(name, number, type)
  values ("Create Database", 203, 'T')
insert spt_values(name, number, type)
  values ("Create Default", 233, 'T')
insert spt_values(name, number, type)
  values ("Create Trigger", 221, 'T')
insert spt_values(name, number, type)
  values ("Create Procedure", 222, 'T')
insert spt_values(name, number, type)
  values ("Create Rule", 236, 'T')
insert spt_values(name, number, type)
  values ("Create Table", 198, 'T')
insert spt_values(name, number, type)
  values ("Create View", 207, 'T')
insert spt_values(name, number, type)
  values ("Dump Database", 228, 'T')
insert spt_values(name, number, type)
  values ("Dump Transaction", 235, 'T')
insert spt_values(name, number, type)
  values ("DBCC", 317, 'T')
insert spt_values(name, number, type)
  values ("Truncate Table", 320, 'T')
insert spt_values(name, number, type)
  values ("Update Statistics", 326, 'T')
insert spt_values(name, number, type)
  values ("Decrypt", 353, 'T')
insert spt_values(name, number, type)
  values ("Create Encryption Key", 354, 'T')
insert spt_values(name, number, type)
  values ("Alter Encryption Key", 355, 'T')
insert spt_values(name, number, type)
  values ("Transfer Table", 368, 'T')
insert spt_values(name, number, type)
  values ("Delete Statistics", 282, 'T')
go

/* Values for systransactions.state */
insert spt_values(name, number, type) values ("State", -1, 'T1')
insert spt_values(name, number, type) values ("Begun", 1, 'T1')
insert spt_values(name, number, type) values ("In Command", 5, 'T1')
insert spt_values(name, number, type) values ("Done Command", 2, 'T1')
insert spt_values(name, number, type) values ("In Abort Cmd", 6, 'T1')
insert spt_values(name, number, type) values ("Prepared", 4, 'T1')
insert spt_values(name, number, type) values ("Committed", 7, 'T1')
insert spt_values(name, number, type) values ("In Post Commit", 8, 'T1')
insert spt_values(name, number, type) values ("In Abort Tran", 9, 'T1')
insert spt_values(name, number, type) values ("In Abort Savept", 10, 'T1')
insert spt_values(name, number, type) values ("Done", 3, 'T1')
insert spt_values(name, number, type) values ("Begun-Detached", (65536 | 1), 'T1')
insert spt_values(name, number, type) values ("Done Cmd-Detached", (65536 | 2), 'T1')
insert spt_values(name, number, type) values ("Prepared-Detached", (65536 | 4), 'T1')
insert spt_values(name, number, type) values ("Done-Detached", (65536 | 3), 'T1')
insert spt_values(name, number, type) values ("Pseudo Prepared", (65536 | 11), 'T1')
insert spt_values(name, number, type) values ("Heur Committed", (65536 | 12), 'T1')
insert spt_values(name, number, type) values ("Heur Rolledback", (65536 | 13), 'T1')
go

/* Values for systransactions.status */
insert spt_values(name, number, type) values ("Status", -1, 'T2')
insert spt_values(name, number, type) values ("Attached", 1, 'T2')
insert spt_values(name, number, type) values ("Detached", 2, 'T2')
insert spt_values(name, number, type) values ("NA", 3, 'T2')
go

/* Values for systransactions.type */
insert spt_values(name, number, type) values ("Type", -1, 'T3')
insert spt_values(name, number, type) values ("Local", 1, 'T3')
insert spt_values(name, number, type) values ("Internal", 2, 'T3')
insert spt_values(name, number, type) values ("External", 3, 'T3')
insert spt_values(name, number, type) values ("Subordinate", 4, 'T3')
insert spt_values(name, number, type) values ("Dtx_State", 98, 'T3')
insert spt_values(name, number, type) values ("Remote", 99, 'T3')
go

/* Values for systransactions.coordinator */
insert spt_values(name, number, type)
  values ("Coordinator", -1, 'T4')
insert spt_values(name, number, type)
  values ("None", 0, 'T4')
insert spt_values(name, number, type)
  values ("Syb2PC", 1, 'T4')
insert spt_values(name, number, type)
  values ("ASTC", 2, 'T4')
insert spt_values(name, number, type)
  values ("XA", 3, 'T4')
insert spt_values(name, number, type)
  values ("DTC", 4, 'T4')
insert spt_values(name, number, type)
  values ("OTS", 5, 'T4')
go

/* Values for systransactions.failover */
insert spt_values(name, number, type) values ("Resident Tx",   0, 'T5')
insert spt_values(name, number, type) values ("Failed-over Tx", 1, 'T5')
insert spt_values(name, number, type) values ("Tx by Failover-Conn", 2, 'T5')
go

/* Values for syslocks.type */
insert spt_values(name, number, type)
  values ("LOCK TYPES", -1, 'L')
insert spt_values(name, number, type)
  values ("Ex_table", 1, 'L')
insert spt_values(name, number, type)
  values ("Sh_table", 2, 'L')
insert spt_values(name, number, type)
  values ("Ex_intent", 3, 'L')
insert spt_values(name, number, type)
  values ("Sh_intent", 4, 'L')
insert spt_values(name, number, type)
  values ("Ex_page", 5, 'L')
insert spt_values(name, number, type)
  values ("Sh_page", 6, 'L')
insert spt_values(name, number, type)
  values ("Update_page", 7, 'L')
insert spt_values(name, number, type)
  values ("Ex_row", 8, 'L')
insert spt_values(name, number, type)
  values ("Sh_row", 9, 'L')
insert spt_values(name, number, type)
  values ("Update_row", 10, 'L')
insert spt_values(name, number, type)
  values ("Sh_nextkey", 11, 'L')
go
insert spt_values(name, number, type)
  values ("Ex_table-blk", 256+1, 'L')
insert spt_values(name, number, type)
  values ("Sh_table-blk", 256+2, 'L')
insert spt_values(name, number, type)
  values ("Ex_intent-blk", 256+3, 'L')
insert spt_values(name, number, type)
  values ("Sh_intent-blk", 256+4, 'L')
insert spt_values(name, number, type)
  values ("Ex_page-blk", 256+5, 'L')
insert spt_values(name, number, type)
  values ("Sh_page-blk", 256+6, 'L')
insert spt_values(name, number, type)
  values ("Update_page-blk", 256+7, 'L')
insert spt_values(name, number, type)
  values ("Ex_row-blk", 256+8, 'L')
insert spt_values(name, number, type)
  values ("Sh_row-blk", 256+9, 'L')
insert spt_values(name, number, type)
  values ("Update_row-blk", 256+10, 'L')
insert spt_values(name, number, type)
  values ("Sh_nextkey-blk", 256+11, 'L')
go
insert spt_values(name, number, type)
  values ("Ex_table-demand", 512+1, 'L')
insert spt_values(name, number, type)
  values ("Sh_table-demand", 512+2, 'L')
insert spt_values(name, number, type)
  values ("Ex_intent-demand", 512+3, 'L')
insert spt_values(name, number, type)
  values ("Sh_intent-demand", 512+4, 'L')
insert spt_values(name, number, type)
  values ("Ex_page-demand", 512+5, 'L')
insert spt_values(name, number, type)
  values ("Sh_page-demand", 512+6, 'L')
insert spt_values(name, number, type)
  values ("Update_page-demand", 512+7, 'L')
insert spt_values(name, number, type)
  values ("Ex_row-demand", 512+8, 'L')
insert spt_values(name, number, type)
  values ("Sh_row-demand", 512+9, 'L')
insert spt_values(name, number, type)
  values ("Update_row-demand", 512+10, 'L')
insert spt_values(name, number, type)
  values ("Sh_nextkey-demand", 512+11, 'L')
go
insert spt_values(name, number, type)
  values ("Ex_table-demand-blk", 512+256+1, 'L')
insert spt_values(name, number, type)
  values ("Sh_table-demand-blk", 512+256+2, 'L')
insert spt_values(name, number, type)
  values ("Ex_intent-demand-blk", 512+256+3, 'L')
insert spt_values(name, number, type)
  values ("Sh_intent-demand-blk", 512+256+4, 'L')
insert spt_values(name, number, type)
  values ("Ex_page-demand-blk", 512+256+5, 'L')
insert spt_values(name, number, type)
  values ("Sh_page-demand-blk", 512+256+6, 'L')
insert spt_values(name, number, type)
  values ("Update_page-demand-blk", 512+256+7, 'L')
insert spt_values(name, number, type)
  values ("Ex_row-demand-blk", 512+256+8, 'L')
insert spt_values(name, number, type)
  values ("Sh_row-demand-blk", 512+256+9, 'L')
insert spt_values(name, number, type)
  values ("Update_row-demand-blk", 512+256+10, 'L')
insert spt_values(name, number, type)
  values ("Sh_nextkey-demand-blk", 512+256+11, 'L')
go
insert spt_values(name, number, type)
  values ("Ex_table-request", 1024+1, 'L')
insert spt_values(name, number, type)
  values ("Sh_table-request", 1024+2, 'L')
insert spt_values(name, number, type)
  values ("Ex_intent-request", 1024+3, 'L')
insert spt_values(name, number, type)
  values ("Sh_intent-request", 1024+4, 'L')
insert spt_values(name, number, type)
  values ("Ex_page-request", 1024+5, 'L')
insert spt_values(name, number, type)
  values ("Sh_page-request", 1024+6, 'L')
insert spt_values(name, number, type)
  values ("Update_page-request", 1024+7, 'L')
insert spt_values(name, number, type)
  values ("Ex_row-request", 1024+8, 'L')
insert spt_values(name, number, type)
  values ("Sh_row-request", 1024+9, 'L')
insert spt_values(name, number, type)
  values ("Update_row-request", 1024+10, 'L')
insert spt_values(name, number, type)
  values ("Sh_nextkey-request", 1024+11, 'L')
go
insert spt_values(name, number, type)
  values ("Ex_table-demand-request", 1024+512+1, 'L')
insert spt_values(name, number, type)
  values ("Sh_table-demand-request", 1024+512+2, 'L')
insert spt_values(name, number, type)
  values ("Ex_intent-demand-request", 1024+512+3, 'L')
insert spt_values(name, number, type)
  values ("Sh_intent-demand-request", 1024+512+4, 'L')
insert spt_values(name, number, type)
  values ("Ex_page-demand-request", 1024+512+5, 'L')
insert spt_values(name, number, type)
  values ("Sh_page-demand-request", 1024+512+6, 'L')
insert spt_values(name, number, type)
  values ("Update_page-demand-request", 1024+512+7, 'L')
insert spt_values(name, number, type)
  values ("Ex_row-demand-request", 1024+512+8, 'L')
insert spt_values(name, number, type)
  values ("Sh_row-demand-request", 1024+512+9, 'L')
insert spt_values(name, number, type)
  values ("Update_row-demand-request", 1024+512+10, 'L')
insert spt_values(name, number, type)
  values ("Sh_nextkey-demand-request", 1024+512+11, 'L')
go

/* Values for syslocks.context */
insert spt_values(name, number, type)
  values ("LOCK CONTEXT VALUES", 2048, "L2")

/* No context bits turned on */
insert spt_values(name, number, type)
  values ("", 2049, "L2")

insert spt_values(name, number, type)
  values ("Fam dur", 2049+1, 'L2')

insert spt_values(name, number, type)
  values ("Range", 2049+2, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Range", 2049+2+1, 'L2')

insert spt_values(name, number, type)
  values ("Inf key", 2049+4, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Inf key", 2049+4+1, 'L2')

insert spt_values(name, number, type)
  values ("Inf key", 2049+4+2, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Inf key", 2049+4+2+1, 'L2')

insert spt_values(name, number, type)
  values ("Ind pg", 2049+8, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Ind pg", 2049+8+1, 'L2')

insert spt_values(name, number, type)
  values ("Ind pg, Range", 2049+8+2, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Ind pg, Range", 2049+8+2+1, 'L2')

insert spt_values(name, number, type)
  values ("Ind pg, Inf key", 2049+8+4, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Ind pg, Inf key", 2049+8+4+1, 'L2')

insert spt_values(name, number, type)
  values ("Ind pg, Inf key", 2049+8+4+2, 'L2')

insert spt_values(name, number, type)
  values ("Fam dur, Ind pg, Inf key", 2049+8+4+2+1, 'L2')

/* The delete bit is not exposed to the user */
insert spt_values(name, number, type)
  values ("Delete", 2049+16, 'L2')
go

/*
**  These values define the status bits in sysindexes.
*/
insert spt_values (name, number, type)
	values ("INDEX TYPES", -1, "I")
insert spt_values (name, number, type)
	values ("nonclustered", 0, "I")
insert spt_values (name, number, type)
	values ("ignore duplicate keys", 1, "I")
insert spt_values (name, number, type)
	values ("unique", 2, "I")
insert spt_values (name, number, type)
	values ("ignore duplicate rows", 4, "I")
insert spt_values (name, number, type)
	values ("clustered", 16, "I")
insert spt_values (name, number, type)
	values ("allow duplicate rows", 64, "I")
go

/*
**  These values define the ptntype in syspartitions.
*/
insert spt_values (name, number, type)
	values ("PARTITION TYPES", -1, "PN")
insert spt_values (name, number, type)
	values ("range", 1, "PN")
insert spt_values (name, number, type)
	values ("hash", 2, "PN")
insert spt_values (name, number, type)
	values ("roundrobin", 3, "PN")
insert spt_values (name, number, type)
	values ("list", 4, "PN")
go

/*
**  These values define the object type.  The number made from the low
**  4 bits in sysobjects.sysstats indicate the type of object.
**	
** 
** Be sure to add new message values in a_messages
*/
insert spt_values (name, number, type)
	values ("OBJECT TYPES", -1, "O")
insert spt_values (name, number, type, msgnum)
	values ("system table", 1, "O", 17101)
insert spt_values (name, number, type, msgnum)
	values ("view", 2, "O", 17102)
insert spt_values (name, number, type, msgnum)
	values ("user table", 3, "O", 17103)
insert spt_values (name, number, type, msgnum)
	values ("stored procedure",4, "O", 17104)
/* no number 5 */
insert spt_values (name, number, type, msgnum)
	values ("default", 6, "O", 17105)
insert spt_values (name, number, type, msgnum)
	values ("rule", 7, "O", 17106)
insert spt_values (name, number, type, msgnum)
	values ("trigger", 8, "O", 17100)
insert spt_values (name, number, type, msgnum)
	values ("referential constraint", 9, "O", 17140)
insert spt_values (name, number, type, msgnum)
	values ("SQL function", 10, "O", 17139)
insert spt_values (name, number, type, msgnum)
	values ("stored procedure (ext)", 4, "O1", 17107)
insert spt_values (name, number, type, msgnum)
	values ("SQLJ function", 12, "O", 18903)
insert spt_values (name, number, type, msgnum)
	values ("computed column", 13, "O", 17589)
insert spt_values (name, number, type, msgnum)
	values ("SQLJ procedure", 4, "O2", 18904)
insert spt_values (name, number, type, msgnum)
	values ("partition condition", 14, "O", 17587)
insert spt_values (name, number, type, msgnum)
	values ("virtually hashed table", 128, "O2", 19585)

go

/*
** These values define status bits in sysobjects.sysstat3.
*/
insert spt_values (name, number, type)
	values ("OBJECT STATUS3", -1, "O3")
insert spt_values (name, number, type, msgnum)
	values ("full dml logging", 1, "O3", 19992)
insert spt_values (name, number, type, msgnum)
	values ("minimal dml logging", 2, "O3", 19993)
insert spt_values (name, number, type, msgnum)
	values ("incremental transfer on", 32768, "O3", 19994)
go

/*
**  These values translate the object type's userstat bits.  If the high
**  bit is set for a sproc, then it's a report.
*/
insert spt_values (name, number, type)
	values ("REPORT TYPES", -1, "R")
insert spt_values (name, number, type)
	values ("", 0, "R")
insert spt_values (name, number, type)
	values (" (rpt)", -32768, "R")
go

/*
**  Database status bits.
**  NB -- If you add a bit here make sure you add the value to the value
**	of the ALL SETTABLE option if the user can set it.
** 
** Be sure to add new message values in a_messages
*/
insert spt_values (name, number, type)
	values ("DATABASE STATUS", -1, "D")
insert spt_values (name, number, type, msgnum)
	values ("failed upgrade", 1, "D", 17061)
insert spt_values (name, number, type, msgnum)
	values ("select into/bulkcopy/pllsort", 4, "D", 17050)
insert spt_values (name, number, type, msgnum)
	values ("trunc log on chkpt", 8, "D", 17051)
insert spt_values (name, number, type, msgnum)
	values ("trunc. log on chkpt.", 8, "D", 17051)
insert spt_values (name, number, type, msgnum)
	values ("no chkpt on recovery", 16, "D", 17052)
insert spt_values (name, number, type, msgnum)
	values ("don't recover", 32, "D", 17053)
insert spt_values (name, number, type, msgnum)
	values ("not recovered", 256, "D", 17054)
insert spt_values (name, number, type, msgnum)
	values ("ddl in tran", 512, "D", 17055)
insert spt_values (name, number, type, msgnum)
	values ("read only", 1024, "D", 17056)
insert spt_values (name, number, type, msgnum)
	values ("dbo use only", 2048, "D", 17057)
go
insert spt_values (name, number, type, msgnum)
	values ("single user", 4096, "D", 17058)
insert spt_values (name, number, type, msgnum)
	values ("inconsistent security label", 16384, "D", 17060)
insert spt_values (name, number, type, msgnum)
	values ("allow nulls by default", 8192, "D", 17069)
insert spt_values (name, number, type, msgnum)
	values ("ALL SETTABLE OPTIONS", 15900, "D", 17059)
go

/*
** More database options.
** We ran out of status bits for spt_values.type = "D".  Thus,
** the type field is now char(2), and these entries describe
** the status2 options.
*/
insert spt_values (name, number, type, msgnum)
	values ("ALL SETTABLE OPTIONS", 79, "D2", 17059)
insert spt_values (name, number, type, msgnum)
	values ("abort tran on log full", 1, "D2", 17062)
insert spt_values (name, number, type, msgnum)
	values ("no free space acctg", 2, "D2", 17063)
insert spt_values (name, number, type, msgnum)
	values ("auto identity", 4, "D2", 17145)
insert spt_values (name, number, type, msgnum)
	values ("identity in nonunique index", 8, "D2", 17144)
insert spt_values (name, number, type, msgnum)
	values ("offline", 16, "D2", 17594)
insert spt_values (name, number, type, msgnum)
	values ("unique auto_identity index", 64, "D2", 17437)
insert spt_values (name, number, type, msgnum)
	values ("has suspect pages/objects", 128, "D2", 17596)
insert spt_values (name, number, type, msgnum)
	values ("online for standby access", 1024, "D2", 17595)
insert spt_values (name, number, type, msgnum)
	values ("mixed log and data", 32768, "D2", 17601)
go

/*
** Sysdatabases.statu3 options.
**  NB -- If you add a bit here make sure you add the value to the value
**	of the ALL SETTABLE option if the user can set it.
*/
insert spt_values (name, number, type, msgnum)
	values ("ALL SETTABLE OPTIONS",  16780288, "D3", 17059)
insert spt_values (name, number, type, msgnum)
	values ("quiesce database", 128, "D3", 17597)

insert spt_values (name, number, type, msgnum)
	values ("async log service", 1024, "D3", 18982)
insert spt_values (name, number, type, msgnum)
	values ("delayed commit", 2048, "D3", 17602)
insert spt_values (name, number, type, msgnum)
	values ("archive database", 4194304, "D3", 17603)
insert spt_values (name, number, type, msgnum)
	values ("compressed data", 8388608, "D3", 17604)
insert spt_values (name, number, type, msgnum)
	values ("scratch database", 16777216, "D3", 19423)
insert spt_values (name, number, type, msgnum)
	values ("compressed log", 134217728, "D3", 17605)
if @@clustermode != "shared disk cluster"
begin
	insert spt_values (name, number, type, msgnum)
		values ("user created temp db", 256, "D3", 17599)
	insert spt_values (name, number, type)
		values ("TEMPDB STATUS MASK", 256, "D3")
end
else
begin
	insert spt_values (name, number, type, msgnum)
		values ("local user temp db", 256, "D3", 17606)
	insert spt_values (name, number, type, msgnum)
		values ("local system temp db", 536870912, "D3", 17607)
	insert spt_values (name, number, type, msgnum)                
		values ("global user temp db", 1073741824, "D3", 17608)
	insert spt_values (name, number, type)
		values ("TEMPDB STATUS MASK", 1610612992, "D3")
	insert spt_values (name, number, type)
		values ("LOCAL TEMPDB STATUS MASK", 536871168, "D3")
end

/*
** Sysdatabases.statu4 options.
**  NB -- If you add a bit here make sure you add the value to the value
**	of the ALL SETTABLE option if the user can set it.
*/
insert spt_values (name, number, type, msgnum)
	values ("ALL SETTABLE OPTIONS", 0, "D4", 17059)
insert spt_values (name, number, type, msgnum)
	values ("minimal dml logging", 256, "D4", 19993)
insert spt_values (name, number, type, msgnum)
	values ("template database", 1024, "D4", 19984)
insert spt_values (name, number, type, msgnum)
	values ("in-memory database", 4096, "D4", 19983)
/*
**  Yes or no.
** 
** Be sure to add new message values in a_messages
*/
insert spt_values (name, number, type)
	values ("YES OR NO", -1, "B")
insert spt_values (name, number, type, msgnum)
	values ("no", 0, "B", 17010)
insert spt_values (name, number, type, msgnum)
	values ("yes", 1, "B", 17011)
go

/*
**  Status bits in syscolumns.status2
**
** Be sure to add new message values in a_messages
*/

insert spt_values (name, number, type, msgnum)
        values ("in", 1, 'C2', 17583)
insert spt_values (name, number, type, msgnum)
        values ("out", 2, 'C2', 17584)
insert spt_values (name, number, type, msgnum)
        values ("inout", 4, 'C2', 17585)
insert spt_values (name, number, type, msgnum)
        values ("return type", 8, 'C2', 17586)

/*
**  Status bits in sysservers
** 
** Be sure to add new message values in a_messages and
** to update the procedure sp_serveroption to check
** for the appropriate role.
*/
insert spt_values (name, number, type)
	values ("SYSSERVERS TYPES", -1, "A")
insert spt_values (name, number, type, msgnum)
	values ("timeouts", 0, "A", 17000)
insert spt_values (name, number, type, msgnum)
	values ("no timeouts", 1, "A", 17001)
insert spt_values (name, number, type, msgnum)
        values ("net password encryption", 2, "A", 17002)
insert spt_values (name, number, type, msgnum)
	values ("readonly", 4, "A", 17148)
insert spt_values (name, number, type, msgnum)
        values ("rpc security model A", 8, "A", 17003)
insert spt_values (name, number, type, msgnum)
        values ("rpc security model B", 16, "A", 17004)
insert spt_values (name, number, type)
	values ("cis hafailover", 32, "A")
go
insert spt_values (name, number, type, msgnum)
        values ("use message confidentiality", 64, "A", 17006)
insert spt_values (name, number, type, msgnum)
        values ("use message integrity", 128, "A", 17007)
insert spt_values (name, number, type, msgnum)
        values ("mutual authentication", 256, "A", 17008)
insert spt_values (name, number, type, msgnum)
	values ("server logins", 512, "A", 17009)
insert spt_values (name, number, type)
        values  ("external engine auto start", 1024, "A")
go
--
-- insert spt_values (name, number, type)
--         values  ("uses ssl", 2048, "A")
--
insert spt_values (name, number, type)
	values ("negotiated logins", 4096, "A")
insert spt_values (name, number, type)
	values ("enable login redirection", 2, "A2")
if @@clustermode = "shared disk cluster"
begin
	insert spt_values (name, number, type)
		values ("cluster instance", 4, "A2")
end
go

insert spt_values (name, number, type)
	values ("relocated joins", 1, "A2")
insert spt_values (name, number, type)
	values ("incompatible sort order", 8, "A2")
go

/*
**  Status bits in sysremotelogins
** 
** Be sure to add new message values in a_messages
*/
insert spt_values (name, number, type)
	values ("SYSREMOTELOGINS TYPES", -1, "F")
insert spt_values (name, number, type, msgnum)
	values ("-- none --", 0, "F", 17661)
insert spt_values (name, number, type, msgnum)
	values ("trusted", 1, "F", 17070)
go

/*
**  Translate syskeys.type to english.
*/
insert spt_values (name, number, type)
	values ("SYSKEYS TYPES", -1, "K")
insert spt_values (name, number, type)
	values ("primary", 1, "K")
insert spt_values (name, number, type)
	values ("foreign", 2, "K")
insert spt_values (name, number, type)
	values ("common", 3, "K")
go

/*
**  Translate sysdevices.status to english.
** 
** Be sure to add new message values in a_messages
*/
insert spt_values (name, number, type)
	values ("SYSDEVICES STATUS", -1, "V")
insert spt_values (name, number, type, msgnum)
	values ("default disk", 1, "V", 17120)
insert spt_values (name, number, type, msgnum)
	values ("physical disk", 2, "V", 17121)
insert spt_values (name, number, type, msgnum)
	values ("archive database disk", 4, "V", 17122)
insert spt_values (name, number, type, msgnum)
	values ("read-only", 8, "V", 17123)
insert spt_values (name, number, type, msgnum)
	values ("dump device", 16, "V", 17124)
insert spt_values (name, number, type, msgnum)
	values ("serial writes", 32, "V", 17125)
insert spt_values (name, number, type, msgnum)
	values ("device mirrored", 64, "V", 17126)
insert spt_values (name, number, type, msgnum)
	values ("reads mirrored", 128, "V", 17127)
insert spt_values (name, number, type, msgnum)
	values ("half-mirror only", 256, "V", 17128)
insert spt_values (name, number, type, msgnum)
	values ("mirror enabled", 512, "V", 17129)
go

insert spt_values (name, number, type)
	values ("SYSDEVICES STATUS2", -1, "V2")
insert spt_values (name, number, type, msgnum)
	values ("virtual cache device", 8, "V2", 17631)
/*
**  Translate @@options bit to english
**
**  These entries are used only by DB-Lib for
**  db{set,get}options commands
** 
** Be sure to add new message values in a_messages
** (Currently, the message number is not used 
** for options - type == 'N' - )
*/
insert spt_values (name, number, type)
        values ("OPTIONS BITS", -1, "N")
insert spt_values (name, number, type, msgnum)
        values ("errlvl 1", 1, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("errlvl 2", 2, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("errlvl 3", 3, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("showplan", 4, "N", 17080)
insert spt_values (name, number, type, msgnum)
        values ("noexec", 5, "N", 17081)
insert spt_values (name, number, type, msgnum)
        values ("arithignore", 6, "N", 17082)
insert spt_values (name, number, type, msgnum)
        values ("arithabort", 7, "N", 17083)
insert spt_values (name, number, type, msgnum)
        values ("numeric_truncation", 8, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("background", 9, "N", 17084)
insert spt_values (name, number, type, msgnum)
        values ("browse", 10, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("colnames", 11, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("format", 12, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("control", 13, "N", 17085)
insert spt_values (name, number, type, msgnum)
        values ("offsets", 14, "N", 17086)
insert spt_values (name, number, type, msgnum)
        values ("statistics io and time", 15, "N", 17087)
insert spt_values (name, number, type, msgnum)
        values ("parseonly", 16, "N", 17088)
insert spt_values (name, number, type, msgnum)
        values ("procid", 18, "N", 17089)
insert spt_values (name, number, type, msgnum)
        values ("rowcount", 20, "N", 17090)
insert spt_values (name, number, type, msgnum)
        values ("getdata", 21, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("altnames", 22, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("nocount", 23, "N", 17091)
insert spt_values (name, number, type, msgnum)
        values ("quoted_identifier", 24, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("forceplan", 25, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("fmtonly", 26, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("chained", 27, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("close on end tran", 29, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("fipsflagger", 30, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("resonly", 31, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("self_recursion", 32, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("ansinull", 33, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("dup_in_subquery", 34, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("or_strategy", 35, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("flushmessage", 36, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("ansi_permissions", 37, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("string_rtruncation", 38, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("prefetch", 40, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("triggers", 41, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("replication", 42, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("replication force_ddl", 43, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("process_limit_action warning", 44, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("process_limit_action abort", 45, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("sort_resources", 47, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("transactional_rpc", 48, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("cis_rpc_handling", 49, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("strict_dtm_enforcement", 50, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("raw_object_serialization", 51, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("textptr_parameters", 52, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("sort_merge", 54, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("jtc", 56, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("remote_indexes", 58, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("explicit_transaction_required", 59, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("bulk_insert_batch_size", 60, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("statement_cache", 62, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("command_status_reporting", 63, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("proc_return_status", 64, "N", 0)
insert spt_values (name, number, type, msgnum)
        values ("proc_output_params", 65, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("extended_syntax", 70, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("metrics_capture", 71, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("nodata", 72, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("dml_on_computed", 73, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("calibrate", 74, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("delayed_commit", 76, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("ciphertext", 80, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("export_options", 82, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("literal_autoparam", 84, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("show_sqltext", 85, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("timestamp insert", 86, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("repmode UPDATE", 87, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("repmode DELETE", 88, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("repmode INSERT SELECT", 89, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("repmode SELECT INTO", 90, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("repmode never", 91, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("repmode off", 92, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("compatibility_mode", 93, "N", 0)
insert spt_values (name, number, type, msgnum)
	values ("deferred_name_resolution", 97, "N", 0)

/*
**  Set the DataServer machine type
**  spt_values.low is the number of bytes in a DataServer page for the
**  particular DataServer machine.
*/
insert spt_values (name, number, type, low)
	values ("DATASERVER HOST TYPE", -1, "E", 0)
go

/*
**  List the physical types that are compatible.
*/
insert spt_values (name, number, type)
	values ("COMPATIBLE TYPES", -1, "J")
insert spt_values (name, number, low, type)
	values ("binary", 1, 45, "J")
insert spt_values (name, number, low, type)
	values ("varbinary", 1, 37, "J")
insert spt_values (name, number, low, type)
	values ("bit", 2, 50, "J")
insert spt_values (name, number, low, type)
	values ("char", 3, 47, "J")
insert spt_values (name, number, low, type)
	values ("varchar", 3, 39, "J")
insert spt_values (name, number, low, type)
	values ("datetime", 4, 61, "J")
insert spt_values (name, number, low, type)
	values ("datetimn", 4, 111, "J")
insert spt_values (name, number, low, type)
	values ("smalldatetime", 4, 58, "J")
insert spt_values (name, number, low, type)
	values ("bigdatetime", 4, 189, "J")
insert spt_values (name, number, low, type)
	values ("bigtime", 4, 190, "J")
insert spt_values (name, number, low, type)
	values ("bigdatetimen", 4, 187, "J")
insert spt_values (name, number, low, type)
	values ("bigtimen", 4, 188, "J")
insert spt_values (name, number, low, type)
	values ("date", 4, 49, "J")
insert spt_values (name, number, low, type)
	values ("daten", 4, 123, "J")
insert spt_values (name, number, low, type)
	values ("time", 4, 51, "J")
insert spt_values (name, number, low, type)
	values ("timen", 4, 147, "J")
insert spt_values (name, number, low, type)
	values ("float", 5, 62, "J")
go
insert spt_values (name, number, low, type)
	values ("floatn", 5, 109, "J")
insert spt_values (name, number, low, type)
	values ("real", 5, 59, "J")
insert spt_values (name, number, low, type)
	values ("int", 6, 56, "J")
insert spt_values (name, number, low, type)
	values ("intn", 6, 38, "J")
insert spt_values (name, number, low, type)
	values ("smallint", 6, 52, "J")
insert spt_values (name, number, low, type)
	values ("tinyint", 6, 48, "J")
insert spt_values (name, number, low, type)
	values ("money", 7, 60, "J")
insert spt_values (name, number, low, type)
	values ("moneyn", 7, 110, "J")
insert spt_values (name, number, low, type)
	values ("smallmoney", 7, 122, "J")
insert spt_values (name, number, low, type)
	values ("numeric", 8, 63, "J")
go
insert spt_values (name, number, low, type)
        values ("uint", 10, 66, "J")
insert spt_values (name, number, low, type)
        values ("uintn", 10, 68, "J")
insert spt_values (name, number, low, type)
        values ("usmallint", 10, 65, "J")
insert spt_values (name, number, low, type)
	values ("ubigint", 10, 67, "J")
insert spt_values (name, number, low, type)
        values ("bigint", 6, 191, "J")

insert spt_values (name, number, low, type)
	values ("numericn", 8, 108, "J")
insert spt_values (name, number, low, type)
	values ("decimal", 8, 55, "J")
insert spt_values (name, number, low, type)
	values ("decimaln", 8, 106, "J")
go
insert spt_values (name, number, low, type)
	values ("unichar", 9, 135, "J")
insert spt_values (name, number, low, type)
	values ("univarchar", 9, 155, "J")
go

/*
**  Add some text for sysusages.segmap.
** 
** Be sure to add new message values in a_messages
*/
insert into spt_values (name, type, number)
	values ('SYSUSAGES SEGMAP', 'S', -1)
insert into spt_values (name, type, number, msgnum)
	values ('data only', 'S', 0, 17110)
insert into spt_values (name, type, number, msgnum)
	values ('data only', 'S', 1, 17110)
insert into spt_values (name, type, number, msgnum)
	values ('data only', 'S', 2, 17110)
insert into spt_values (name, type, number, msgnum)
	values ('data only', 'S', 3, 17110)
insert into spt_values (name, type, number, msgnum)
	values ('log only', 'S', 4, 17111)
insert into spt_values (name, type, number, msgnum)
	values ('data and log', 'S', 5, 17112)
insert into spt_values (name, type, number, msgnum)
	values ('data and log', 'S', 6, 17112)
insert into spt_values (name, type, number, msgnum)
	values ('data and log', 'S', 7, 17112)
go

/*
** BEGIN OMNI ADDITIONS
*/
/*
**  Add some text for sysservers.srvclass
**  
** Low is set equal to the class's initial server status.  
** Zero indicates read/write mode.
*/
insert into spt_values (name, type, number)
	values ('SYSSERVERS.SRVCLASS', "X", -1)
insert into spt_values (name, type, number, low)
	values ('local', "X", 0, 0)
insert into spt_values (name, type, number, low)
	values ('sql_server', "X", 1, 0)
insert into spt_values (name, type, number, low)
	values ('access_server', "X", 3, 0)
insert into spt_values (name, type, number, low)
	values ('direct_connect', "X", 3, 0)
insert into spt_values (name, type, number, low)
	values ('sds', "X", 6, 0)
insert into spt_values (name, type, number, low)
	values ('ASEnterprise', "X", 7, 0)
insert into spt_values (name, type, number, low)
	values ('ASAnywhere', "X", 8, 0)
insert into spt_values (name, type, number, low)
	values ('ASIQ', "X", 9, 0)
insert into spt_values (name, type, number, low)
	values ('ASEJB', "X", 10, 0)
insert into spt_values (name, type, number, low)
	values ('RPCServer', "X", 11, 0)
insert into spt_values (name, type, number, low)
	values ('TIBCO_JMS', "X", 12, 0)
insert into spt_values (name, type, number, low)
	values ('IBM_MQ', "X", 13, 0)
insert into spt_values (name, type, number, low)
	values ('EAS_JMS', "X", 14, 0)
insert into spt_values (name, type, number, low)
	values ('SONICMQ_JMS', "X", 15, 0)
go
/*
** Add some text for syscolumns.remote_type.  These translate the third
** arg to sp_addobjectdefs into an integer type.
*/
insert into spt_values (name, type, number)
	values ('OBJECT DEFINITION TYPE', "Y", -1)
insert into spt_values (name, type, number)
	values ('table', "Y", 1)
insert into spt_values (name, type, number)
	values ('view', "Y", 1)
insert into spt_values (name, type, number)
	values ('directory', "Y", 2)
insert into spt_values (name, type, number)
	values ('rpc', "Y", 3)
insert into spt_values (name, type, number)
	values ('file', "Y", 4)
insert into spt_values (name, type, number)
	values ('function', "Y", 5)
insert into spt_values (name, type, number)
	values ('internal', "Y", 6)
go
/*
** Add the Omni Connect command
*/
insert spt_values(name, number, type)
  values ("Connect", 253, 'T')
go
/*
** END OMNI ADDITIONS
*/
/*
** Features supported on some platforms and not others.  low != 0 means
** supported.  Initialize to 0 here.  Each of these may be reset by platform.
*/
insert into spt_values (name, type, number, low)
	values ('PLATFORM FEATURES', 'G',-1, 0)
insert into spt_values (name, type, number, low, msgnum)
	values ('Channel Devices', 'G', 0, 0, 17075)
go

insert spt_values(name,number,type) values("Certified",1,"oc")
insert spt_values(name,number,type) values("Suspect",2,"oc")
insert spt_values(name,number,type) values("Uncertified",3,"oc")
go


/*
** Table/Index options used by stored procedure sp_chgattribute.
*/
insert into spt_values (name, number, type)
        values ('max_rows_per_page', 0, 'H')
insert into spt_values (name, number, type)
        values ('reservepagegap', 1, 'H')
insert into spt_values (name, number, type)
        values ('exp_row_size', 2, 'H')
insert into spt_values (name, number, type)
        values ('fillfactor', 3, 'H')
insert into spt_values (name, number, type)
        values ('concurrency_opt_threshold', 4, 'H')
insert into spt_values (name, number, type)
        values ('identity_gap', 5, 'H')
insert into spt_values (name, number, type)
	values ('optimistic_index_lock', 6, 'H')
insert into spt_values (name, number, type)
	values ('dealloc_first_txtpg', 7, 'H')
insert into spt_values (name, number, type)
	values ('identity_burn_max', 8, 'H')
insert into spt_values (name, number, type)
	values ('ascinserts', 9, 'H')
insert into spt_values (name, number, type) 
	values ('local_unique_index', 10, 'H')
insert into spt_values (name, number, type)
        values ('plldegree', 11, 'H')
go

/*
** Added for ASE HA server usage.
** This very first section is used to store names and IDs of supported
** cluster systems on ASE HA server.
**      name:   os_name(uname -s)|cluster_system_name-cluster_system_version
**
**              if os_name is 'General', then it can reside on multiple OSs.
**              if cluster_system_version is 'XX', it means version is not
**              meaningful or clear.
**      low:    Internal cluster system ID. This is harcoded and defined
**              in sql/generic/include/hasmgr.h as HA_CLUSTER_XXX. So this
**              has to be maintained manually to be consistent with those
**              macros.
**      number: starting from 0, as a new type 'ha'. This number should also
**              less than 1000. Numbers greater than 1000 are left for other
**              HA related values.
**      type:   Claim a new type 'ha'
**
**  Note: Commenting some Cluster platforms as they are no longer
**	  supported from ASE15.0. Not removing these lines to retain
**	  the history of the cluster system id values (of 'low').
**
** insert into spt_values(name, low, number, type)
**        values ("SunOS|SC-2.2", 0, 0, "ha")
** insert into spt_values(name, low, number, type)
**        values ("SunOS|VCS-Sybase", 5, 5, "ha")
** insert into spt_values(name, low, number, type)
**        values ("NT|VCS-1.3.0", 6, 6, "ha")
** insert into spt_values(name, low, number, type)
**        values ("TRU64|TCS-5.0A", 7, 7, "ha")
**
*/
insert into spt_values(name, low, number, type)
       values ("HP-UX|SG", 1, 1, "ha")
insert into spt_values(name, low, number, type)
       values ("AIX|HACMP", 2, 2, "ha")
insert into spt_values(name, low, number, type)
       values ("NT|MSCS", 3, 3, "ha")
insert into spt_values(name, low, number, type)
       values ("IRIX|FS", 4, 4, "ha")
insert into spt_values(name, low, number, type)
       values ("SunOS|SC", 8, 8, "ha")
insert into spt_values(name, low, number, type)
       values ("SunOS|VCS", 9, 9, "ha")
insert into spt_values(name, low, number, type)
       values ("Linux|VCS", 10, 10, "ha")
go


/*
 **  The following are the values 
 **  for the local/nolocal flag for sp_msgadmin
*/
insert into spt_values(name, number, type)
	values ('nolocal', 1, 'Rt')
insert into spt_values(name, number, type)
	values ('local',   0, 'Rt')


/*
**  Create and initialize the table used by the sp_monitor procedure.
*/
if exists (select *
		from sysobjects
			where name = "spt_monitor")
begin
	drop table spt_monitor
end
go
create table spt_monitor
(
	lastrun 	datetime,
	cpu_busy 	int,
	io_busy 	int,
	idle 		int,
	pack_received 	int,
	pack_sent 	int,
	connections 	int,
	pack_errors	int,
	total_read 	int,
	total_write 	int,
	total_errors 	int
) lock allpages  on system
go

grant select on spt_monitor to public
go

insert into spt_monitor
	select
	lastrun = getdate(),
	cpu_busy = @@cpu_busy,
	io_busy = @@io_busy,
	idle = @@idle,
	pack_received = @@pack_received,
	pack_sent = @@pack_sent,
	connections = @@connections,
	pack_errors = @@packet_errors,
	total_read = @@total_read,
	total_write = @@total_write,
	total_errors = @@total_errors
go

set nocount off
go
grant select on spt_values to public
go

dump tran master with truncate_only
go

/*
{
** 		Definitions for Auto DB expansion feature:
**		==========================================
**
** Data that will eventually get loaded via a_values into spt_values.
** This data saves the expected strings that users are expected to enter
** for the sp_dbextend interface. These strings represent things like
** commands, object type(s) and other things to manipulate.
**
** The data is saved in an indexed directory structure.
**
** . The first few entries (< ~20) store the type of information being
**   stored, and the (low, high) number where the rows for that class of
**   information reside.
**
** . Then for each type of info, the (low, high) number rows encode the
**   actual string literals.
**
** This scheme reduces hard-coding strings in the others sprocs somewhat.
** Calling sprocs only have to remember the class names (e.g. 'objects',
** 'commands' etc.), and their associated directory entry number.
*/

print "Loading spt_values data for auto-db extend feature..."
go

set nocount on
go

use master
go

delete spt_values
where type = 'XT'	-- Database/device extension commands.
go

if (@@error != 0) select syb_quit()
go

/*
** =========================================================================
** Start defining the 'commands' for sp_dbextend interface, tagging
** each command with a number. Keep track of start/end of the sequence
** of these numbers.
*/

declare @low		int
      , @high		int
      , @direntry	int		-- Counter for 'directory entries'
      , @cmd_set	varchar(10)
      , @cmd_clear	varchar(10)
      , @cmd_listraw	varchar(10)
      , @cmd_modify	varchar(10)
      , @cmd_list	varchar(10)
      , @cmd_listfull	varchar(10)
      , @cmd_simulate	varchar(10)
      , @cmd_execute	varchar(10)
      , @cmd_help	varchar(10)
      , @cmd_trace	varchar(10)
      , @cmd_reload	varchar(20)

      , @cmd_trace_lvl	varchar(10)
      , @cmd_check	varchar(10)
      , @cmd_version	varchar(10)
      , @cmd_reset	varchar(10)
      , @cmd_who	varchar(10)
      , @cmd_enable	varchar(10)
      , @cmd_disable	varchar(10)

select	  @direntry = 0		-- Start of directory entry.
	, @cmd_set		= 'set'
	, @cmd_clear		= 'clear'
	, @cmd_listraw		= 'listraw'
	, @cmd_modify		= 'modify'
	, @cmd_list		= 'list'
	, @cmd_listfull		= 'listfull'
	, @cmd_simulate		= 'simulate'
	, @cmd_execute		= 'execute'
	, @cmd_help		= 'help'
	, @cmd_trace		= 'trace'
	, @cmd_reload		= 'reload defaults'
	, @cmd_trace_lvl	= 'tracelevel'
	, @cmd_check		= 'check'
	, @cmd_version		= 'version'
	, @cmd_reset		= 'reset'
	, @cmd_who		= 'who'
	, @cmd_enable		= 'enable'
	, @cmd_disable		= 'disable'

select @low = 11		-- Start number for 'commands'
select @high = @low
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_set)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_clear)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_listraw)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_modify)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_list)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_listfull)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_simulate)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_execute)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_help)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_trace)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_reload)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_check)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_version)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_reset)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_enable)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_disable)

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', @cmd_who)

/*
** Now that we have all commands registered, record the start/end values
** for this range as low/high columns in spt_values.
*/
insert into spt_values(number, type, name, low, high)
values (@direntry, 'XT', 'commands', @low, @high)

-- Reserve few more values for future commands, if any.

/*
** =========================================================================
** Start of object type name strings. Some of the 'commands' from above
** operate on this object. Here is the list of 'objects' that a command
** can operate on.
*/
select @low = @high + 10, @direntry = @direntry + 1

select @high = @low
insert into spt_values(number, type, name) values (@high, 'XT', 'database')

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', 'device')

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', 'threshold')

/*
** Now that we have all object types registered, record the start/end values
** for this range as low/high columns in spt_values.
*/
insert into spt_values(number, type, name, low, high)
values (@direntry, 'XT', 'objects', @low, @high)

/*
** =========================================================================
** The 'modify' command takes an argument telling it what to modify. Here
** is the list of valid arguments.
*/
select @low = @high + 10, @direntry = @direntry + 1

select @high = @low
insert into spt_values(number, type, name) values (@high, 'XT', 'growby')

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', 'maxsize')

/*
** Now that we have all object types registered, record the start/end values
** for this range as low/high columns in spt_values.
*/
insert into spt_values(number, type, name, low, high)
values (@direntry, 'XT', @cmd_modify, @low, @high)

/*
** =========================================================================
** The 'trace' command takes an argument to turn traceging ON/OFF.
*/
select @low = @high + 10, @direntry = @direntry + 1

select @high = @low
insert into spt_values(number, type, name) values (@high, 'XT', 'on')

select @high = @high + 1
insert into spt_values(number, type, name) values (@high, 'XT', 'off')

/*
** Now that we have all object types registered, record the start/end values
** for this range as low/high columns in spt_values.
*/
insert into spt_values(number, type, name, low, high)
values (@direntry, 'XT', @cmd_trace, @low, @high)

/*
** =========================================================================
** The 'trace' command also (will eventually) provide a way to turn on 
** tracing at some level. The level is internally handled by the sprocs to
** generate more verbose levels of trace information.
**
** Debugging levels:
**	1	- Execution flow.
**	5	- More detail.
**	10	- Greatest detail.
*/
select @low = @high + 10, @direntry = @direntry + 1
select @high = @low

/*
** Now that we have all object types registered, record the start/end values
** for this range as low/high columns in spt_values.
*/
insert into spt_values(number, type, name, low, high)
values (@direntry, 'XT', @cmd_trace_lvl, @low, 0)

/*
** =========================================================================
** These are the list of operations that could be performed by other users
** on databases, and we try to do a soft-synchronization with them to avoid
** race conditions. This factory-supplied list can be easily modified by the
** customer to include other commands that might need this synchronization.
** ( See sp_dbxt_synchronize_alterdbs.)
*/
select @low = @high + 10, @direntry = @direntry + 1

select @high = @low
insert into spt_values(number, type, name)
	values (@high, 'XT', 'CREATE DATABASE')

select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'ALTER DATABASE')

select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'DROP DATABASE')

select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'LOAD DATABASE')

select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'MOUNT DATABASE')

select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'UNMOUNT DATABASE')

-- All disk related commands just show up as DISK, and then farm off to
-- lower-level control that implements each sub-action.
--
select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'DISK')

select @high = @high + 1
insert into spt_values(number, type, name)
	values (@high, 'XT', 'DISK RESIZE')

/*
** Now that we have all commands that we want to soft-synchronize with,
** record the start/end values for this range as low/high columns in
** spt_values.
*/
insert into spt_values(number, type, name, low, high)
values (@direntry, 'XT', 'soft-sync commands', @low, @high)
go

/*
** 	End - Definitions for Auto DB expansion feature:
**	==================================================
}
*/

/*
** User authentication mechanisms. The column low
** will have the authentication id, and number
** the configuration number.
** Check the dependencies with login.h for following values
*/
insert into spt_values(name, low, number, type)
values ("AUTH_DEFAULT", 0, 0, "ua")
insert into spt_values(name, low, number, type)
values ("ASE",  32,   0, "ua")
insert into spt_values(name, low, number, type)
values ("LDAP", 64, 418, "ua")
insert into spt_values(name, low, number, type)
values ("PAM", 128, 432, "ua")
insert into spt_values(name, low, number, type)
values ("KERBEROS", 256, 0, "ua")
insert into spt_values(name, low, number, type)
values ("ANY", 480,   0, "ua")
insert into spt_values(name, low, number, type)
values ("AUTH_MASK", 480, 0, "ua")
go

/*
** Dummy row which contains the Encryption key values
** to help out in extracting the name field uniquely.
** It is currently used by sp_help.
** EK stands for encryption key.
*/
insert into spt_values(name, number, type, low, msgnum)
values ("encryption key", 15, "EK", 1, 17588)
go
  

/*
**	Begin - Definitions for the Cluster Workload Manager:
**	======================================================
**
**  The following types are used by the workload manager:
**	"W1" -> these define logical cluster set options.
**		name = name of the set option
**		number = wlmgr attribute number
**		low = 1 if can be set on system lc, 0 if it can't
**		msgnum = help msg number
""	"W2" -> these are values for the W1 set options.
**		name = option setting
**		number = corresponding number from W1 type
**		low = bit value corresponding with name
**		msgnum = help msg number
**	"W3" -> these are values for route types.
*		name = route type
**		number = route attribute number
**		msgnum = help msg number
**	"W4" -> these are the profile categories: weight and threshold
*		name = profile category
**		number = profile attribute number
**		msgnum = 0
**	"W5" -> these are the profile elements.
*		name = profile element
**		number = profile element attribute number
**		msgnum = 0
**		
*/

/* Logical cluster set options */
insert into spt_values(name, number, low, type, msgnum)
values ("open", 1, 1, "W1", 19746)
insert into spt_values(name, number, low, type, msgnum)
values ("failover", 2, 0, "W1", 19747)
insert into spt_values(name, number, low, type, msgnum)
values ("system_view", 3, 1, "W1", 19748)
insert into spt_values(name, number, low, type, msgnum)
values ("startup", 4, 0, "W1", 19749)
insert into spt_values(name, number, low, type, msgnum)
values ("down_routing", 5, 0, "W1", 19750)
insert into spt_values(name, number, low, type, msgnum)
values ("load_profile", 6, 1, "W1", 19751)
insert into spt_values(name, number, low, type, msgnum)
values ("fail_to_any", 7, 0, "W1", 19752)
insert into spt_values(name, number, low, type, msgnum)
values ("login_distribution", 8, 1, "W1", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("action_release", 9, 1, "W1", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("gather", 10, 1, "W1", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("failover_recovery", 11, 0, "W1", 0)

/* Logical cluster set option settings */

/* failover mode */
insert into spt_values(name, number, low, type, msgnum)
values ("instance", 2, 8, "W2", 19753)
insert into spt_values(name, number, low, type, msgnum)
values ("group", 2, 16, "W2", 19754)

/* system_view */
insert into spt_values(name, number, low, type, msgnum)
values ("instance", 3, 32, "W2", 19755)
insert into spt_values(name, number, low, type, msgnum)
values ("cluster", 3, 64, "W2", 19756)

/* startup mode */
insert into spt_values(name, number, low, type, msgnum)
values ("automatic", 4, 128, "W2", 19757)
insert into spt_values(name, number, low, type, msgnum)
values ("manual", 4, 256, "W2", 19758)

/* down routing mode */
insert into spt_values(name, number, low, type, msgnum)
values ("disconnect", 5, 512, "W2", 19759)
insert into spt_values(name, number, low, type, msgnum)
values ("open", 5, 1024, "W2", 19760)
insert into spt_values(name, number, low, type, msgnum)
values ("system", 5, 2048, "W2", 19761)

/* login distribution mode */
insert into spt_values(name, number, low, type, msgnum)
values ("affinity", 8, 4096, "W2", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("round-robin", 8, 8192, "W2", 0)

/* fail_to_any */
insert into spt_values(name, number, low, type, msgnum)
values ("off", 7, 0, "W2", 19763)
insert into spt_values(name, number, low, type, msgnum)
values ("false", 7, 0, "W2", 19763)
insert into spt_values(name, number, low, type, msgnum)
values ("on", 7, 1, "W2", 19762)
insert into spt_values(name, number, low, type, msgnum)
values ("true", 7, 1, "W2", 19762)

/* Logical cluster route types */
insert into spt_values(name, number, type, msgnum)
values ("login", 0, "W3", 19772)
insert into spt_values(name, number, type, msgnum)
values ("application", 1, "W3", 19773)
insert into spt_values(name, number, type, msgnum)
values ("alias", 2, "W3", 19774)

/* cluster profiles */
insert into spt_values(name, number, low, type, msgnum)
values ("weight", 1, 0, "W4", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("threshold", 2, 0, "W4", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("cpu busy", 1, 1, 255, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("user connections", 2, 1, 255, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("run queue", 3, 1, 255, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("io load", 4, 1, 255, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("engine deficit", 5, 1, 255, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("user metric", 6, 1, 255, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("login", 101, 2, 100, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("dynamic", 102, 2, 100, "W5", 0)
insert into spt_values(name, number, low, high, type, msgnum)
values ("hysteresis", 103, 2, 100, "W5", 0)

/* Logical cluster action release mode */
insert into spt_values(name, number, low, type, msgnum)
values ("manual", 9, 16384, "W2", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("automatic", 9, 32768, "W2", 0)

/* Logical cluster gather mode */
insert into spt_values(name, number, low, type, msgnum)
values ("manual", 10, 65536, "W2", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("automatic", 10, 131072, "W2", 0)

/* Logical cluster failover recovery */
insert into spt_values(name, number, low, type, msgnum)
values ("off", 11, 262144, "W2", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("false", 11, 262144, "W2", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("on", 11, 524288, "W2", 0)
insert into spt_values(name, number, low, type, msgnum)
values ("true", 11, 524288, "W2", 0)

/*
**	End - Definitions for the Cluster Workload Manager:
**	======================================================
*/

dump tran master with truncate_only
go
set nocount off
go

/*
** Insert rows which contains the RTMS provider mask
** low indicates if it is a customer used RTMS provider
*/
insert spt_values (name, number, type, low, msgnum)
	values ("RTMS PROVIDERS MASK", -1, "RT", 0, NULL)
insert spt_values (name, number, type, low, msgnum)
	values ("all providers", 1, "RT", 0, NULL)
insert spt_values (name, number, type, low, msgnum)
	values ("tibco_jms", 2, "RT", 1, NULL)
insert spt_values (name, number, type, low, msgnum)
	values ("ibm_mq", 4, "RT", 1, NULL)
insert spt_values (name, number, type, low, msgnum)
	values ("eas_jms", 8, "RT", 1, NULL)
insert spt_values (name, number, type, low, msgnum)
	values ("sonicmq_jms", 16, "RT", 1, NULL)
go

/* 
** The following rows describe strings used to describe
** the SQL operations relevant to SQL statement replication.
** Valid options are:
**
**	'u' for SQL UPDATE statements.
**	'd' for SQL DELETE statements.
**	'i' for SQL INSERT SELECT statements.
**	's' for SQL SELECT INTO statements.
*/
insert spt_values (name, number, type)
	values ('udis', 1, "SQ")
go

/*
** Insert rows describing 'optimizer level' configuration parameter.
** Those rows represent legitimate values of this config paramater.
*/
insert spt_values (name, number, type)
	values("ase1502esd5", 150205, "OL")
insert spt_values (name, number, type)
	values("ase1502esd6", 150206, "OL")
insert spt_values (name, number, type)
	values("ase1503ir", 150300, "OL")
insert spt_values (name, number, type)
	values("ase1503esd1", 150301, "OL")
insert spt_values (name, number, type)
	values("ase1503esd2", 150302, "OL")
insert spt_values (name, number, type)
	values("ase_current", 999998, "OL")
insert spt_values (name, number, type)
	values("ase_default", 999999, "OL")
go

/*
** Insert values describing the output of the builtin
** tran_dumpable_status. (Keep name <= 28 chars)
** The procedure sp_tran_dumpable_status expects
** a description of the bit and the bit ordinal
** position instead of the bit value.
*/
insert spt_values (name, number, type)
	values("Fail to use the database", 0, "DX")
insert spt_values (name, number, type)
	values("Log is not on its own device", 1, "DX")
insert spt_values (name, number, type)
	values("First log page in data seg", 2, "DX")
insert spt_values (name, number, type)
	values("Trunc log on ckpt is set", 3, "DX")
insert spt_values (name, number, type)
	values("Non-logged writes happened", 4, "DX")
insert spt_values (name, number, type)
	values("Log has been truncated", 5, "DX")
insert spt_values (name, number, type)
	values("No dump taken since crt/upg", 6, "DX")
insert spt_values (name, number, type)
	values("Durability is not full", 7, "DX")
insert spt_values (name, number, type)
	values("Database is read-only", 8, "DX")
insert spt_values (name, number, type)
	values("Online for standby access", 9, "DX")
insert spt_values (name, number, type)
	values("Database is an archive", 10, "DX")
go
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_instmsg')
begin
	drop procedure sp_instmsg
end
go
print "Installing sp_instmsg"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/* A_MESSAGES - install system stored procedure
**		messages into sysmessages. THIS IS NOT TO BE
**		USED TO INSTALL SERVER MESSAGES.
*/

set nocount on
go


create procedure sp_instmsg
	@msg_num	int,
	@msg_text	varchar(1024)
as
	declare @description varchar(1024)

	select @description = description from sysmessages where
		error = @msg_num and langid is null

	if @description = @msg_text
		return 1

	if @description is not null
		delete sysmessages where error = @msg_num

	if @msg_text is null
		return 2

	insert sysmessages values
		(@msg_num, 0, 0, @msg_text, null, null)

	return 0
go

/*
**Messages for "sproc_phrases"	17000
*/

exec sp_instmsg 17000, "timeouts"
exec sp_instmsg 17001, "no timeouts"
exec sp_instmsg 17002, "net password encryption"
exec sp_instmsg 17010, "no"
exec sp_instmsg 17011, "yes"
exec sp_instmsg 17037, "default sortorder id"

/*
**Messages for "sp_sproc_phrases"	17050
*/

exec sp_instmsg 17050, "select into/bulkcopy/pllsort"

/*
**Messages for "sproc_phrases"	17051
*/

exec sp_instmsg 17051, "trunc log on chkpt"
exec sp_instmsg 17052, "no chkpt on recovery"
exec sp_instmsg 17053, "don't recover"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17054, "not recovered"
exec sp_instmsg 17055, "ddl in tran"
exec sp_instmsg 17056, "read only"
exec sp_instmsg 17057, "dbo use only"
exec sp_instmsg 17058, "single user"
exec sp_instmsg 17059, "ALL SETTABLE OPTIONS"
exec sp_instmsg 17060, "dbname has changed"
exec sp_instmsg 17061, "failed upgrade"
exec sp_instmsg 17062, "abort tran on log full"
exec sp_instmsg 17063, "no free space acctg"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17069, "allow nulls by default"
exec sp_instmsg 17070, "trusted"
exec sp_instmsg 17075, "Channel Devices"
exec sp_instmsg 17080, "showplan"
exec sp_instmsg 17081, "noexec"
exec sp_instmsg 17082, "arithignore"
exec sp_instmsg 17083, "arithabort"
exec sp_instmsg 17084, "background"
exec sp_instmsg 17085, "control"
exec sp_instmsg 17086, "offsets"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17087, "statistics io and time"
exec sp_instmsg 17088, "parseonly"
exec sp_instmsg 17089, "procid"
exec sp_instmsg 17090, "rowcount"
exec sp_instmsg 17091, "nocount"
exec sp_instmsg 17100, "trigger"
exec sp_instmsg 17101, "system table"
exec sp_instmsg 17102, "view"
exec sp_instmsg 17103, "user table"
exec sp_instmsg 17104, "stored procedure"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17105, "default"
exec sp_instmsg 17106, "rule"
exec sp_instmsg 17107, "stored procedure (ext)"
exec sp_instmsg 17110, "data only"
exec sp_instmsg 17111, "log only"
exec sp_instmsg 17112, "data and log"
exec sp_instmsg 17120, "default disk"
exec sp_instmsg 17121, "physical disk"

/*
**Messages for "sp_sproc_phrases"	17122
*/

exec sp_instmsg 17122, "archive database disk"
exec sp_instmsg 17123, "read-only"

/*
**Messages for "sproc_phrases"	17124
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17124, "dump device"
exec sp_instmsg 17125, "serial writes"
exec sp_instmsg 17126, "device mirrored"
exec sp_instmsg 17127, "reads mirrored"
exec sp_instmsg 17128, "half-mirror only"
exec sp_instmsg 17129, "mirror enabled"
exec sp_instmsg 17130, "os_session_label"
exec sp_instmsg 17131, "maximum write"
exec sp_instmsg 17132, "current write"
exec sp_instmsg 17133, "minimum write"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17134, "maximum read"
exec sp_instmsg 17135, "current read"
exec sp_instmsg 17136, "maxhold"
exec sp_instmsg 17137, "minhold"
exec sp_instmsg 17138, "clearance"

/*
**Messages for "sp_sproc_phrases"	17139
*/

exec sp_instmsg 17139, "SQL function"

/*
**Messages for "sproc_phrases"	17140
*/

exec sp_instmsg 17140, "referential constraint"
exec sp_instmsg 17142, "You need to be able to set curwrite label to data_high. This script will continue in spite of failure to set curwrite. Please rerun after setting your labels correctly."
exec sp_instmsg 17144, "identity in nonunique index"
exec sp_instmsg 17145, "auto identity"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17148, "readonly"

/*
**Messages for "sp_getmessage"	17200
*/

exec sp_instmsg 17200, "Message number must be greater than or equal to 17000."
exec sp_instmsg 17201, "'%1!' is not an official language name from syslanguages."
exec sp_instmsg 17202, "Message number %1! does not exist in the %2! language."

/*
**Messages for "sp_addmessage"	17210
*/

exec sp_instmsg 17210, "Message number must be at least 20000."
exec sp_instmsg 17211, "Cannot add message until sysusermessages system table is created properly by Upgrade."
exec sp_instmsg 17212, "A message with number %1! in the specified language already exists."
exec sp_instmsg 17213, "Drop the old message first if you still wish to add this one."
exec sp_instmsg 17214, "The message has been inserted."
exec sp_instmsg 17215, "The message has not been inserted."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17216, "Only the System Administrator (SA) or the Database Owner (dbo) may add messages which set the WITH_LOG option to `'true'`."
exec sp_instmsg 17217, "The only valid @with_log values are TRUE or FALSE."
exec sp_instmsg 17218, "Message number %1! with language ID %2! was created by user ID %3!. You cannot replace that message; you must first delete the existing message using sp_dropmessage, then add the changed message."

/*
**Messages for "sp_dropmessage"	17220
*/

exec sp_instmsg 17220, "Message number %1! does not exist."
exec sp_instmsg 17221, "Message deleted."
exec sp_instmsg 17222, "User '%1!' does not have permission to drop message number %2!."
exec sp_instmsg 17223, "User '%1!' does not have permission to drop message number %2! in the %3! language."
exec sp_instmsg 17224, "Drop failed.  Your curwrite label must match the security label of the message.  Check sysusermessages."

/*
**Messages for "sp_addalias"	17230
*/

exec sp_instmsg 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
exec sp_instmsg 17231, "No login with the specified name exists."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17232, "No user with the specified name exists in the current database."
exec sp_instmsg 17233, "'%1!' is already a user in the current database."
exec sp_instmsg 17234, "The specified user name is already aliased."
exec sp_instmsg 17235, "Alias user added."
exec sp_instmsg 17236, "Setting curwrite label to data_low for inserts into sysalternates table failed."

/*
**Messages for "sp_addgroup"	17240
*/

exec sp_instmsg 17240, "'%1!' is not a valid name."
exec sp_instmsg 17241, "A user with the specified group name already exists."
exec sp_instmsg 17242, "A group with the specified name already exists."
exec sp_instmsg 17243, "New group added."

/*
**Messages for "sp_addlanguage"	17250
*/

exec sp_instmsg 17250, "'%1!' already exists in syslanguages."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17251, "'%1!' is not a valid date order."
exec sp_instmsg 17252, "'%1!' is not a valid first day."
exec sp_instmsg 17253, "'%1!' alias already exists in syslanguages."
exec sp_instmsg 17254, "Language not inserted."
exec sp_instmsg 17255, "New language inserted."

/*
**Messages for "sp_addlogin"	17260
*/

exec sp_instmsg 17260, "Can't run %1! from within a transaction."
exec sp_instmsg 17261, "Only the System Administrator (SA) may execute this procedure."
exec sp_instmsg 17262, "A user with the specified login name already exists."
exec sp_instmsg 17263, "Database name not valid -- login not added."
exec sp_instmsg 17264, "New login created."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17265, "A role with the specified name '%1!' already exists in this Server."
exec sp_instmsg 17266, "All logins have been assigned. No more logins can be added at this time."
exec sp_instmsg 17267, "Invalid value specified for %1! option. Login not created."

/*
**Messages for "sp_addremotelogin"	17270
*/

exec sp_instmsg 17270, "There is not a server named '%1!'."
exec sp_instmsg 17271, "'%1!' is the local server - remote login not applicable."
exec sp_instmsg 17272, "There is already a default-name mapping of a remote login from remote server '%1!'."
exec sp_instmsg 17273, "New remote login created."
exec sp_instmsg 17274, "'%1!' isn't a local user -- remote login denied."
exec sp_instmsg 17275, "There is already a remote user named '%1!' for remote server '%2!'."
exec sp_instmsg 17276, "Usage:sp_addremotelogin remoteserver [, loginame [,remotename]]"

/*
**Messages for "sp_addsegment"	17280
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17280, "No such device exists -- run sp_helpdb to list the devices for the current database."
exec sp_instmsg 17281, "The specified device is not used by the database."
exec sp_instmsg 17282, "The specified device is not a database device."
exec sp_instmsg 17283, "'%1!' is reserved exclusively as a log device."
exec sp_instmsg 17284, "'%1!' is not a valid identifier."
exec sp_instmsg 17285, "There is already a segment named '%1!'."
exec sp_instmsg 17286, "The maximum number of segments for the current database are already defined."
exec sp_instmsg 17287, "Segment created."
exec sp_instmsg 17288, "You must execute this procedure from the database in which you wish to %1! a segment. Please execute 'use %2!' and try again."
exec sp_instmsg 17289, "Set your curwrite to the hurdle of current database."

/*
**Messages for "sp_addserver"	17290
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17290, "There is already a server named '%1!', physical name '%2!'."
exec sp_instmsg 17291, "sp_addserver servername [, local | NULL] [, physical_name]"
exec sp_instmsg 17292, "There is already a local server."
exec sp_instmsg 17293, "Server added."
exec sp_instmsg 17294, "Changing physical name of server '%1!' from '%2!' to '%3!'"
exec sp_instmsg 17295, "Adding server '%1!', physical name '%2!'"
exec sp_instmsg 17296, "Unknown server class '%1!'."
exec sp_instmsg 17297, "Changing server class of server '%1!' from '%2!' to '%3!'."

/*
**Messages for "sp_addtype"	17300
*/

exec sp_instmsg 17300, "Usage: sp_addtype name, 'datatype' [,null | nonull | identity]"
exec sp_instmsg 17301, "'%1!' is not a valid type name."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17302, "A type with the specified name already exists."
exec sp_instmsg 17303, "Physical datatype does not exist."
exec sp_instmsg 17304, "User-defined datatypes based on the 'timestamp' datatype are not allowed."
exec sp_instmsg 17305, "Physical datatype does not allow nulls."
exec sp_instmsg 17306, "Physical type is fixed length. You cannot specify the length."
exec sp_instmsg 17307, "You must specify a length with this physical type."
exec sp_instmsg 17308, "Illegal length specified -- must be between 1 and %1!."
exec sp_instmsg 17309, "Type added."

/*
**Messages for "sp_addumpdevice"	17310
*/

exec sp_instmsg 17310, "Unknown device type. Use 'disk', 'tape' or 'archive database'."
exec sp_instmsg 17311, "device_name may not be NULL."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17312, "physicalname may not be NULL."
exec sp_instmsg 17314, "Device with same logical name already exists."
exec sp_instmsg 17317, "Please specify media capacity in megabytes (1 MB minimum)."
exec sp_instmsg 17318, "WARNING: specified size parameter is not used for the disk device type."
exec sp_instmsg 17319, "'Disk' device added."
exec sp_instmsg 17320, "'Tape' device added."
exec sp_instmsg 17321, "WARNING: physical device name '%1!' is not unique."
exec sp_instmsg 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."

/*
**Messages for "sp_adduser"	17330
*/

exec sp_instmsg 17330, "A user with the same name already exists in the database."
exec sp_instmsg 17331, "User already has a login under a different name."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17332, "User already has alias access to the database."
exec sp_instmsg 17333, "No group with the specified name exists."
exec sp_instmsg 17334, "All user ids have been assigned."
exec sp_instmsg 17335, "New user added."
exec sp_instmsg 17336, "Setting curwrite label to data_low for inserts into sysusers table failed."

/*
**Messages for "sp_bindefault"	17340
*/

exec sp_instmsg 17340, "Default and table or usertype must be in current database."
exec sp_instmsg 17341, "Usage: sp_bindefault defaultname, objectname [, 'futureonly']"
exec sp_instmsg 17342, "No such default exists.  You must create the default first."
exec sp_instmsg 17343, "You can't bind a default to a timestamp datatype column."
exec sp_instmsg 17344, "You do not own a column of that name."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17345, "Default bound to column."
exec sp_instmsg 17346, "You do not own a datatype of that name."
exec sp_instmsg 17347, "Default bound to datatype."
exec sp_instmsg 17348, "The new default has been bound to columns(s) of the specified user datatype."
exec sp_instmsg 17349, "You cannot bind a declared default. The default must be created using create default."

/*
**Messages for "sp_bindrule"	17350
*/

exec sp_instmsg 17350, "Rule and table or usertype must be in current database."
exec sp_instmsg 17351, "Usage: sp_bindrule rulename, objectname [, 'futureonly']"
exec sp_instmsg 17352, "No such rule exists.  You must create the rule first."
exec sp_instmsg 17353, "You can't bind a rule to a text, image, or timestamp datatype column."
exec sp_instmsg 17354, "Rule bound to table column."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17355, "You can't bind a rule to a text, image, or timestamp datatype."
exec sp_instmsg 17356, "Rule bound to datatype."
exec sp_instmsg 17357, "The new rule has been bound to column(s) of the specified user datatype."
exec sp_instmsg 17358, "You cannot bind a declared constraint. The rule must be created using create rule."
exec sp_instmsg 17359, "You cannot bind a rule to a virtual computed column."

/*
**Messages for "sp_changedbowner"	17360
*/

exec sp_instmsg 17360, "Only the System Administrator (SA) or the Database Owner (dbo) can change the owner of a database."
exec sp_instmsg 17361, "Can't change the owner of the master, model, tempdb or sybsystemprocs database."
exec sp_instmsg 17362, "The proposed new db owner already is a user in the database or owns the database."
exec sp_instmsg 17363, "The proposed new db owner already is aliased in the database."
exec sp_instmsg 17364, "The dependent aliases were mapped to the new dbo."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17365, "The dependent aliases were dropped."
exec sp_instmsg 17366, "Database owner changed."
exec sp_instmsg 17368, "Your curwrite label needs to be set correctly before you attempt to change the database owner."

/*
**Messages for "sp_changegroup"	17370
*/

exec sp_instmsg 17370, "Group changed."

/*
**Messages for "sp_chklangparam"	17373
*/

exec sp_instmsg 17373, "List of %1! names contains spaces, which are not allowed."
exec sp_instmsg 17374, "List of %1! names has too few names."
exec sp_instmsg 17375, "List of %1! names has too many names."
exec sp_instmsg 17376, "List of %1! names has name(s) which are too long."
exec sp_instmsg 17377, "List of %1! names contains name(s) which have '%2!' non-alphabetic characters."

/*
**Messages for "sp_commitservice"	17380
*/

exec sp_instmsg 17380, "Commit service xact id doesn't exist."

/*
**Messages for "sp_commonkey"	17390
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17390, "Table or view name must be in current database."
exec sp_instmsg 17391, "First table in the common key doesn't exist."
exec sp_instmsg 17392, "Second table in the common key doesn't exist."
exec sp_instmsg 17393, "Only the table owner may define its common keys."
exec sp_instmsg 17394, "The tables have no such first column or the columns are of different types."
exec sp_instmsg 17395, "The tables have no such second column or the columns are of different types."
exec sp_instmsg 17396, "The tables have no such third column or the columns are of different types."
exec sp_instmsg 17397, "The tables have no such fourth column or the columns are of different types."
exec sp_instmsg 17398, "The tables have no such fifth column or the columns are of different types."
exec sp_instmsg 17399, "The tables have no such sixth column or the columns are of different types."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17400, "The tables have no such seventh column or the columns are of different types."
exec sp_instmsg 17401, "The tables have no such eighth column or the columns are of different types."
exec sp_instmsg 17402, "New common key added."
exec sp_instmsg 17403, "Common key definition already exists between the tables '%1!' and table '%2!' for the specified columns."

/*
**Messages for "sp_configure"	17410
*/

exec sp_instmsg 17410, "Configuration option doesn't exist."
exec sp_instmsg 17411, "Configuration option is not unique."
exec sp_instmsg 17412, "Only the System Administrator (SA) may change configuration parameters."
exec sp_instmsg 17413, "The value of the 'number of devices' must not be less than the number of active devices '%1!"
exec sp_instmsg 17414, "You can't set the default language to a language ID that is not defined in syslanguages."
exec sp_instmsg 17415, "Configuration option value is not legal."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17416, "Configuration option changed. Run the RECONFIGURE command to install."
exec sp_instmsg 17417, "Maximum file descriptors or FILLM process quota too low to support requested number of user connections. Configuration variable 'user connections' will not be modified."
exec sp_instmsg 17418, "'%1!' is an invalid file command. The valid commands are 'verify', 'read', 'write', and 'restore'."
exec sp_instmsg 17419, "Configuration option changed. ASE need not be rebooted since the option is dynamic."

/*
**Messages for "sp_dboption"	17420
*/

exec sp_instmsg 17420, "Settable database options."
exec sp_instmsg 17421, "No such database -- run sp_helpdb to list databases."
exec sp_instmsg 17422, "The 'master' database's options can not be changed."
exec sp_instmsg 17423, "Usage: sp_dboption [dbname, optname, {true | false}]"
exec sp_instmsg 17424, "Database option doesn't exist or can't be set by user."
exec sp_instmsg 17425, "Run sp_dboption with no parameters to see options."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17426, "Database option is not unique."
exec sp_instmsg 17427, "Only the System Administrator (SA) or the owner of the database may set db options."
exec sp_instmsg 17428, "You must be in the 'master' database in order to change database options."
exec sp_instmsg 17429, "The database is currently in use -- 'read only' option disallowed."
exec sp_instmsg 17430, "Run the CHECKPOINT command in the database that was changed."
exec sp_instmsg 17431, "true"
exec sp_instmsg 17432, "false"
exec sp_instmsg 17433, "Database option '%1!' turned ON for database '%2!'."
exec sp_instmsg 17434, "Database option '%1!' turned OFF for database '%2!'."
exec sp_instmsg 17435, "The 'single user' option is not valid for the 'sybsecurity' database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17436, "You cannot set the '%1!' option for a temporary database."
exec sp_instmsg 17437, "unique auto_identity index"
exec sp_instmsg 17438, "disable alias access"
exec sp_instmsg 17439, "You cannot turn on '%1!' for '%2!' because this is an HA server that has been configured with the proxy_db option."

/*
**Messages for "sp_defaultdb"	17440
*/

exec sp_instmsg 17440, "Database name not valid -- default not changed."
exec sp_instmsg 17441, "You can't change someone else's default database."
exec sp_instmsg 17442, "Default database changed."
exec sp_instmsg 17443, "Error in updating the default database."
exec sp_instmsg 17444, "Automatic login script for user '%1!' is disabled. Use sp_modifylogin to enable execution of auto login script for the new database."
exec sp_instmsg 17445, "Cannot change default database since login trigger for user '%1!' is currently active"

/*
**Messages for "sp_defaultlanguage"	17450
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17450, "Only the System Administrator (SA) or '%1!' can change %2!'s default language."
exec sp_instmsg 17451, "This user does not exist.  Run sp_addlogin to add this user in."
exec sp_instmsg 17452, "%1!'s default language has been changed to %2!."
exec sp_instmsg 17453, "Error in changing the default language."

/*
**Messages for "sp_depends"	17460
*/

exec sp_instmsg 17460, "Object must be in the current database."
exec sp_instmsg 17461, "Object does not exist in this database."
exec sp_instmsg 17462, "Things the object references in the current database."
exec sp_instmsg 17463, "Things inside the current database that reference the object."
exec sp_instmsg 17464, "Object doesn't reference any object and no objects reference it."
exec sp_instmsg 17465, "The specified column (or all columns, if none was specified) in %1! has no dependencies on other objects, and no other object depends on any columns from it."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17466, "Dependent objects that reference column %1!."
exec sp_instmsg 17467, "Dependent objects that reference all columns in the table. Use sp_depends on each column to get more information."
exec sp_instmsg 17468, "Columns referenced in stored procedures, views or triggers are not included in this report."
exec sp_instmsg 17469, "Tables that reference this object:"

/*
**Messages for "sp_diskdefault"	17470
*/

exec sp_instmsg 17470, "No such device exists -- run sp_helpdevice to list the ASE devices."
exec sp_instmsg 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices."
exec sp_instmsg 17472, "Usage: sp_diskdefault logicalname {defaulton | defaultoff}."
exec sp_instmsg 17473, "The device '%1!' is a private device. This operation is not valid for private devices."
exec sp_instmsg 17474, "Device '%1!' is a virtual cache device. It cannot be marked as default device."

/*
**Messages for "sp_dropalias"	17480
*/

exec sp_instmsg 17480, "Alias user dropped."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17481, "No alias for specified user exists."

/*
**Messages for "sp_dropdevice"	17482
*/

exec sp_instmsg 17482, "Device is being used by a database. You can't drop it."
exec sp_instmsg 17483, "Device dropped."

/*
**Messages for "sp_dropdumpdevice"	17484
*/

exec sp_instmsg 17484, "No device with specified logical name exists."
exec sp_instmsg 17485, "Device is not a dump device and may not be dropped."

/*
**Messages for "sp_dropgroup"	17486
*/

exec sp_instmsg 17486, "Can't drop the group 'public'."
exec sp_instmsg 17487, "You cannot drop group because it owns objects in database."
exec sp_instmsg 17488, "Group has members.  It must be empty before it can be dropped."
exec sp_instmsg 17489, "Group has been dropped."

/*
**Messages for "sp_dropkey"	17490
*/

exec sp_instmsg 17490, "Usage: sp_dropkey {primary | foreign | common}, tab name [, dependent tab name]"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17491, "Type must be 'primary', 'foreign', or 'common'."
exec sp_instmsg 17492, "The table or view named doesn't exist in the current database."
exec sp_instmsg 17493, "You must be the owner of the table or view to drop its key."
exec sp_instmsg 17494, "No primary key for the table or view exists."
exec sp_instmsg 17495, "Primary key for the table or view dropped."
exec sp_instmsg 17496, "Dependent foreign keys were also dropped."
exec sp_instmsg 17497, "You must supply the dependent table or view as the third parameter."
exec sp_instmsg 17498, "The dependent table or view doesn't exist in the current database."
exec sp_instmsg 17499, "No foreign key for the table or view exists."
exec sp_instmsg 17500, "Foreign key dropped."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17501, "No common keys exist between the two tables or views supplied."
exec sp_instmsg 17502, "Common keys dropped."

/*
**Messages for "sp_droplanguage"	17505
*/

exec sp_instmsg 17505, "Can't drop '%1!' because there are associated entries in master.dbo.sysmessages.  Run sp_droplanguage with the 'dropmessages' flag."
exec sp_instmsg 17506, "The only legal value for the second parameter is 'dropmessages'."
exec sp_instmsg 17507, "Language deleted."

/*
**Messages for "sp_droplogin"	17509
*/

exec sp_instmsg 17509, "User exists or is an alias or is a database owner in at least one database. Drop the user or the alias, or change the database ownership before dropping the login."
exec sp_instmsg 17511, "Login dropped."

/*
**Messages for "sp_dropremotelogin"	17512
*/

exec sp_instmsg 17512, "Remote login dropped."
exec sp_instmsg 17513, "There is no remote user '%1!' mapped to local user '%2!' from the remote server '%3!'."

/*
**Messages for "sp_dropsegment"	17520
*/

exec sp_instmsg 17520, "There is no such segment as '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17521, "Can't drop the '%1!'segment completely."
exec sp_instmsg 17522, "The segment '%1!' is being used."
exec sp_instmsg 17523, "Segment '%1!' does not reference device '%2!'."
exec sp_instmsg 17524, "There is only one device mapping for the segment '%1!' -- use sp_dropsegment with no device argument."
exec sp_instmsg 17525, "Segment dropped."
exec sp_instmsg 17526, "Segment reference to device dropped."
exec sp_instmsg 17527, "WARNING: There are no longer any segments referencing device '%1!'.  This device will no longer be used for space allocation."
exec sp_instmsg 17528, "WARNING: There are no longer any segments referencing devices '%1!'.  These devices will no longer be used for space allocation."

/*
**Messages for "sp_dropserver"	17530
*/

exec sp_instmsg 17530, "There are still remote logins for the server '%1!'."
exec sp_instmsg 17531, "Remote logins for remote server '%1!' have been dropped."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17532, "Usage: sp_dropserver server [, droplogins]"
exec sp_instmsg 17533, "Server dropped."
exec sp_instmsg 17534, "There are still external logins for the server '%1!'."
exec sp_instmsg 17535, "External logins for remote server '%1!' have been dropped."
exec sp_instmsg 17536, "Unable to drop server '%1!' because it is referenced in master.dbo.sysdatabases."
exec sp_instmsg 17537, "Unable to drop server '%1!' because it is referenced by transaction coordinator."

/*
**Messages for "sp_droptype"	17540
*/

exec sp_instmsg 17540, "The type doesn't exist or you don't own it."
exec sp_instmsg 17541, "Type is being used. You cannot drop it."
exec sp_instmsg 17542, "Type has been dropped."

/*
**Messages for "sp_dropuser"	17543
*/

exec sp_instmsg 17543, "You cannot drop the 'database owner'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17544, "You cannot drop the 'guest' user from master database or a temporary database."
exec sp_instmsg 17545, "You cannot drop user because user '%1!' owns objects in database."
exec sp_instmsg 17546, "You cannot drop user because user '%1!' owns types in database."
exec sp_instmsg 17547, "The dependent aliases were also dropped."
exec sp_instmsg 17548, "User has been dropped from current database."
exec sp_instmsg 17549, "You cannot drop user because user '%1!' owns grantable privileges and granted them to other users.  The user has granted the following privileges:"

/*
**Messages for "sp_extendsegment"	17550
*/

exec sp_instmsg 17550, "Segment extended."
exec sp_instmsg 17551, "Device '%1!' is now exclusively used by '%2!'"
exec sp_instmsg 17552, "This command has been ignored.  Extending the log segment on device '%1!' would leave no space for creating objects in database '%2!'."

/*
**Messages for "sp_foreignkey"	17560
*/

exec sp_instmsg 17560, "Foreign key table doesn't exist."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17561, "Primary key table doesn't exist."
exec sp_instmsg 17562, "Only the owner of the table may define a foreign key."
exec sp_instmsg 17563, "The table does not have a column named '%1!'."
exec sp_instmsg 17564, "Primary key does not exist with the same number of columns as the foreign key."
exec sp_instmsg 17565, "Primary key does not exist."
exec sp_instmsg 17566, "Datatypes of the column '%1!' in the keys are different."
exec sp_instmsg 17567, "New foreign key added."
exec sp_instmsg 17568, "Column '%1!' may not be specified as a foreign key because the column or the associated primary key column is encrypted."
exec sp_instmsg 17569, "Foreign key relationship already exists between table '%1!' and primary table '%2!' for the specified columns."

/*
**Messages for "sp_help"	17570
*/

exec sp_instmsg 17570, "Operating System File"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17571, "---------------------"
exec sp_instmsg 17572, "'%1!' is not a valid database name."
exec sp_instmsg 17573, "Object is Remote/External"
exec sp_instmsg 17574, "-------------------------"
exec sp_instmsg 17575, "Object created with 'existing' option"
exec sp_instmsg 17576, "Lock scheme Allpages"
exec sp_instmsg 17577, "Lock scheme Datapages"
exec sp_instmsg 17578, "Lock scheme Datarows"
exec sp_instmsg 17579, "Lock scheme is unknown or is corrupted"
exec sp_instmsg 17581, "Trigger is disabled."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17582, "Trigger is enabled."
exec sp_instmsg 17583, "in"
exec sp_instmsg 17584, "out"
exec sp_instmsg 17585, "inout"
exec sp_instmsg 17586, "Return Type"
exec sp_instmsg 17587, "partition condition"
exec sp_instmsg 17588, "encryption key"
exec sp_instmsg 17589, "computed column"

/*
**Messages for "sp_helpdb"	17590
*/

exec sp_instmsg 17590, "The specified database does not exist."
exec sp_instmsg 17591, "no options set"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17592, " -- unused by any segments --"
exec sp_instmsg 17594, "offline"
exec sp_instmsg 17595, "online for standby access"
exec sp_instmsg 17596, "has suspect pages/objects"
exec sp_instmsg 17597, "quiesce database"
exec sp_instmsg 17598, "log preallocation"
exec sp_instmsg 17599, "user created temp db"
exec sp_instmsg 17600, "sp_helpdb: order value '%1!' is not valid. Valid values are 'lstart' and 'device_name'. Using default value 'lstart'."
exec sp_instmsg 17601, "mixed log and data"
exec sp_instmsg 17602, "delayed commit"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17603, "archive"
exec sp_instmsg 17604, "compressed data"
exec sp_instmsg 17605, "compressed log"
exec sp_instmsg 17606, "local user temp db"
exec sp_instmsg 17607, "local system temp db"
exec sp_instmsg 17608, "global user temp db"
exec sp_instmsg 17609, "Device allocation is not displayed for local temporary database '%1!'. To display this information, execute the procedure on the owner instance '%2!'."

/*
**Messages for "sp_helpdevice"	17610
*/

exec sp_instmsg 17610, "No such i/o device exists."
exec sp_instmsg 17611, "special"
exec sp_instmsg 17612, "disk"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17613, "tape"
exec sp_instmsg 17614, "UNKNOWN DEVICE"
exec sp_instmsg 17615, "MIRROR ENABLED"
exec sp_instmsg 17616, "MIRROR DISABLED"
exec sp_instmsg 17617, "mirror ="
exec sp_instmsg 17618, "only device '%1!' of mirror is enabled -- device '%2!' is disabled"
exec sp_instmsg 17619, "channel"
exec sp_instmsg 17620, "nonserial writes"
exec sp_instmsg 17621, "dsync on"
exec sp_instmsg 17622, "dsync off"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17623, "directio on"
exec sp_instmsg 17624, "directio off"
exec sp_instmsg 17625, "raw device"
exec sp_instmsg 17626, "block device"
exec sp_instmsg 17627, "file system device"
exec sp_instmsg 17628, "unknown device type"
exec sp_instmsg 17629, "private"
exec sp_instmsg 17630, "REFIT PENDING"
exec sp_instmsg 17631, "virtual cache device"

/*
**Messages for "sp_helpindex"	17640
*/

exec sp_instmsg 17640, "Object does not have any indexes."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17641, "Object has the following indexes"

/*
**Messages for "sp_helpjoins"	17650
*/

exec sp_instmsg 17650, "First table doesn't exist."
exec sp_instmsg 17651, "Second table doesn't exist."
exec sp_instmsg 17652, "Object must be in your current database."

/*
**Messages for "sp_helpkey"	17660
*/

exec sp_instmsg 17660, "No defined keys for this object."
exec sp_instmsg 17661, " -- none --"
exec sp_instmsg 17662, "For information on declarative integrity features : PRIMARY KEY, UNIQUE, FOREIGN KEY, CHECK CONSTRAINT, REFERENTIAL CONSTRAINT, NULL/NOT NULL, and DEFAULT, use sp_helpconstraint system stored procedure."

/*
**Messages for "sp_helplanguage"	17670
*/

exec sp_instmsg 17670, "No alternate languages are available."
exec sp_instmsg 17671, "us_english is always available, even though it is not in master.dbo.syslanguages."

/*
**Messages for "sp_helplog"	17672
*/

exec sp_instmsg 17672, "In database '%1!', the log starts on device '%2!'."

/*
**Messages for "sp_helprotect"	17673
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17673, "All"
exec sp_instmsg 17674, "No such object or user exists in the database."
exec sp_instmsg 17675, "Illegal string found where the keyword grant is expected."
exec sp_instmsg 17676, "This may be a temporary object. Please execute procedure from your currently assigned temporary database. Use db_name(@@tempdbid) to find currently assigned temporary database."
exec sp_instmsg 17677, "sp_helprotect [name [, username [, 'grant' [,'none'|'granted'|'enabled'|role_name [,permission_name]]]]]"
exec sp_instmsg 17678, "Illegal role name '%1!' specified."

/*
**Messages for "sp_helptext"	17679
*/

exec sp_instmsg 17679, "There is no text for object '%1!'."

/*
**Messages for "sp_helpremotelogin"	17680
*/

exec sp_instmsg 17680, "There are no remote servers defined."
exec sp_instmsg 17681, "There are no remote logins for the remote server '%1!'."
exec sp_instmsg 17682, "There are no remote logins defined."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17683, "There are no remote logins for '%1!'."
exec sp_instmsg 17684, "There are no remote logins."
exec sp_instmsg 17685, "There are no remote logins for '%1!' on remote server '%2!'."
exec sp_instmsg 17686, "** mapped locally **"
exec sp_instmsg 17687, "** use local name **"

/*
**Messages for "sp_helpsort"	17690
*/

exec sp_instmsg 17690, "Character Set ="
exec sp_instmsg 17691, "Sort Order ="
exec sp_instmsg 17692, "Sort Order Description"
exec sp_instmsg 17693, "Characters, in Order"
exec sp_instmsg 17694, "Class 2 Character Set"

/*
**Messages for "sp_helpuser"	17700
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17700, "Users aliased to user."
exec sp_instmsg 17701, "The name supplied is a group name."
exec sp_instmsg 17702, "The name supplied is aliased to another user."
exec sp_instmsg 17703, "The name supplied is not a user, group, or aliased."
exec sp_instmsg 17704, "Curread label needs to dominate the hurdle of the current database."
exec sp_instmsg 17705, "The supplied name is a role name. Please resubmit the command with the name of a user, group or aliased."

/*
**Messages for "sp_logdevice"	17710
*/

exec sp_instmsg 17710, "This command has been ignored.  The device specified is the only non-log device available for the database and cannot be made log-only."
exec sp_instmsg 17711, "syslogs moved."

/*
**Messages for "sp_markreport"	17712
*/

exec sp_instmsg 17712, "Report must be in your current database."
exec sp_instmsg 17713, "No such report exists."

/*
**Messages for "sp_objectsegment"	17714
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17714, "not applicable"

/*
**Messages for "sp_logdevice"	17715
*/

exec sp_instmsg 17715, "The last-chance threshold for database %1! is now %2! pages."
exec sp_instmsg 17716, "Could not update the last-chance threshold for database %1!"

/*
**Messages for "sp_password"	17720
*/

exec sp_instmsg 17720, "Error:  Unable to set the Password."
exec sp_instmsg 17721, "Password correctly set."

/*
**Messages for "sp_placeobject"	17730
*/

exec sp_instmsg 17730, "Use sp_logdevice to move syslogs table."
exec sp_instmsg 17731, "You can't move system tables."
exec sp_instmsg 17732, "You do not own table '%1!'."
exec sp_instmsg 17733, "There is no table named '%1!'."
exec sp_instmsg 17734, "There is no index named '%1!' for table '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17735, "'%1!' is now on segment '%2!'."
exec sp_instmsg 17736, "You can't place a user table/index to logsegment."
exec sp_instmsg 17737, "Partitioned objects cannot be moved."
exec sp_instmsg 17738, "sp_placeobject is not allowed for %1!, as it is a virtually hashed table."
exec sp_instmsg 17739, "Segment %1! has a virtually hashed table; therefore, you cannot place an object on this segment."

/*
**Messages for "sp_primarykey"	17740
*/

exec sp_instmsg 17740, "Only the owner of the table may define a primary key."
exec sp_instmsg 17741, "Primary key already exists on table -- drop key first."
exec sp_instmsg 17742, "The table has no such first column."
exec sp_instmsg 17743, "The table has no such second column."
exec sp_instmsg 17744, "The table has no such third column."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17745, "The table has no such fourth column."
exec sp_instmsg 17746, "The table has no such fifth column."
exec sp_instmsg 17747, "The table has no such sixth column."
exec sp_instmsg 17748, "The table has no such seventh column."
exec sp_instmsg 17749, "The table has no such eighth column."
exec sp_instmsg 17750, "New primary key added."

/*
**Messages for "sp_addtype"	17751
*/

exec sp_instmsg 17751, "Illegal precision specified -- must be between 1 and 38."
exec sp_instmsg 17752, "Illegal scale specified -- must be less than precision."

/*
**Messages for "sp_bindefault"	17753
*/

exec sp_instmsg 17753, "The column already has a default. Bind disallowed."

/*
**Messages for "sp_addtype"	17754
*/

exec sp_instmsg 17754, "Illegal precision specified -- must be between 1 and 48."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17755, "User types with the identity property must be integer, smallint, tinyint or numeric with a scale of 0."
exec sp_instmsg 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."

/*
**Messages for "sp_recompile"	17760
*/

exec sp_instmsg 17760, "%1!' is a system table. Cannot use '%2!' on system tables."
exec sp_instmsg 17761, "Object '%1!' is not a table."
exec sp_instmsg 17762, "Each stored procedure and trigger that uses table '%1!' will be recompiled the next time it is executed."
exec sp_instmsg 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in updating the schemacnt column in sysobjects."

/*
**Messages for "sp_remoteoption"	17770
*/

exec sp_instmsg 17770, "Settable remote login options."
exec sp_instmsg 17771, "There is no remote user '%1!' mapped to local user '%2!' on remote server '%3!'."
exec sp_instmsg 17772, "Usage: sp_remoteoption [remoteserver, loginame, remotename, optname, {true | false}]"
exec sp_instmsg 17773, "Remote login option doesn't exist or can't be set by user."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17774, "Run sp_remoteoption with no parameters to see options."
exec sp_instmsg 17775, "Remote login option is not unique."
exec sp_instmsg 17776, "Only the System Administrator (SA) may set remote login options."
exec sp_instmsg 17777, "Option '%1!' turned on."
exec sp_instmsg 17778, "Option '%1!' turned off."

/*
**Messages for "sp_rename"	17780
*/

exec sp_instmsg 17780, "There is already a column named '%1!' in table '%2!'."
exec sp_instmsg 17781, "Column name has been changed."
exec sp_instmsg 17782, "You do not own a table, column or index of that name in the current database."
exec sp_instmsg 17783, "There is already an index named '%1!' for table '%2!'."
exec sp_instmsg 17784, "Index name has been changed."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17785, "Table or view names beginning with '#' are not allowed."
exec sp_instmsg 17786, "Object name cannot be changed either because it does not exist in this database, or you don't own it, or it is a system name."
exec sp_instmsg 17787, "Newname already exists in systypes."
exec sp_instmsg 17788, "Newname already exists in sysobjects."
exec sp_instmsg 17789, "Object name has been changed."

/*
**Messages for "sp_renamedb"	17790
*/

exec sp_instmsg 17790, "Only the System Administrator (SA) can change the name of a database."
exec sp_instmsg 17791, "A database with the new name already exists."
exec sp_instmsg 17792, "The databases master, model, tempdb, sybsecurity and sybsystemprocs cannot be renamed."
exec sp_instmsg 17793, "System Administrator (SA) must set database '%1!' to single-user mode with sp_dboption before using '%2!'."
exec sp_instmsg 17794, "Database is renamed and in single-user mode."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17795, "System Administrator (SA) must reset it to multi-user mode with sp_dboption."

/*
**Messages for "sp_serverinfo"	17796
*/

exec sp_instmsg 17796, "Legal request codes are as follows:"

/*
**Messages for "sp_serveroption"	17800
*/

exec sp_instmsg 17800, "No such server -- run sp_helpserver to list servers."
exec sp_instmsg 17801, "Usage: sp_serveroption [server, {{security mechanism, mechname}|{server cost, value}|{optname, {true | false}}}]"
exec sp_instmsg 17802, "Server option doesn't exist or can't be set by user."
exec sp_instmsg 17803, "Run sp_serveroption with no parameters to see options."
exec sp_instmsg 17804, "Server option is not unique."
exec sp_instmsg 17805, "Only the System Administrator (SA) may set server options."
exec sp_instmsg 17806, "Option can be set for remote servers only -- not the local server."
exec sp_instmsg 17807, "Settable server options."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17809, "Security services Confidentiality, Integrity and Mutual Authentication can be used only with Secured RPC Model 'B'."

/*
**Messages for "sp_setlangalias"	17810
*/

exec sp_instmsg 17810, "Language alias not changed."
exec sp_instmsg 17811, "Language alias reset."

/*
**Messages for "sp_spaceused"	17830
*/

exec sp_instmsg 17830, "Object is stored in 'sysprocedures' and has no space allocated directly."
exec sp_instmsg 17831, "Views don't have space allocated."
exec sp_instmsg 17832, "Not avail."

/*
**Messages for "sp_unbindefault"	17840
*/

exec sp_instmsg 17840, "Column or usertype must be in current database."
exec sp_instmsg 17841, "Default unbound from table column."
exec sp_instmsg 17842, "The specified column has no default."
exec sp_instmsg 17843, "You do not own a table with a column of that name."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17844, "You do not own a user datatype of that name."
exec sp_instmsg 17845, "The specified user datatype has no default."
exec sp_instmsg 17846, "Default unbound from datatype."
exec sp_instmsg 17847, "Columns of the user datatype specified had their defaults unbound."
exec sp_instmsg 17848, "You cannot unbind a declared default. Use ALTER TABLE command."

/*
**Messages for "sp_unbindrule"	17850
*/

exec sp_instmsg 17850, "Rule unbound from table column."
exec sp_instmsg 17851, "The specified column has no rule."
exec sp_instmsg 17852, "The specified user datatype has no rule."
exec sp_instmsg 17853, "Rule unbound from datatype."
exec sp_instmsg 17854, "Columns of the user datatype specified had their rules unbound."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17855, "You cannot unbind a declared constraint. Use ALTER TABLE command."
exec sp_instmsg 17856, "Usage: sp_unbindrule objectname [, NULL|'futureonly'] [, 'all'|'accessrule']"

/*
**Messages for "sp_indsuspect"	17860
*/

exec sp_instmsg 17860, "Suspect indexes in database %1!:"
exec sp_instmsg 17861, "There are no suspect indexes in database %1!."
exec sp_instmsg 17862, "Table must be in the current database."
exec sp_instmsg 17863, "There is no table named %1! in the current database."
exec sp_instmsg 17864, "Suspect indexes on table %1!:"
exec sp_instmsg 17865, "There are no suspect indexes on table %1!."

/*
**Messages for "sp_addthreshold"	17870
*/

exec sp_instmsg 17870, "Table '%1!' does not exist in database '%2!'. %3!"
exec sp_instmsg 17871, "There is no segment named '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17872, "This threshold is too close to one or more existing thresholds.  Thresholds must be no closer than 128 pages to each other."
exec sp_instmsg 17873, "Adding threshold for segment '%1!' at '%2!' pages."
exec sp_instmsg 17874, "A threshold at %1! pages is logically impossible for segment '%2!'.  Choose a value between %3! and %4! pages."
exec sp_instmsg 17875, "Only the DBO of database '%1!' or a user with System Administrator (SA) role may add, delete, or modify thresholds in that database."
exec sp_instmsg 17876, "Warning: The specified threshold level is greater than the existing number of free pages on this segment."
exec sp_instmsg 17877, "Insert of systhresholds row failed."
exec sp_instmsg 17878, "Rebuild of the database threshold table failed."
exec sp_instmsg 17879, "Only users that have System Administrator (SA) authorization granted directly may add, or modify thresholds in that database."

/*
**Messages for "sp_auth"	17880
*/

exec sp_instmsg 17880, "No such account -- nothing changed."
exec sp_instmsg 17881, "Invalid role -- nothing changed."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17882, "Invalid role -- nothing changed. The user must already have System Administrator (SA) role before being granted the Sybase Technical Support role."
exec sp_instmsg 17883, "Cannot revoke System Security Officer (SSO) role from the last remaining unlocked System Security Officer (SSO) account."
exec sp_instmsg 17884, "Neither 'grant' or 'revoke' is specified -- nothing changed."
exec sp_instmsg 17885, "Authorization updated."
exec sp_instmsg 17886, "Error in updating role."
exec sp_instmsg 17887, "Cannot revoke System Administrator (SA) role from the last remaining unlocked System Administrator (SA) account."
exec sp_instmsg 17888, "You must possess either the System Administrator (SA) or System Security Officer (SSO) role to execute %1!."

/*
**Messages for "sp_bindmsg"	17890
*/

exec sp_instmsg 17890, "Constraint name must be in `current' database."
exec sp_instmsg 17891, "Constraint name must belong to the current user."
exec sp_instmsg 17892, "Message id must be a user defined message."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17893, "No such message exists. Please create the message first using sp_addmessage."
exec sp_instmsg 17894, "No such referential or check constraint exists. Please check whether the constraint name is correct."
exec sp_instmsg 17895, "Constraint is bound to a message. You must unbind the message first."
exec sp_instmsg 17896, "Binding message failed unexpectedly. Please try again."
exec sp_instmsg 17897, "Message bound to constraint."

/*
**Messages for "sp_clearstats"	17900
*/

exec sp_instmsg 17900, "%1! login account(s) cleared."
exec sp_instmsg 17902, "You cannot run stored procedure '%1!' from a low durability database."

/*
**Messages for "sp_dropthreshold"	17903
*/

exec sp_instmsg 17903, "Table '%1!' does not exist in database '%2!' -- cannot drop thresholds."
exec sp_instmsg 17904, "Segment '%1!' does not have a threshold at '%2!' pages."
exec sp_instmsg 17905, "You may not drop the log's last-chance threshold."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17906, "Dropping threshold for segment '%1!' at '%2!' pages."
exec sp_instmsg 17907, "Delete of systhresholds row failed."

/*
**Messages for "sp_helpthreshold"	17910
*/

exec sp_instmsg 17910, "Database '%1!' has no thresholds -- table '%2!' does not exist."
exec sp_instmsg 17911, "Segment '%1!' does not exist."

/*
**Messages for "sp_lockaccount"	17912
*/

exec sp_instmsg 17912, "Error in locking the account."
exec sp_instmsg 17913, "Locked account(s):"
exec sp_instmsg 17914, "Account unlocked."
exec sp_instmsg 17915, "Warning: the specified account is currently active."
exec sp_instmsg 17916, "Cannot lock the last remaining unlocked SSO login."
exec sp_instmsg 17917, "Error: locktype must either be 'lock' or 'unlock'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17918, "Nothing changed."
exec sp_instmsg 17919, "Account locked."

/*
**Messages for "sp_modifylogin"	17920
*/

exec sp_instmsg 17920, "The given security label value is syntactically wrong."
exec sp_instmsg 17921, "The given maxwrite value cannot dominate the minwrite value from syslogins -- nothing changed."
exec sp_instmsg 17922, "The given minwrite value is not dominated by the maxwrite value from syslogins -- nothing changed."
exec sp_instmsg 17923, "The given security label is not dominated by the clearance value from syslogins -- nothing changed."
exec sp_instmsg 17924, "The given clearance value cannot dominate the %1! value from syslogins -- nothing changed."
exec sp_instmsg 17925, "You entered an invalid option name. No change was made."
exec sp_instmsg 17926, "Option changed."
exec sp_instmsg 17927, "Error in changing the value of the specified column."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17928, "Invalid role name specified -- nothing changed."
exec sp_instmsg 17929, "The specified role is not granted to the account -- nothing changed."
exec sp_instmsg 17930, "Specify a value for the option to be modified."
exec sp_instmsg 17931, "You cannot specify both @option and @column parameters. Specify only one of these parameters."
exec sp_instmsg 17932, "You entered an invalid value. No change was made."
exec sp_instmsg 17933, "Specify the name of the option to be modified."
exec sp_instmsg 17934, "All overrides for the password security option have been removed."

/*
**Messages for "sp_setsproc"	17935
*/

exec sp_instmsg 17935, "Error in updating checkauths in memory -- nothing changed."
exec sp_instmsg 17936, "Neither 'on' or 'off' is specified -- nothing changed."
exec sp_instmsg 17937, "Error in updating checkauths in Sysobjects."

/*
**Messages for "sp_unbindmsg"	17940
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 17940, "Constraint is not bound to any message."
exec sp_instmsg 17941, "Unbinding message failed unexpectedly. Please try again."
exec sp_instmsg 17942, "Message unbound from constraint."

/*
**Messages for "sp_displayaccount"	17943
*/

exec sp_instmsg 17943, "Suid: %1!"
exec sp_instmsg 17944, "Loginame: %1!"
exec sp_instmsg 17945, "Fullname: %1!"
exec sp_instmsg 17946, "Maximum Write Level: %1!"
exec sp_instmsg 17947, "Minimum Write Level: %1!"
exec sp_instmsg 17948, "Maximum Read Level: %1!"
exec sp_instmsg 17949, "Locked: %1!"
go

dump transaction master with truncate_only
go

exec sp_instmsg 17950, "Date of Last Password Change: %1!"
exec sp_instmsg 17951, "Configured Authorization:"

/*
**Messages for "sp_setreplicate"	17960
*/

exec sp_instmsg 17960, "Replication Server support is not enabled.  Replication Server support must be enabled before you can change the replication status of '%1!'."
exec sp_instmsg 17961, "Usage: sp_setreplicate object_name, {true | false}"
exec sp_instmsg 17962, "The replication status for '%1!' is already set to %2!. Replication status for '%3!' does not change."
exec sp_instmsg 17963, "An object with the same name, but owned by a different user is already being replicated.  The object '%1!' cannot be replicated."
exec sp_instmsg 17964, "The replication status for '%1!' is set to %2!."
exec sp_instmsg 17965, "The replication status for '%1!' is currently %2!."
exec sp_instmsg 17966, "Due to system failure, the replication status for '%1!' has not been changed."
exec sp_instmsg 17967, "Only the System Administrator (SA) or the Database Owner (DBO) may execute this stored procedure."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17968, "The built-in function logschema() failed for '%1!'. See the other messages printed along with this message for more information."
exec sp_instmsg 17969, "No user table or procedure named '%1!' exists in the current database."

/*
**Messages for "sp_syntax"	17970
*/

exec sp_instmsg 17970, "sp_syntax provides syntax help for Sybase products."
exec sp_instmsg 17971, "These modules are installed on this Server:"
exec sp_instmsg 17972, "Usage: sp_syntax command [, module [, language]]"
exec sp_instmsg 17973, "No command or routine has a name like '%%%1!%%'"
exec sp_instmsg 17974, "No module has a name like '%%%1!%%'"
exec sp_instmsg 17975, "No command or routine has a name like '%%%1!%%' and a module like '%%%2!%%'"

/*
**Messages for "sp_auditdatabase"	17976
*/

exec sp_instmsg 17976, "No databases currently have auditing enabled."
exec sp_instmsg 17977, "'%1!' does not exist."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17978, "'%1!' has the following auditing options enabled:"
exec sp_instmsg 17979, "Invalid second argument.  Valid choices are 'ok', 'fail', 'both', or 'off'."
exec sp_instmsg 17980, "Invalid third argument.  Valid choices are 'd', 'u', 'o', 'g', 'r', or 't'."
exec sp_instmsg 17981, "Error updating the audit flags in the system catalogs. This is a system error.  Contact a user with System Administrator (SA) role."
exec sp_instmsg 17982, "Audit option has been changed and has taken effect immediately."
exec sp_instmsg 17983, "Audit option has been changed and will take effect after a reboot."
exec sp_instmsg 17984, "Error updating the audit flags in memory.  This is a system error.  Contact a user with System Administrator (SA) role."

/*
**Messages for "sp_auditinstall"	17985
*/

exec sp_instmsg 17985, "You must be in the sybsecurity database to run this procedure."
exec sp_instmsg 17986, "Device name ignored because no segment name was provided."
exec sp_instmsg 17987, "Segment '%1!' does not exist in the sybsecurity database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17988, "Creating segment '%1!' on device '%2!'..."
exec sp_instmsg 17989, "Creating sysaudits table on the '%1!' segment..."
exec sp_instmsg 17990, "Dumping transaction log in sybsecurity with no_log..."

/*
**Messages for "sp_auditlogin"	17991
*/

exec sp_instmsg 17991, "No logins currently have auditing enabled."
exec sp_instmsg 17992, "Invalid second argument.  Valid options are 'table', 'view', or 'cmdtext'."
exec sp_instmsg 17993, "'%1!' is not a valid argument."

/*
**Messages for "sp_auditobject"	17994
*/

exec sp_instmsg 17994, "Only 'default table' or 'default view' is allowed."
exec sp_instmsg 17995, "Only 'ok', 'fail', 'both' or 'off' can be specified."
exec sp_instmsg 17996, "You must provide 'ok', 'fail', 'both', or 'off' preceding the 'dusi' string."
exec sp_instmsg 17997, "Error:  An invalid letter was specified.  Use only 'd', 'u', 's', or 'i'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 17998, "No databases currently have %1! auditing enabled."
exec sp_instmsg 17999, "'%1!' has the following %2! auditing options enabled."
exec sp_instmsg 18000, "No objects currently have auditing enabled."
exec sp_instmsg 18001, "An object name must be provided."

/*
**Messages for "sp_auditoption"	18002
*/

exec sp_instmsg 18002, "You must provide an audit option."
exec sp_instmsg 18003, "Audit option '%1!' does not exist.  Valid options are:"
exec sp_instmsg 18004, "Audit option '%1!' is ambiguous.  Ambiguous options are:"
exec sp_instmsg 18005, "'%1!' is an invalid audit option string in this context."

/*
**Messages for "sp_auditsproc"	18006
*/

exec sp_instmsg 18006, "The third argument was not necessary; therefore, it was ignored."
exec sp_instmsg 18007, "No databases currently have default sproc/trigger auditing enabled."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18008, "'%1!' has the following default sproc/trigger auditing enabled:"
exec sp_instmsg 18009, "No sprocs/triggers currently have auditing enabled."
exec sp_instmsg 18010, "A sproc/trigger name or 'all' must be provided."

/*
**Messages for "sp_auditobject"	18011
*/

exec sp_instmsg 18011, "Object name must be qualified with the owner name."

/*
**Messages for "sp_auditsproc"	18012
*/

exec sp_instmsg 18012, "Sproc/trigger name must be qualified with the owner name."

/*
**Messages for "sp_lockaccount"	18013
*/

exec sp_instmsg 18013, "Cannot lock the last remaining unlocked SA account."

/*
**Messages for "sp_configurelogin"	18015
*/

exec sp_instmsg 18015, "%1! must be a valid sensitivity_boundary label."
exec sp_instmsg 18016, "The connection label supplied is an invalid sensitivity label."
exec sp_instmsg 18017, "%1! must dominate %2!."
exec sp_instmsg 18018, "New login configured."

/*
**Messages for "sp_trustlogin"	18019
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18019, "Must specify 'on' or 'off'."
exec sp_instmsg 18020, "Account updated."

/*
**Messages for "sp_auditobject"	18021
*/

exec sp_instmsg 18021, "Object name may be qualified with the owner name only; please don't qualify with the database name."

/*
**Messages for "sp_auditsproc"	18022
*/

exec sp_instmsg 18022, "Procedure/trigger name may be qualified with the owner name only; please don't qualify with the database name."

/*
**Messages for "sp_trustlogin"	18023
*/

exec sp_instmsg 18023, "The optional %1! and %2!  labels must all be non-NULL if at least one of them is specified."

/*
**Messages for "sp_helpconstr"	18024
*/

exec sp_instmsg 18024, "Object does not have any declarative constraints."

/*
**Messages for "sp_sproclabels"	18025
*/

exec sp_instmsg 18025, "Non-NULL labels specified in 'off' action."
exec sp_instmsg 18026, "Illegal action command specified."
exec sp_instmsg 18027, "Procedure remains in a non-executable state."
exec sp_instmsg 18028, "Certified state modified for object '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18029, "The procedures label configuration has changed."
exec sp_instmsg 18030, "No change, update failed with error: %1!"

/*
**Messages for "sp_modifythreshold"	18031
*/

exec sp_instmsg 18031, "This procedure can only affect thresholds in the current database.  Say 'USE %1!', then run this procedure again."
exec sp_instmsg 18032, "You may not alter the free space or segment name of the log's last-chance threshold."

/*
**Messages for "sp_dropuser"	18033
*/

exec sp_instmsg 18033, "You cannot drop user because user '%1!' owns thresholds in database."

/*
**Messages for "sp_auditinstall"	18034
*/

exec sp_instmsg 18034, "The sysaudits table already exists.  This table will be truncated and re-used.  Therefore, segment and device parameters, if supplied, will be ignored."

/*
**Messages for "sp_checkreswords"	18035
*/

exec sp_instmsg 18035, "Reserved Words Used as Database Object Names for Database,"
exec sp_instmsg 18036, " Upgrade renames sysobjects.schema to sysobjects.schemacnt."
exec sp_instmsg 18037, " Found no reserved words used as names for database-wide objects."
exec sp_instmsg 18038, " Found no reserved words used as database object names."

/*
**Messages for "sp_pkeys"	18039
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18039, "Table qualifier must be name of current database."
exec sp_instmsg 18040, "Catalog procedure '%1!' can not be run in a transaction."

/*
**Messages for "sp_stored_procedures"	18041
*/

exec sp_instmsg 18041, "Stored procedure qualifier must be name of current database."

/*
**Messages for "sp_special_columns"	18042
*/

exec sp_instmsg 18042, "Illegal value for 'col_type' argument. Legal values are 'V' or 'R'."

/*
**Messages for "sp_fkeys"	18043
*/

exec sp_instmsg 18043, "primary key table name or foreign key table name must be given."
exec sp_instmsg 18044, "%1! table qualifier must be name of current database."

/*
**Messages for "sp_locklogin"	18045
*/

exec sp_instmsg 18045, "Cannot lock the last remaining unlocked SA login."

/*
**Messages for "sp_role"	18046
*/

exec sp_instmsg 18046, "Cannot revoke the SA role from the last remaining unlocked SA login."

/*
**Messages for "sp_syntax"	18047
*/

exec sp_instmsg 18047, "There is not enough room in the default devices to create the sybsyntax database."
exec sp_instmsg 18048, "The sybsyntax database could not be created."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18049, " Syntax Help"

/*
**Messages for "sp_fkeys"	18050
*/

exec sp_instmsg 18050, "Foreign key"
exec sp_instmsg 18051, "Primary key"

/*
**Messages for "sp_lock"	18052
*/

exec sp_instmsg 18052, "The class column will display the cursor name for locks associated with a cursor for the current user and the cursor id for other users."

/*
**Messages for "sp_dropuser"	18053
*/

exec sp_instmsg 18053, "User '%1!' was granted grantable privileges by the following users:"

/*
**Messages for "sp_estspace"	18054
*/

exec sp_instmsg 18054, "Table contains text/image type columns. You must specify the total length per row for these columns in the argument list."

/*
**Messages for "sp_fixindex"	18055
*/

exec sp_instmsg 18055, "Procedure should be used on system tables only."
exec sp_instmsg 18056, "Cannot re-create index on this table."
exec sp_instmsg 18057, "The index with id 1 on sysobjects can not be recreated."

/*
**Messages for "sp_rename"	18058
*/

exec sp_instmsg 18058, "Name of user-defined type name changed."

/*
**Messages for "sp_server_info"	18059
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18059, "Attribute id %1! is not supported."

/*
**Messages for "sp_crtsybsystemprocs"	18060
*/

exec sp_instmsg 18060, "The database sybsystemprocs needs to be atleast %1!MB in size. It is currently at %2!MB."
exec sp_instmsg 18061, "Installing system stored procedures in the sybsystemprocs database."
exec sp_instmsg 18062, "Database sybsystemprocs of size %1!MB is being created on the default device."
exec sp_instmsg 18063, "Done creating database sybsystemprocs on the default device."
exec sp_instmsg 18064, "Cannot create database sybsystemprocs of size %1!MB on the default device because there is not enough space. Please create this database elsewhere and rerun the installmaster script."

/*
**Messages for "sp_auditsproc"	18065
*/

exec sp_instmsg 18065, "Illegal fourth argument. Valid arguments are: 'access', 'trusted_invocation'"

/*
**Messages for "sp_auditdatabase"	18066
*/

exec sp_instmsg 18066, "Invalid third argument.  Valid choices are 'd', 'u', 'o', 'g', 'r', 't' or 'a'"

/*
**Messages for "sp_displaylogin"	18067
*/

exec sp_instmsg 18067, "Clearance Level: %1!"

/*
**Messages for "sproclabels"	18068
*/

exec sp_instmsg 18068, "Stored Procedure/ Trigger does not exist in this database"

/*
**Messages for "sp_grantlogin"	18069
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18069, "Access granted."

/*
**Messages for "sp_revokelogin"	18070
*/

exec sp_instmsg 18070, "Access revoked."

/*
**Messages for "sp_rename"	18071
*/

exec sp_instmsg 18071, "Set curwrite to the level of table/column."

/*
**Messages for "sp_addsegment"	18072
*/

exec sp_instmsg 18072, "Setting curwrite to data_low for updating syssegments failed."

/*
**Messages for "sp_auditdatabase"	18073
*/

exec sp_instmsg 18073, "Set command failed. Set your maxwrite and minwrite labels to correct level."

/*
**Messages for "sp_auditobject"	18074
*/

exec sp_instmsg 18074, "Curwrite label could not be set to the object level. Set your maxwrite and minwrite labels correctly."

/*
**Messages for "sp_dropgroup"	18075
*/

exec sp_instmsg 18075, "Set your maxwrite label correctly."

/*
**Messages for "sp_droptype"	18076
*/

exec sp_instmsg 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."

/*
**Messages for "sp_rename"	18077
*/

exec sp_instmsg 18077, "Set curwrite to the level of index."
exec sp_instmsg 18078, "Set curwrite to the level of the object in systypes."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18079, "Set curwrite to the level of the object in sysobjects."
exec sp_instmsg 18080, "Certified state of object '%1!' has been set to 'Suspect'."

/*
**Messages for "sp_sproclabels"	18081
*/

exec sp_instmsg 18081, "Object name cannot be NULL if action is non-NULL."
exec sp_instmsg 18082, "At least one of the labels must be non-NULL."

/*
**Messages for "sp_configurelogin"	18083
*/

exec sp_instmsg 18083, "Login account %1! has already been configured. Use sp_trustlogin to modify security profile of this account."

/*
**Messages for "sp_addthreshold,sp_modifythreshold"	18084
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18084, "A threshold at %1! pages for segment '%2!' is too close to the maximum size of the database. Because of this, the threshold will not fire more than once per ASE re-boot. Modify the value using sp_modifythreshold to be between %3! and %4! pages."

/*
**Messages for "sp_helpartition"	18085
*/

exec sp_instmsg 18085, "Object is not partitioned."

/*
**Messages for "sp_bindcache"	18086
*/

exec sp_instmsg 18086, "Specified named cache does not exist."
exec sp_instmsg 18087, "You must be in Master to bind or unbind a database."
exec sp_instmsg 18088, "The target database does not exist."
exec sp_instmsg 18089, "The 'master' database cannot be bound to or unbound from a named cache."
exec sp_instmsg 18090, "The target object does not exist."
exec sp_instmsg 18091, "The target index does not exist."
exec sp_instmsg 18092, "Only logs may be bound to this cache."

/*
**Messages for "sp_movemass"	18093
*/

exec sp_instmsg 18093, "The specified source buffer pool does not exist."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18094, "Not enough memory in source buffer pool to satisfy request."

/*
**Messages for "sp_poolconfig"	18095
*/

exec sp_instmsg 18095, "The destination buffer pool size must be a minimum of %1! kilobytes."

/*
**Messages for "sp_movemass"	18096
*/

exec sp_instmsg 18096, "Request will result in creating a source buffer pool less than the minimum of 512 kilobytes."

/*
**Messages for "sp_bindcache"	18098
*/

exec sp_instmsg 18098, "Individual tables in a temporary database cannot be bound to or unbound from named caches. However, the entire temporary database may be bound or unbound."

/*
**Messages for "sp_setrepdb"	18099
*/

exec sp_instmsg 18099, "Usage: sp_setrepdb {true | false}"

/*
**Messages for "sp_setreptable"	18100
*/

exec sp_instmsg 18100, "Usage: sp_setreptable [ table_name [, {true | false | never} [, {owner_on | owner_off} [, use_index ] ] ] ]"
exec sp_instmsg 18101, "The specified table must be in the current database."
exec sp_instmsg 18102, "Table '%1!' does not exist in this database."
exec sp_instmsg 18103, "An object with the same name, but owned by a different user, is already being replicated.  The table '%1!' cannot be replicated."

/*
**Messages for "sp_setrepproc"	18104
*/

exec sp_instmsg 18104, "table"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18105, "function"
exec sp_instmsg 18106, "The specified stored procedure must be in the current database."
exec sp_instmsg 18107, "Stored procedure '%1!' does not exist in this database."
exec sp_instmsg 18108, "Usage: sp_setrepproc [proc_name [, {'false' | 'table' | {'function' [,{'log_current' | 'log_sproc'}]}}]]"

/*
**Messages for "sp_setrepcol"	18109
*/

exec sp_instmsg 18109, "Usage: sp_setrepcol table_name [, column_name [, {do_not_replicate | always_replicate | replicate_if_changed} [, use_index ] ] ]"
exec sp_instmsg 18110, "The table '%1!' is not marked as replicated."
exec sp_instmsg 18111, "do_not_replicate"
exec sp_instmsg 18112, "always_replicate"
exec sp_instmsg 18113, "replicate_if_changed"
exec sp_instmsg 18114, "A table name must be provided."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18115, "No Text/Image or off-row object columns in '%1!'."
exec sp_instmsg 18116, "The replication status for all Text/Image and off-row object columns in '%1!' has been set to %2!."
exec sp_instmsg 18117, "Column '%1!' does not exist in '%2!' or it is not a Text/Image or off-row object column."
exec sp_instmsg 18118, "Object '%1!' does not exist in this database."

/*
**Messages for "sp_procqmode"	18120
*/

exec sp_instmsg 18120, "System 11 or later"

/*
**Messages for "sp_chgattribute"	18121
*/

exec sp_instmsg 18121, "Unrecognized change attribute option."
exec sp_instmsg 18122, "'%1!' attribute of object '%2!' changed to %3!."

/*
**Messages for "sp_configure"	18123
*/

exec sp_instmsg 18123, "Configuration option changed. Since the option is static, Adaptive Server must be rebooted in order for the change to take effect."
exec sp_instmsg 18124, "No matching configuration options.  Here is a listing of groups:"
exec sp_instmsg 18125, "Must provide the parameter 'filename'."

/*
**Messages for "sp_logiosize"	18126
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18126, "Log I/O Size must be a power of 2, and is between a logical pagesize to size of 8 logical pages. For example, if the logical pagesize is %1!K, the log I/O size should be %2!, %3!, %4!, or %5![k|K]."
exec sp_instmsg 18127, "You must have System Administrator (SA) role to execute this stored procedure."
exec sp_instmsg 18128, "Unable to change the log I/O size. The memory pool for the specified log I/O size does not exist."
exec sp_instmsg 18129, "Log I/O size is set to %1! Kbytes."
exec sp_instmsg 18130, "sp_logiosize failed. Please contact Sybase Technical Support to help you resolve the problem."
exec sp_instmsg 18131, "Log I/O Size value '%1!' is illegal."
exec sp_instmsg 18132, "The transaction log for database '%1!' will use I/O size of %2! Kbytes."

/*
**Messages for "sp_configure"	18133
*/

exec sp_instmsg 18133, "The character set, '%1!', is invalid since it is not defined in Syscharsets."
exec sp_instmsg 18134, "The sortorder, '%1!', is invalid since it is not defined in Syscharsets."

/*
**Messages for "sp_cacheconfig"	18135
*/

exec sp_instmsg 18135, "The specified named cache '%1!' does not exist."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18136, "The cache type can only be specified once."
exec sp_instmsg 18137, "Attempt to delete the default data cache. The default cache may not be deleted."

/*
**Messages for "sp_poolconfig"	18138
*/

exec sp_instmsg 18138, "A cache name must be supplied."
exec sp_instmsg 18139, "Syntax error encountered. Parameter must be of the form 'wash = int[KMGP]'."

/*
**Messages for "sp_cacheconfig"	18140
*/

exec sp_instmsg 18140, "Cannot modify a cache type to be 'log only' when non-log objects are bound to it. Use sp_helpcache to print out bound objects and sp_unbindcache to delete the cache bindings."

/*
**Messages for "sp_poolconfig"	18141
*/

exec sp_instmsg 18141, "Syntax error encountered. Specification of the wash size must be of the form 'wash = int[PKMG]'."
exec sp_instmsg 18142, "I/O size of the memory pool is expected as the third argument."
exec sp_instmsg 18143, "The source pool (%1! buffers, total size %2!) is not large enough to satisfy the request to move %3! of memory."
exec sp_instmsg 18144, "Source pool (%1!) and destination pool (%2!) are the same pool. The source and destination pools must be different."
exec sp_instmsg 18145, "Less memory moved than requested in cache '%1!'. Requested size = %2! Kb: from pool = %3!, to pool = %4!, actual memory moved = %5! Kb."

/*
**Messages for "sp_aux_getsize"	18146
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18146, "Syntax error encountered. Sizes must be of the form int[KMGP]. For example, a size of 5 megabytes may be specified as '5M'."

/*
**Messages for "sp_poolconfig"	18147
*/

exec sp_instmsg 18147, "Invalid buffer size of %1! encountered. Valid buffer sizes are powers of two between %2! and %3! kilobytes inclusive."
exec sp_instmsg 18148, "The specified pool (%1!) does not exist in named cache '%2!'."

/*
**Messages for "sp_aux_getsize"	18149
*/

exec sp_instmsg 18149, "Invalid size of %1! encountered. Sizes must be greater than zero."

/*
**Messages for "sp_displaylevel"	18150
*/

exec sp_instmsg 18150, "The login '%1!' does not exist."
exec sp_instmsg 18151, "The current display level for login '%1!' is '%2!'."
exec sp_instmsg 18152, "Invalid display level. The valid values are 'basic', 'intermediate' or 'comprehensive'."
exec sp_instmsg 18153, "The display level for login '%1!' has been changed to '%2!'."

/*
**Messages for "sp_aux_parse_entity"	18154
*/

exec sp_instmsg 18154, "Object '%1!' is not a table."

/*
**Messages for "sp_cacheconfig"	18155
*/

exec sp_instmsg 18155, "The cache type can be 'logonly', 'mixed' or 'inmemory_storage' only. Replacement policy can be 'strict', 'relaxed' or 'none' only."

/*
**Messages for "sp_bindcache"	18156
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18156, "Usage: sp_unbindcache dbname [, [ownername.]tablename [, indexname | 'text only' | 'table only']]"

/*
**Messages for "sp_setrepdb"	18157
*/

exec sp_instmsg 18157, "The stored procedure 'sp_setrepdb' is currently not supported."

/*
**Messages for "sp_setpglockpromote"	18158
*/

exec sp_instmsg 18158, "At least one of the parameters 'new_lwm', 'new_hwm' or 'new_pct' must be non-NULL to execute this procedure."
exec sp_instmsg 18159, "You must be in the 'master' database to add, change or drop lock promotion attributes for a user database."
exec sp_instmsg 18160, "Please specify a non-NULL value for '%1!', since it has not been set previously with a non-NULL value."
exec sp_instmsg 18161, "Object name parameter must be NULL for Server-wide lock promotion attributes. Using NULL instead of - '%1!'."
exec sp_instmsg 18162, "'%1!' is a not a user table. '%2!' can be used only on user tables."
exec sp_instmsg 18163, "The lock promotion LWM value '%1!' cannot be greater than the lock promotion HWM value '%2!'."
exec sp_instmsg 18164, "Invalid value specified for 'scope' parameter. Valid values are 'SERVER','DATABASE' or 'TABLE'."
exec sp_instmsg 18165, "The 'lock promotion' attributes of '%1!', '%2!' have been changed. The new values are '%3!'."

/*
**Messages for "sp_dropglockpromote"	18166
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18166, "Lock promotion attribute does not exist for '%1!', '%2!'. Cannot delete it."
exec sp_instmsg 18167, "Lock promotion attribute of object '%1!' has been dropped."
exec sp_instmsg 18168, "Invalid value '%1!', specified for 'scope' parameter. Valid values are 'DATABASE' or 'TABLE'."
exec sp_instmsg 18169, "Server-wide lock promotion values cannot be dropped. Use 'sp_configure' to restore server-wide defaults."

/*
**Messages for "sp_bindcache"	18170
*/

exec sp_instmsg 18170, "Usage: sp_bindcache cachename, dbname [, [ownername.]tablename [, indexname | 'text only' | 'table only']]"

/*
**Messages for "sp_aux_parse_entity"	18171
*/

exec sp_instmsg 18171, "The table must have a text column if 'text only' is specified."

/*
**Messages for "sp_cacheconfig"	18172
*/

exec sp_instmsg 18172, "The change is completed. ASE must be rebooted for the change to take effect."

/*
**Messages for "sp_cachestrategy"	18173
*/

exec sp_instmsg 18173, "Only the System Administrator (SA) or the Object Owner may execute this stored Procedure."

/*
**Messages for "sp_helpcache"	18174
*/

exec sp_instmsg 18174, "The database '%1!' is offline. To obtain cache-bindings for objects in this database, please online the database and rerun sp_helpcache."

/*
**Messages for "sp_bindcache"	18175
*/

exec sp_instmsg 18175, "Specified named cache is not active yet. ASE must be rebooted to activate the named cache."

/*
**Messages for "sp_cachestrategy"	18176
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18176, "Usage: sp_cachestrategy dbname, [ownername.]tablename [, indexname | 'text only' | 'table only' [, { prefetch | mru }, { 'on' | 'off'}]]"

/*
**Messages for "sp_cacheconfig"	18177
*/

exec sp_instmsg 18177, "Usage: sp_cacheconfig [ cachename [, 'cache_size[K|P|M|G]' ] [, logonly | mixed | inmemory_storage] [, strict | relaxed | none] [, cache_partition = [1|2|4|8|16|32|64]][, 'instance instance_name']]"

/*
**Messages for "sp_sysmon"	18179
*/

exec sp_instmsg 18179, "Invalid parameter '%1!'. Usage: sp_sysmon {'begin_sample'|{{'end_sample'|'hh:mm:ss'}[,section]}} [,@applmon={'appl_only'|'appl_and_login'|'no_appl'|'noclear'|'clear'} [, @filter={cache wizard filter value|'noclear'|'clear'} [, @dumpcounters={'y'|'n'|'noclear'|'clear'|NULL} [, @option={'noclear'|'clear'|NULL}]]]]"

/*
**Messages for "sp_helptext"	18180
*/

exec sp_instmsg 18180, "Configuration Parameter 'select on syscomments.text' is set to 0. Only the object owner or user with sa_role can run sp_helptext on this object."

/*
**Messages for "sp_add_time_range"	18182
*/

exec sp_instmsg 18182, "Timerange name must be non-NULL."
exec sp_instmsg 18183, "Starting day must be non-NULL."
exec sp_instmsg 18184, "Ending day must be non-NULL."
exec sp_instmsg 18185, "Starting time must be non-NULL."
exec sp_instmsg 18186, "Unknown startday %1!."
exec sp_instmsg 18187, "Unknown endday %1!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18188, "Range '%1!' already exists."
exec sp_instmsg 18189, "Unknown starting time value %1!."
exec sp_instmsg 18190, "Unknown ending time value %1!."
exec sp_instmsg 18191, "Ending time must be later in the day than starting time."
exec sp_instmsg 18192, "New time range created. ID number is %1!."

/*
**Messages for "sp_drop_time_range"	18193
*/

exec sp_instmsg 18193, "Unknown time range '%1!'."
exec sp_instmsg 18194, "`at all times' range may not be dropped."
exec sp_instmsg 18195, "There are still limits using this range."
exec sp_instmsg 18196, "Time range '%1!' dropped."

/*
**Messages for "sp_modify_time_range"	18197
*/

exec sp_instmsg 18197, "At least one of the starting day, ending day, starting time, or ending time must be non-NULL."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18198, "Timerange name must be non-NULL."
exec sp_instmsg 18199, "Unknown time range name '%1!'."
exec sp_instmsg 18200, "at all times' range may not be modified."
exec sp_instmsg 18201, "Modification would cause overlap with range %1!."

/*
**Messages for "sp_add_resource_limit"	18202
*/

exec sp_instmsg 18202, "At least one of the login or application name must be non-NULL."
exec sp_instmsg 18203, "Limit type must be non-NULL."
exec sp_instmsg 18204, "Unknown limit type '%1!'."
exec sp_instmsg 18205, "Limit value must be non-NULL."
exec sp_instmsg 18206, "Illegal limit value %1!. Value must be non-negative."
exec sp_instmsg 18207, "Illegal action %1!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18208, "Illegal enforcement-time value %1! for this limit type."
exec sp_instmsg 18209, "Illegal scope value %1! for this limit type."
exec sp_instmsg 18210, "Unknown starting time value '%1!' found in systimeranges."
exec sp_instmsg 18211, "Unknown ending time value '%1!' found in systimeranges."
exec sp_instmsg 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
exec sp_instmsg 18213, "This user/application can have only one limit for each distinct combination of time range, limit type, enforcement time and scope."
exec sp_instmsg 18214, "New resource limit created."

/*
**Messages for "sp_drop_resource_limit"	18215
*/

exec sp_instmsg 18215, "Resource limit dropped."

/*
**Messages for "sp_help_resource_limit"	18216
*/

exec sp_instmsg 18216, "Users other than the System Administrator (SA) may only view limits applicable to themselves."
exec sp_instmsg 18217, "Illegal limit time argument '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18218, "Unknown limitday value '%1!'."

/*
**Messages for "sp_add_time_range"	18219
*/

exec sp_instmsg 18219, "Ending time must be non-NULL."

/*
**Messages for "sp_drop_resource_limit"	18220
*/

exec sp_instmsg 18220, "No such limit found in sysresourcelimits."

/*
**Messages for "sp_audit"	18221
*/

exec sp_instmsg 18221, "Setting must be 'off', 'on', 'pass', 'fail'."
exec sp_instmsg 18222, "Object name must be 'all'."
exec sp_instmsg 18223, "User auditing for '%1!' is '%2!'."
exec sp_instmsg 18224, "'%1!' is not a valid login name or role name."
exec sp_instmsg 18225, "Login name must be 'all'."
exec sp_instmsg 18226, "'%1!' is not a valid login name."
exec sp_instmsg 18227, "'%1!' is not in the current database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18228, "'%1!' is not a valid object name."
exec sp_instmsg 18229, "'%1!' is not a valid audit option."
exec sp_instmsg 18230, "Role auditing for '%1!' is '%2!'."
exec sp_instmsg 18231, "Server-wide auditing '%1!' is '%2!'."
exec sp_instmsg 18232, "Default auditing '%1!' for '%2!' in database '%3!' is '%4!'."
exec sp_instmsg 18233, "Database-specific auditing '%1!' in database '%2!' is '%3!'."
exec sp_instmsg 18234, "User-specific auditing '%1!' for user '%2!' is '%3!'."
exec sp_instmsg 18235, "Object-specific auditing '%1!' for object '%2!' is '%3!'."
exec sp_instmsg 18236, "Error updating the audit flags. This is a system error. Contact a user with System Security Officer (SSO) Role."
exec sp_instmsg 18237, "An Error in spt_values table. This is a system error. Contact a user with System Security Officer (SSO) Role."

/*
**Messages for "sp_addaudittable"	18238
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18238, "You cannot create a total of more than 8 audit tables."
exec sp_instmsg 18239, "Creating segment '%1!' on '%2!' device."
exec sp_instmsg 18240, "Creating table '%1!' on '%2!' segment."

/*
**Messages for "sp_audit"	18241
*/

exec sp_instmsg 18241, "The name '%1!' is not a valid database name."

/*
**Messages for "sp_modify_time_range"	18242
*/

exec sp_instmsg 18242, "No such time range found in systimeranges."

/*
**Messages for "sp_helpconstraint"	18243
*/

exec sp_instmsg 18243, "Total Number of Referential Constraints: %1!"
exec sp_instmsg 18244, "-- Number of references made by this table: %1!"
exec sp_instmsg 18245, "-- Number of references to this table: %1!"
exec sp_instmsg 18246, "-- Number of self references to this table: %1!"
exec sp_instmsg 18247, "Formula for Calculation:"

/*
**Messages for "sp_addengine"	18248
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18248, "Validation of engine group modification failed. Check server errorlog for any additional information."
exec sp_instmsg 18249, "Name '%1!' is not valid."
exec sp_instmsg 18250, "Failed to add engine '%1!' to engine group '%2!'. Check server errorlog for any additional information. List of engines in engine group unchanged."
exec sp_instmsg 18251, "Cannot modify pre-defined engine groups."

/*
**Messages for "sp_addexeclass"	18252
*/

exec sp_instmsg 18252, "'%1!' value '%2!' is not valid."
exec sp_instmsg 18253, "No specification for engine group '%1!' exists."
exec sp_instmsg 18254, "Failed to update attributes of objects assigned to class '%1!'. Check server errorlog for any additional information."

/*
**Messages for "sp_bindexeclass"	18255
*/

exec sp_instmsg 18255, "%1! cannot be NULL."
exec sp_instmsg 18256, "%1! is not a valid object type for this stored procedure."
exec sp_instmsg 18257, "No definition for classname '%1!' exists."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18258, "Scope '%1!' is not a valid name."
exec sp_instmsg 18259, "No login with the specified name '%1!' exists."
exec sp_instmsg 18260, "Validation of execution class binding failed. Check server errorlog for any additional information."
exec sp_instmsg 18261, "Failed to bind '%1!' to execution class '%2!'. Check server errorlog for any additional information."

/*
**Messages for "sp_clearpsexe"	18262
*/

exec sp_instmsg 18262, "A non-SA user can not modify attributes of another process."
exec sp_instmsg 18263, "A non-SA user can only modify its priority value."
exec sp_instmsg 18264, "No ASE process with the specified ID exists."
exec sp_instmsg 18265, "No specification for the specified process exists."
exec sp_instmsg 18266, "%1! is not a valid execution attribute."
exec sp_instmsg 18267, "Failed to clear value of attribute '%1!' for spid '%2!'. Check server errorlog for any additional information."

/*
**Messages for "sp_dropengine"	18268
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18268, "Internal Error: Wrong engine list format in sysattributes."
exec sp_instmsg 18269, "Cannot drop engine group used in class definition."
exec sp_instmsg 18270, "Failed to drop engine '%1!' from engine group '%2!'. Check server errorlog for any additional information. List of engines in engine group unchanged."
exec sp_instmsg 18271, "Cannot drop engine group bound to an ASE process."

/*
**Messages for "sp_dropexeclass"	18272
*/

exec sp_instmsg 18272, "%1! is not a valid execution class name."
exec sp_instmsg 18273, "Either '%1!' is being used so it cannot be dropped or an internal error occurred. Check server errorlog for any additional information."

/*
**Messages for "sp_setpsexe"	18274
*/

exec sp_instmsg 18274, "A non-SA user can only lower its own priority value."
exec sp_instmsg 18275, "Failed to set attribute '%1!' to '%2!' for spid '%3!'. Check server errorlog for any additional information."

/*
**Messages for "sp_showcontrolinfo"	18276
*/

exec sp_instmsg 18276, "%1! is not a valid object type."

/*
**Messages for "sp_showexeclass"	18277
*/

exec sp_instmsg 18277, "Execution class '%1!' is not a valid class."

/*
**Messages for "sp_unbindexeclass"	18278
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18278, "Failed to unbind '%1!' from execution class. Check server errorlog for any additional information."
exec sp_instmsg 18279, "The specified binding to be dropped does not exist."

/*
**Messages for "sp_helpmetadata"	18280
*/

exec sp_instmsg 18280, "There are %1! user objects in %2! database(s), requiring %3! Kbytes of memory. The 'open objects' configuration parameter is currently set to %4!."
exec sp_instmsg 18281, "There are %1! user indexes in %2! database(s), requiring %3! Kbytes of memory. The 'open indexes' configuration parameter is currently set to %4!."
exec sp_instmsg 18282, "There are %1! databases, requiring %2! Kbytes of memory. The 'open databases' configuration parameter is currently set to %3!."

/*
**Messages for "sp_helpconfig"	18283
*/

exec sp_instmsg 18283, "Configuration parameter '%1!' is not supported in this system stored procedure, or the usage is incorrect. Please refer to System Administration Guide for help."

/*
**Messages for "sp_monitormetadata"	18284
*/

exec sp_instmsg 18284, "Usage information at date and time: %1!."

/*
**Messages for "sp_helpmetadata"	18285
*/

exec sp_instmsg 18285, "A %1! Kbytes object descriptor cache would contain %2! object descriptors."
exec sp_instmsg 18286, "A %1! Kbytes index descriptor cache would contain %2! index descriptors."
exec sp_instmsg 18287, "A %1! Kbytes database descriptor cache would contain %2! database descriptors."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18288, "A cache of %1! object descriptors requires %2! Kbytes of ASE memory."
exec sp_instmsg 18289, "A cache of %1! index descriptors requires %2! Kbytes of ASE memory."
exec sp_instmsg 18290, "A cache of %1! database descriptors requires %2! Kbytes of ASE memory."
exec sp_instmsg 18291, "The parameter value '%1!' is invalid."

/*
**Messages for "sp_monitormetadata"	18292
*/

exec sp_instmsg 18292, "An internal error occurred while accessing monitor information."

/*
**Messages for "sp_bindefault"	18293
*/

exec sp_instmsg 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."

/*
**Messages for "sp_addexternlogin"	18294
*/

exec sp_instmsg 18294, "User '%1!' is not a local user -- request denied."
exec sp_instmsg 18295, "Only the 'sa' may update another's external login."
exec sp_instmsg 18296, "External login updated."
exec sp_instmsg 18297, "User '%1!' will be known as '%2!' in remote server '%3!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18298, "Run the 'CHECKPOINT' command to update your in-memory remote connection structures."

/*
**Messages for "sp_addobjectdef"	18299
*/

exec sp_instmsg 18299, "Unknown object type '%1!'."
exec sp_instmsg 18300, "A server name is not permitted in the local object_name."
exec sp_instmsg 18301, "Database name '%1!' is not the current database."
exec sp_instmsg 18302, "User '%1!' is not a valid user in the '%2!' database."
exec sp_instmsg 18303, "You must be the System Administrator (SA) or Database Owner (DBO) to add a definition for another user's table."
exec sp_instmsg 18304, "Object '%1!' has already been defined."
exec sp_instmsg 18305, "Table '%1!' has already been created."
exec sp_instmsg 18306, "The format for the object_loc parameter is invalid."
exec sp_instmsg 18307, "Server name '%1!' does not exist in sysservers."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18308, "The server name in object_loc must be a remote server. '%1!' is the local server."

/*
**Messages for "sp_dropobjectdef"	18309
*/

exec sp_instmsg 18309, "You must be the System Administrator (SA) or Database Owner (DBO) to drop a definition for another user's table."
exec sp_instmsg 18310, "Table has not been defined."
exec sp_instmsg 18311, "You cannot remove a table definition for a table that has been created. Drop the table first."

/*
**Messages for "sp_addtabledef"	18312
*/

exec sp_instmsg 18312, "Object type is '%1!'."
exec sp_instmsg 18313, "Unrecognized storage_location type '%1!'."

/*
**Messages for "sp_autoconnect"	18314
*/

exec sp_instmsg 18314, "Login '%1!' does not exist in syslogins table."
exec sp_instmsg 18315, "Only the 'sa' can modify another's autoconnect capability."
exec sp_instmsg 18316, "Autoconnect ON for user '%1!', server '%2!'."
exec sp_instmsg 18317, "Autoconnect OFF for user '%1!' server '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18318, "Unrecognized flag '%1!'; must be either 'true' or 'false'."

/*
**Messages for "sp_dropexternlogin"	18319
*/

exec sp_instmsg 18319, "There is no external login for server '%1!'."
exec sp_instmsg 18320, "Only the 'sa' may drop another's external login."
exec sp_instmsg 18321, "Remote login/alias dropped."

/*
**Messages for "sp_defaultloc"	18322
*/

exec sp_instmsg 18322, "There is not a database named '%1!'."
exec sp_instmsg 18323, "There is not an object type named '%1!'."
exec sp_instmsg 18324, "An RMS filespec for a directory must be specified."
exec sp_instmsg 18325, "Storage location syntax must end in '.'."
exec sp_instmsg 18326, "Created default location for database '%1!' at '%2!'."
exec sp_instmsg 18327, "You cannot remap objects in the master, model, or tempdb databases."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18328, "There is no default storage location in effect for database '%1!'."
exec sp_instmsg 18329, "Default storage location deleted for database '%1!'."
exec sp_instmsg 18330, "Database '%1!' already has a default location '%2!'."

/*
**Messages for "sp_droptype"	18331
*/

exec sp_instmsg 18331, "Drop failed.  Your curwrite label must match the security label of the type.  Check systypes."

/*
**Messages for "sp_cacheconfig"	18332
*/

exec sp_instmsg 18332, "You need to be able to set curwrite label to data_low.  This script will continue in spite of failure to set curwrite.  Please rerun after setting your labels correctly."

/*
**Messages for "sp_cachestrategy"	18333
*/

exec sp_instmsg 18333, "Cache configuration failed.  Your curread must dominate the sensitivity level of the object."

/*
**Messages for "sp_displaylogin"	18334
*/

exec sp_instmsg 18334, "Default Database: %1!"
exec sp_instmsg 18335, "Default Language: %1!"

/*
**Messages for "sp_dbremap"	18336
*/

exec sp_instmsg 18336, "Permission denied. Your curwrite label must be set at the hurdle of the affected database."

/*
**Messages for "sp_dropalias"	18337
*/

exec sp_instmsg 18337, "Setting curwrite label to data_low for deleting from sysalternates table failed."

/*
**Messages for "sp_setlockpromote"	18338
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18338, "Invalid obj_type parameter: '%1!'. Please specify either 'page' or 'row'."

/*
**Messages for "sp_poolconfig"	18339
*/

exec sp_instmsg 18339, "The '%1!' buffer pool in cache '%2!' is marked as invalid because the size of the pool became less than the required minimum pool size of 512K. The buffer pool will be invalid until you restart ASE or delete the buffer pool."

/*
**Messages for "sp_activeroles"	18341
*/

exec sp_instmsg 18341, "An invalid argument was entered. Usage: sp_activeroles [expand_down]"

/*
**Messages for "sp_displayroles"	18342
*/

exec sp_instmsg 18342, "Invalid name '%1!'. This role or user does not exist in this ASE."
exec sp_instmsg 18343, "Invalid mode '%1!'. Mode should either be 'expand_up' or 'expand_down' or 'display_info'."
exec sp_instmsg 18344, "The user name '%1!' should correspond to the current user or you must possess System Security Officer (SSO) authorization to execute '%2!' for another user."

/*
**Messages for "sp_helprotect"	18349
*/

exec sp_instmsg 18349, "@rolename = 'enabled' option is allowed only for the current user."
exec sp_instmsg 18350, "An error was encountered in processing the group-level permissions."
exec sp_instmsg 18351, "An error was encountered in processing the user-level permissions."

/*
**Messages for "sp_unbindcache_all"	18352
*/

exec sp_instmsg 18352, "Failed to set curwrite label to data_low."

/*
**Messages for "sp_setrepdb"	18353
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18353, "data"
exec sp_instmsg 18354, "ddl"
exec sp_instmsg 18355, "Usage: sp_setrepdb dbname, { 'ddl' | 'data' } [, { 'true', 'false' } ]"
exec sp_instmsg 18356, "The stored procedure must be executed with the name of the current database."
exec sp_instmsg 18357, "The status for database '%1!' for '%2!' replication is '%3!'."
exec sp_instmsg 18358, "The status for database '%1!' for '%2!' replication has been changed to '%3!'."

/*
**Messages for "sp_showplan"	18359
*/

exec sp_instmsg 18359, "The spid value must be a positive integer. To look up plans for cached statements, use sp_showplan -1, <statement id>."
exec sp_instmsg 18360, "If the batch id, context id, or statement number is specified, all three must be specified."
exec sp_instmsg 18361, "Batch id must be non-negative."
exec sp_instmsg 18362, "Context id must be non-negative."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18363, "Statement number must be positive."

/*
**Messages for "sp_altermessage"	18371
*/

exec sp_instmsg 18371, "The only valid @parameter value is WITH_LOG."
exec sp_instmsg 18372, "The only valid @parameter_value values are TRUE or FALSE."

/*
**Messages for "sp_config_rep_agent"	18373
*/

exec sp_instmsg 18373, "ASE is not currently configured to use Replication Agent threads. Use sp_configure to set this property."
exec sp_instmsg 18374, "Database '%1!' is not configured to use Replication Agent. Run sp_config_rep_agent without parameters to see a list of databases that use Replication Agent. Use the ENABLE option of sp_config_rep_agent to configure a database to use this feature."
exec sp_instmsg 18375, "You are not authorized to execute this stored procedure. Only the System Administrator (SA), the Database Owner (DBO) or a user with replication_role authorization can execute this stored procedure."

/*
**Messages for "sp_stop_rep_agent"	18376
*/

exec sp_instmsg 18376, "Incorrect syntax for sp_stop_rep_agent. Usage: sp_stop_rep_agent <dbname> [,nowait]."
exec sp_instmsg 18377, "The Replication Agent thread for database '%1!' is being stopped."

/*
**Messages for "sp_start_rep_agent"	18378
*/

exec sp_instmsg 18378, "Incorrect syntax for sp_start_rep_agent. Usage: sp_start_rep_agent <dbname> [, {recovery|recovery_foreground} [,<connect dataserver>, <connect database> [,<rs_servername>, <rs_username>, <rs_password>]]]."
exec sp_instmsg 18379, "Parameters other than the database name can be specified only when starting the Replication Agent thread in recovery mode. The Replication Agent thread was not started."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18380, "Replication Agent thread is started for database '%1!'."

/*
**Messages for "sp_config_rep_agent"	18381
*/

exec sp_instmsg 18381, "You must be in the specified database '%1!' to configure its Replication Agent thread."
exec sp_instmsg 18382, "Database '%1!' is already configured to use Replication Agent. Request to enable Replication Agent has been ignored."
exec sp_instmsg 18383, "Replication Agent enabled for database '%1!'. The Replication Agent thread needs to be started using sp_start_rep_agent."
exec sp_instmsg 18384, "Replication Agent disabled for database '%1!'. The secondary truncation point in the database is preserved."
exec sp_instmsg 18385, "Replication Agent disabled for database '%1!'. The secondary truncation point in the database is no longer active."

/*
**Messages for "sp_addextendedproc"	18387
*/

exec sp_instmsg 18387, "sp_addextendedproc failed. Check the ASE error log file."
exec sp_instmsg 18388, "You must be in the master database in order to run '%1!'."

/*
**Messages for "sp_dropextendedproc"	18389
*/

exec sp_instmsg 18389, "sp_dropextendedproc failed. Check the ASE error log file."

/*
**Messages for "sp_helpextendedproc"	18390
*/

exec sp_instmsg 18390, "sp_helpextendedproc failed. Check the ASE error log file."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18391, "The extended stored procedure '%1!' is not in sysobjects for this user."

/*
**Messages for "sp_freedll"	18392
*/

exec sp_instmsg 18392, "sp_freedll failed. Check the ASE error log file."
exec sp_instmsg 18393, "DLL for the extended stored procedure '%1!' is not found."

/*
**Messages for "sp_poolconfig"	18394
*/

exec sp_instmsg 18394, "The buffer pool '%1!' cannot be used until you restart ASE or delete the pool and retry sp_poolconfig when the cache '%2!' is not in use."

/*
**Messages for "sp_helpconfig"	18395
*/

exec sp_instmsg 18395, "Configuration parameter, '%1!', will consume %2!K of memory if configured at %3!."
exec sp_instmsg 18396, "Configuration parameter, '%1!', can be configured to %2! to fit in %3! of memory."

/*
**Messages for "sp_configure"	18397
*/

exec sp_instmsg 18397, "Changing the value of '%1!' does not increase the amount of memory Adaptive Server uses."

/*
**Messages for "sp_processmail"	18398
*/

exec sp_instmsg 18398, "Failed to read mail from ASE's mailbox. Check XP Server log file for more information."
exec sp_instmsg 18399, "Failed to send mail to %1!. Check XP Server log file for more information."
exec sp_instmsg 18400, "Failed to delete mail. Check XP Server log file for more information."

/*
**Messages for "sp_helpconfig"	18401
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18401, "Configuration parameter, 'max memory', will need to be set to %1! (%2!K) in order for 'total data cache size' to have a value of %3!."
exec sp_instmsg 18402, "Setting 'total memory' to a size of %1! (%2!) will result in a 'total data cache size' of size %3!K."
exec sp_instmsg 18403, "Configuration parameter, 'max memory', will need to be set to %1! (%2!K) in order for the procedure cache to have a value of %3!."

/*
**Messages for "sp_checksource"	18404
*/

exec sp_instmsg 18404, "Source text for compiled object %1! (id = %2!) exists."
exec sp_instmsg 18405, "Source text for compiled object %1! (id = %2!) does not exist."

/*
**Messages for "sp_helptext"	18406
*/

exec sp_instmsg 18406, "Source text for compiled object %1! (id = %2!) is hidden."

/*
**Messages for "sp_reptostandby"	18407
*/

exec sp_instmsg 18407, "Usage: sp_reptostandby dbname [ , { 'ALL' | 'L1' | 'NONE' } [ , 'USE_INDEX' ] ]"
exec sp_instmsg 18408, "The stored procedure must be executed with the name of the current database."
exec sp_instmsg 18409, "The built-in function '%1!' failed. Please see any other messages printed along with this message."
exec sp_instmsg 18410, "The replication status of '%1!' is corrupt. Please contact Sybase Technical Support."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18411, "The replication status for database '%1!' is '%2!'."
exec sp_instmsg 18412, "The replication status for database '%1!' is already set to '%2!'. The replication status is not changed."
exec sp_instmsg 18413, "Due to a system failure, the replication status for '%1!' has not been changed."
exec sp_instmsg 18414, "The replication status for database '%1!' has been set to '%2!'."
exec sp_instmsg 18415, "ALL"
exec sp_instmsg 18416, "NONE"
exec sp_instmsg 18417, "L1"
exec sp_instmsg 18418, "Only the System Administrator (SA), the Database Owner (dbo) or a user with REPLICATION authorization may execute this stored procedure."

/*
**Messages for "sp_locklogin"	18419
*/

exec sp_instmsg 18419, "Account 'sybmail' cannot be unlocked."

/*
**Messages for "sp_cacheconfig"	18420
*/

exec sp_instmsg 18420, "The replacement policy can only be specified once."

/*
**Messages for "sp_start_rep_agent"	18421
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18421, "Failed to start the Replication Agent thread for database '%1!'."

/*
**Messages for "sp_stop_rep_agent"	18422
*/

exec sp_instmsg 18422, "The Replication Agent thread for database '%1!' is not currently running."

/*
**Messages for "sp_config_rep_agent"	18423
*/

exec sp_instmsg 18423, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, enable, <rs_servername>,<rs_username>,<rs_password>. Replication Agent was not enabled for this database."
exec sp_instmsg 18424, "Failed to enable Replication Agent for database '%1!'."

/*
**Messages for "sp_help_rep_agent"	18425
*/

exec sp_instmsg 18425, "Incorrect syntax for sp_help_rep_agent. Usage: sp_help_rep_agent [<dbname> [,{recovery | process | config | scan | security | all } ] ]."

/*
**Messages for "sp_config_rep_agent"	18426
*/

exec sp_instmsg 18426, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, disable [,'preserve secondary truncpt']. Replication Agent was not disabled for database '%1!'."
exec sp_instmsg 18427, "Failed to disable Replication Agent for database '%1!'."
exec sp_instmsg 18428, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, '%1!',<value>. Replication Agent configuration has not been changed."
exec sp_instmsg 18429, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, '%1!', {true| false}. Replication Agent configuration has not been changed."
exec sp_instmsg 18430, "Replication Agent configuration changed for database '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18431, "Failed to configure the Replication Agent for database '%1!'."
exec sp_instmsg 18432, "Replication Agent configuration changed for database '%1!'. The changes will take effect the next time the Replication Agent thread is started."

/*
**Messages for "sp_helplog"	18433
*/

exec sp_instmsg 18433, "No valid log device can be found to contain the starting logpage of '%1!', on database '%2!'. Perhaps the segment mapping of database has changed recently. Please inspect the sysusages catalog and contact your system administrator."

/*
**Messages for "sp_forceonline_page"	18438
*/

exec sp_instmsg 18438, "%1!: All pages/objects in database '%2!' are now online."
exec sp_instmsg 18439, "%1!: Failed because the suspect granularity for database '%2!' is not at page level."
exec sp_instmsg 18440, "%1!: Invalid option '%2!'. Use 'sa_on', 'sa_off', or 'all_users'."
exec sp_instmsg 18441, "%1!: The page '%2!' in '%3!' is either already online or is an invalid ID. Use sp_listsuspect_page to list suspect pages."
exec sp_instmsg 18442, "%1!: Failed to update cached information for page '%2!' of database '%3!'.."
exec sp_instmsg 18443, "%1!: The page '%2!' of database '%3!' is now in state '%4!'."
exec sp_instmsg 18444, "%1!: The page '%2!' of database '%3!' is already in state '%4!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18445, "%1!: The remaining suspect pages in database '%2!' are:"

/*
**Messages for "sp_setsuspect_granularity"	18446
*/

exec sp_instmsg 18446, "sp_setsuspect_granularity: Invalid suspect granularity value. Valid values are - 'page' and 'database'."
exec sp_instmsg 18447, "sp_setsuspect_granularity: The valid options for suspect granularity are - 'page' and 'database'."

/*
**Messages for "sp_forceonline_db"	18448
*/

exec sp_instmsg 18448, "%1!: No suspect pages in database '%2!'. Use sp_listsuspect_page to list suspect pages."

/*
**Messages for "sp_helpconstraint"	18449
*/

exec sp_instmsg 18449, "Details:"
exec sp_instmsg 18450, "Total Number of Referential Constraints"
exec sp_instmsg 18451, "= Number of references made by this table"
exec sp_instmsg 18452, "+ Number of references made to this table"
exec sp_instmsg 18453, "- Number of self references within this table"

/*
**Messages for "sp_dbcc_plandb"	18454
*/

exec sp_instmsg 18454, "Recommended size for %1! database is %2!MB (data = %3!MB, log = %4!MB)."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18455, "Recommended optimum size for %1! is %2!MB."
exec sp_instmsg 18456, "Recommended devices for %1! are:"
exec sp_instmsg 18457, "No suitable devices for %1! in master..sysdevices."
exec sp_instmsg 18458, "Recommended values for workspace size, cache size and process count are:"
exec sp_instmsg 18459, "%1! database already exists with size %2!MB."

/*
**Messages for "sp_dbcc_alterws"	18460
*/

exec sp_instmsg 18460, "%1! is not a valid workspace in %2! database."
exec sp_instmsg 18461, "Workspace %1! in %2! database could not be altered to size %3!KB. Look at the ASE error log for information."
exec sp_instmsg 18462, "Workspace %1! has been altered successfully to size %2!KB."

/*
**Messages for "sp_dbcc_createws"	18463
*/

exec sp_instmsg 18463, "%1! is not a valid DBCC database. Database must be either dbccdb or dbccalt."
exec sp_instmsg 18464, "%1! name cannot be null."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18465, "'%1!' is not a valid workspace type. Valid types are 'scan' and 'text'."
exec sp_instmsg 18466, "Workspace size must be a valid number and must be at least %1!KB."
exec sp_instmsg 18467, "Workspace %1! already exists in %2! database."
exec sp_instmsg 18468, "Workspace %1! could not be created in %2! database. Look at the ASE error log for more information."
exec sp_instmsg 18469, "Workspace %1! of %2!KB size has been created successfully in %3! database."

/*
**Messages for "sp_dbcc_deletedb"	18470
*/

exec sp_instmsg 18470, "No configuration information to delete."
exec sp_instmsg 18471, "Deleting configuration information for database %1!."

/*
**Messages for "sp_dbcc_deletehistory"	18472
*/

exec sp_instmsg 18472, "No history information to delete."
exec sp_instmsg 18473, "Deleting results of DBCC operations completed before %1! on database %2!."

/*
**Messages for "sp_dbcc_evaluatedb"	18474
*/

exec sp_instmsg 18474, "%1! database is not configured for DBCC in the dbcc_config table. Use sp_dbcc_updateconfig to configure it."

/*
**Messages for "sp_dbcc_updateconfig"	18475
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18475, "Workspace %1! does not exist in database %2!."
exec sp_instmsg 18476, "'%1!' is not a valid value for '%2!'."
exec sp_instmsg 18477, "%1! is not a valid cache name."
exec sp_instmsg 18478, "The specified size for cache %1! is not valid."
exec sp_instmsg 18480, "Database name is null. Specify a valid database name."
exec sp_instmsg 18481, "'%1!' is an invalid configuration parameter."

/*
**Messages for "sp_validatedb"	18482
*/

exec sp_instmsg 18482, "Since dbccalt exists, it is the correct database for dbccdb. Use the dbccalt database."

/*
**Messages for "sp_dbcc_configreport"	18483
*/

exec sp_instmsg 18483, "Reporting configuration information of database %1!."
exec sp_instmsg 18484, "No configuration information available for %1! database."

/*
**Messages for "sp_dbcc_differentialreport"	18485
*/

exec sp_instmsg 18485, "date1 and date2 are the same. No report generated."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18486, "Generating 'Differential Report' for object %1! in database %2!."

/*
**Messages for "sp_dbcc_faultreport"	18487
*/

exec sp_instmsg 18487, "Generating 'Fault Report' for object %1!, indid %2!, partition id %3! in database %4!."

/*
**Messages for "sp_dbcc_statisticsreport"	18488
*/

exec sp_instmsg 18488, "Object name must be accompanied by database name."
exec sp_instmsg 18489, "Generating 'Statistics Report' for object %1! in database %2!."

/*
**Messages for "sp_dbcc_summaryreport"	18490
*/

exec sp_instmsg 18490, "'%1!' is an invalid DBCC operation. The valid operations are %2!."
exec sp_instmsg 18491, "No %1! on DBCC operations available."

/*
**Messages for "sp_shmdumpconfig"	18492
*/

exec sp_instmsg 18492, "Invalid dump condition type %1!"
exec sp_instmsg 18493, "You cannot add the system default settings. Use update."
exec sp_instmsg 18494, "No value for %1! was given."
exec sp_instmsg 18495, "The maximum number of dump conditions (%1!) are already set."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18496, "Either drop a dump condition or increase the value of 'maximum dump conditions'."
exec sp_instmsg 18497, "No values to update were given."
exec sp_instmsg 18498, "There is already a condition of type %1!."
exec sp_instmsg 18499, "There is already a condition of type %1! and value %2!."
exec sp_instmsg 18500, "No record found for %1!."
exec sp_instmsg 18501, "No record found for %1! %2!."
exec sp_instmsg 18502, "%1! is not a valid error number."
exec sp_instmsg 18503, "%1! is not a valid module."
exec sp_instmsg 18504, "Severity must be between 10 and 26."
exec sp_instmsg 18505, "Notification failed. Update of condition was not performed. If this was an update operation, please drop and re-add this dump condition."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18506, "Insert of new record for %1! %2! failed."
exec sp_instmsg 18507, "Invalid memory mode %1!."
exec sp_instmsg 18508, "You cannot drop the system default settings."
exec sp_instmsg 18509, "There is no condition set for %1! %2!."
exec sp_instmsg 18510, "Notification failed. Your change did not take affect."
exec sp_instmsg 18511, "Error reading sysattributes table."
exec sp_instmsg 18512, "WARNING: Unknown dump condition record type found: %1!."
exec sp_instmsg 18513, "Current number of conditions: %1!"
exec sp_instmsg 18514, "Maximum number of conditions: %1!"
exec sp_instmsg 18515, "Printing Debug Information:"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18516, "Invalid action: %1!"
exec sp_instmsg 18517, "Dump count reset for %1! %2!."
exec sp_instmsg 18518, "You cannot reset the dump count for the default setting."
exec sp_instmsg 18519, "The maxdumps parameter value must be greater than zero."

/*
**Messages for "sp_helpconfig"	18521
*/

exec sp_instmsg 18521, "Component Integration Services must be enabled and loaded in order to perform memory calculations."

/*
**Messages for "sp_addexeclass"	18522
*/

exec sp_instmsg 18522, "Execution Class '%1!' is a system defined class. This class cannot be created or changed."

/*
**Messages for "sp_setsuspect_granularity"	18523
*/

exec sp_instmsg 18523, "%1!: Not allowed for System databases."
exec sp_instmsg 18524, "%1!: Permission denied. This operation requires System Administrator (sa_role) role."
exec sp_instmsg 18525, "%1!: Suspect granularity option '%2!' is not valid."
exec sp_instmsg 18526, "%1!: The new values will become effective during the next recovery of the database '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18527, "%1!: Object level suspect granularity is not supported in this release."
exec sp_instmsg 18528, "sp_setsuspect_threshold: Suspect threshold value '%1!' is not valid."

/*
**Messages for "sp_setsuspect_threshold"	18529
*/

exec sp_instmsg 18529, "sp_setsuspect_threshold: Not allowed because '%1!' has database level suspect granularity."

/*
**Messages for "sp_listsuspect_db"	18530
*/

exec sp_instmsg 18530, "The database '%1!' has %2! suspect pages belonging to %3! objects."

/*
**Messages for "sp_dbcc_createws"	18531
*/

exec sp_instmsg 18531, "You must execute this procedure from the database in which you wish to create or alter workspaces. Execute 'use %1!' and try again."

/*
**Messages for "sp_sysmon"	18532
*/

exec sp_instmsg 18532, "%1!: Invalid value for section parameter '%2!'."
exec sp_instmsg 18534, "Valid values are: 'kernel','wpm','parallel','taskmgmt','appmgmt','esp','housekeeper','monaccess','xactsum','xactmgmt','indexmgmt','mdcache','locks','dcache','pcache','memory','recovery','diskio','netio', 'cache wizard'"

/*
**Messages for "sp_bindexeclass"	18535
*/

exec sp_instmsg 18535, "Permission denied: 'sybase_ts_role' is required for binding with execution class 'EC0'."

/*
**Messages for "sp_shmdumpconfig"	18536
*/

exec sp_instmsg 18536, "The @value parameter must be NULL when setting system defaults."

/*
**Messages for "sp_setrepdefmode"	18537
*/

exec sp_instmsg 18537, "Usage: sp_setrepdefmode table_name [, owner_on | owner_off | 'udi' [, 'on' | 'off' | 'never'] | 'threshold' [, 'value'] ]"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18538, "owner_on"
exec sp_instmsg 18539, "owner_off"
exec sp_instmsg 18540, "The replication definition mode for '%1!' is already set to '%2!'. Replication definition mode for '%3!' does not change."
exec sp_instmsg 18541, "An object with the same name but owned by a different user is already being replicated with the replication definition mode 'owner_off'. The replication definition mode for '%1!' is not changed."
exec sp_instmsg 18542, "Failed to change the replication definition mode for '%1!' because of an internal error."
exec sp_instmsg 18543, "The replication definition mode for '%1!' is set to '%2!'."

/*
**Messages for "sp_sysmon"	18544
*/

exec sp_instmsg 18544, "%1!: The section parameter '%2!' was ignored with the begin_sample option."

/*
**Messages for "sp_sysmon_collect"	18545
*/

exec sp_instmsg 18545, "%1!: No report was produced. Sampling interval was less than 1 second."

/*
**Messages for "sp_sysmon"	18546
*/

exec sp_instmsg 18546, "%1!: Section parameter '%2!' ignored for begin_sample option."

/*
**Messages for "sp_config_rep_agent"	18547
*/

exec sp_instmsg 18547, "The configuration parameter specified, '%1!' is a display only parameter and cannot be modified."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18548, "The configuration parameter specified, '%1!' is not a displayable parameter."

/*
**Messages for "sp_configure"	18549
*/

exec sp_instmsg 18549, "Invalid third argument supplied: '%1!'. Valid choices are 'with truncate' or 'default'."

/*
**Messages for "sp_bindexeclass"	18551
*/

exec sp_instmsg 18551, "Stored procedure %1!, owned by %2!, does not exist in this database."
exec sp_instmsg 18552, "%1! is not a valid user of this database."

/*
**Messages for "sp_droplogin"	18553
*/

exec sp_instmsg 18553, "Login '%1!' cannot be dropped because it has execution class bindings. Use sp_unbindexeclass before dropping login."

/*
**Messages for "sp_dropuser"	18554
*/

exec sp_instmsg 18554, "You cannot drop user '%1!' because stored proc '%2!' owned by it is bound to an execution class. Use sp_unbindexeclass before dropping user."

/*
**Messages for "sp_dropexeclass"	18555
*/

exec sp_instmsg 18555, "%1! is a system defined execution class which cannot be dropped."

/*
**Messages for "sp_displayaudit"	18556
*/

exec sp_instmsg 18556, "Usage: sp_displayaudit [ procedure | object | login | database | global | default_object | default_procedure [ , name ]]"

/*
**Messages for "sp_aux_getsptaud"	18557
*/

exec sp_instmsg 18557, "The parameter '%1!' is invalid. Enter a valid parameter, and run sp_aux_getsptaud again."

/*
**Messages for "sp_poolconfig"	18558
*/

exec sp_instmsg 18558, "Unable to delete the '%1!' pool in cache '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18559, "This pool has been marked unavailable. You can remove it completely by retrying sp_poolconfig when the cache is not in use or by restarting the Server."
exec sp_instmsg 18560, "Unable to move '%1!' from the '%2!' pool to the '%3!' pool in cache '%4!'. Only '%5!' moved."
exec sp_instmsg 18561, "The '%1!' pool has been marked unavailable, since it is smaller than the minimum pool size of 512KB."
exec sp_instmsg 18562, "You can size the pools correctly by retrying sp_poolconfig when the cache is not in use or by restarting the Server."

/*
**Messages for "sp_transactions"	18563
*/

exec sp_instmsg 18563, "A transaction name should be specified."
exec sp_instmsg 18564, "Invalid option. Possible values are: xid and state."
exec sp_instmsg 18565, "Invalid value for state. Legal values are: heuristic_commit heuristic_abort prepared."

/*
**Messages for "sp_role"	18566
*/

exec sp_instmsg 18566, "Please make use of the 'grant role' / 'revoke role' facility when granting/revoking roles to/from other roles."
exec sp_instmsg 18567, "Please make use of the 'grant role' / 'revoke role' facility when granting/revoking roles which have been granted other roles."
exec sp_instmsg 18568, "Please make use of the 'grant role' / 'revoke role' facility when granting/revoking roles to/from users posessing roles which have been granted other roles."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18569, "The result of this REVOKE command will only take effect after the user logs out and logs back in."

/*
**Messages for "sp_configure"	18570
*/

exec sp_instmsg 18570, "Unable to disable disk mirroring because some devices are currently mirrored. Use 'disk unmirror' to unmirror these devices and then rerun this sp_configure command."

/*
**Messages for "sp_chgattribute"	18571
*/

exec sp_instmsg 18571, "The attribute '%1!' is not applicable to tables with allpages lock scheme."
exec sp_instmsg 18572, "The value for attribute '%1!' must be between %2! and %3!."
exec sp_instmsg 18573, "Failed to update attribute '%1!' for object '%2!'."
exec sp_instmsg 18574, "The attribute 'fillfactor' is applicable only for indexes."

/*
**Messages for "sp_forceonline_object"	18575
*/

exec sp_instmsg 18575, "%1!: The object with object-id '%2!' and index-id '%3!' in database '%4!' is either already online or is an invalid object. Use sp_listsuspect_object to list suspect objects."
exec sp_instmsg 18576, "%1!: Failed to update cached info for object-id '%2!' and index-id '%3!' of database '%4!'."
exec sp_instmsg 18577, "%1!: The object with object-id '%2!' and index-id '%3!' of database '%4!' is now in state '%5!'."
exec sp_instmsg 18578, "%1!: The object with object-id '%2!' and index-id '%3!' of database '%4!' is already in state '%5!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18579, "%1!: The remaining suspect objects in database '%2!' are:"

/*
**Messages for "sp_clean_text_indexes"	18580
*/

exec sp_instmsg 18580, "Unable to drop object definition for %1!"

/*
**Messages for "sp_create_text_index"	18581
*/

exec sp_instmsg 18581, "Invalid text index name - '%1!' already exists"
exec sp_instmsg 18582, "Table '%1!' does not have an identity column - text index creation aborted"
exec sp_instmsg 18583, "Text index creation failed"
exec sp_instmsg 18584, "Index table mapping failed - Text Index creation aborted"

/*
**Messages for "sp_drop_text_index"	18585
*/

exec sp_instmsg 18585, "Index '%1!' is not a Text Index"
exec sp_instmsg 18586, "Unable to drop index table '%1!'. This table must be dropped manually"
exec sp_instmsg 18587, "vs_drop_index failed with code %1!. Unable to drop index '%2!'."

/*
**Messages for "sp_text_index_column_type"	18588
*/

exec sp_instmsg 18588, "Column '%1!' does not exist in table '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18589, "Datatype %1! ( Column '%2!' ) is not supported in a text index."

/*
**Messages for "sp_text_notify"	18590
*/

exec sp_instmsg 18590, "Notification failed, server = '%1!'."

/*
**Messages for "sp_text_online"	18591
*/

exec sp_instmsg 18591, "vs_online failed for server '%1!'."
exec sp_instmsg 18592, "All Databases using text indexes are now online."
exec sp_instmsg 18593, "Databases containing text indexes on server '%1!' are now online."
exec sp_instmsg 18594, "Database '%1!' is now online"

/*
**Messages for "sp_purge_text_index"	18595
*/

exec sp_instmsg 18595, "Text Index '%1!' must be dropped using sp_drop_text_index."
exec sp_instmsg 18596, "Unable to drop Text Index '%1!'."

/*
**Messages for "sp_read_text_events"	18597
*/

exec sp_instmsg 18597, "Text event table does not exist."

/*
**Messages for "sp_redo_text_events"	18598
*/

exec sp_instmsg 18598, "@to_date cannot be specified without @from_date."

/*
**Messages for "sp_show_text_online"	18599
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18599, "sp_show failed for server %1!."

/*
**Messages for "sp_dbrecovery_order"	18600
*/

exec sp_instmsg 18600, "%1!: Illegal option. The only legal option is 'force'."
exec sp_instmsg 18601, "%1!: The database '%2!' has no user specified recovery order."
exec sp_instmsg 18602, "%1!: The database '%2!' already has the user specified recovery order of %3!."
exec sp_instmsg 18603, "%1!: The recovery order %2! is already in use for database '%3!'."
exec sp_instmsg 18604, "%1!: Invalid recovery order. The next valid recovery order is: %2!"
exec sp_instmsg 18605, "%1!: The database '%2!' has no user specified recovery order."
exec sp_instmsg 18606, "The rest of the databases will be recovered in default database id order."
exec sp_instmsg 18607, "%1!: No databases have user specified recovery order. All databases will be recovered in database id order."
exec sp_instmsg 18608, "%1!: Delete row from master.dbo.sysattributes failed. Command aborted."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18609, "%1!: Update row of master.dbo.sysattributes failed. Command aborted."
exec sp_instmsg 18610, "%1!: Insert row to master.dbo.sysattributes failed. Command aborted."

/*
**Messages for "sp_cacheconfig"	18611
*/

exec sp_instmsg 18611, "The specified cache partition number is invalid. A valid cache partition number should be power of 2 and between 1 to 128."

/*
**Messages for "sp_chgattribute"	18612
*/

exec sp_instmsg 18612, "Invalid value specified for option '%1!'. Valid range of values is %2! to %3!."
exec sp_instmsg 18613, "The attribute '%1!' is applicable to tables only."

/*
**Messages for "sp_report_partition_idxerror"	18614
*/

exec sp_instmsg 18614, "The following partitioned tables (if any) in database '%1!' have a clustered index that needs to be recreated without using sorted_data option."

/*
**Messages for "sp_cacheconfig"	18616
*/

exec sp_instmsg 18616, "The cache partition can only be specified once"

/*
**Messages for "sp_object_stats"	18617
*/

exec sp_instmsg 18617, "Usage: sp_object_stats 'hh:mm:ss'[, @top_n][, @dbname[, @objname]][, @rpt_option]"
exec sp_instmsg 18618, "sp_object_stats: Invalid interval string passed '%1!'. It should be in the form 'hh:mm:ss'."
exec sp_instmsg 18619, "sp_object_stats: Failed to %1! temporary table %2!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18620, "sp_object_stats: If @objname is specified, a valid @dbname must also be specified."

/*
**Messages for "sp_dbcc_updateconfig"	18635
*/

exec sp_instmsg 18635, "The database '%1!' with id %2! was configured as '%3!' in dbccdb database. Delete the configuration and history using the command '%4!' and retry the sp_dbcc_updateconfig command."

/*
**Messages for "sp_set_qplan"	18636
*/

exec sp_instmsg 18636, "There is no query plan with the ID %1! in this database."
exec sp_instmsg 18637, "Failed to drop the old query plan with ID %1!, rolling back and aborting."
exec sp_instmsg 18638, "Failed to set the new query plan with ID %1!, rolling back and aborting."

/*
**Messages for "sp_rename_qpgroup"	18639
*/

exec sp_instmsg 18639, "The is no query plans group named '%1!' in this database."

/*
**Messages for "sp_help_qplan"	18640
*/

exec sp_instmsg 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."

/*
**Messages for "sp_help_qpgroup"	18641
*/

exec sp_instmsg 18641, "Query plan groups in database '%1!'"
exec sp_instmsg 18642, "Query plans group '%1!', GID %2!"
exec sp_instmsg 18643, "sysqueryplans rows consumption, number of query plans per row count"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18644, "Query plans that use the most sysqueryplans rows"
exec sp_instmsg 18645, "There is no hash key collision in this group."
exec sp_instmsg 18646, "Number of collisions per hash key"
exec sp_instmsg 18647, "Colliding query plan IDs per hash key"
exec sp_instmsg 18648, "Query plans in this group"
exec sp_instmsg 18649, "The query plans group is empty."

/*
**Messages for "sp_find_qplan"	18650
*/

exec sp_instmsg 18650, "Query plans needing manual checking, as they use more than one row"

/*
**Messages for "sp_drop_qpgroup"	18651
*/

exec sp_instmsg 18651, "Cannot drop the query plans group '%1!', as it is not empty."

/*
**Messages for "sp_copy_qplan"	18652
*/

exec sp_instmsg 18652, "The new query plan would give an association key collision in group '%1!', with the existing query plan %2!."
exec sp_instmsg 18653, "The new query plan already exists in group '%1!', under the ID %2!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18654, "Obtained the unexpected plan comparison return code %1!, when comparing with the query plan %2!. Please contact Sybase Technical Support."
exec sp_instmsg 18655, "Failed to copy the new query plan."

/*
**Messages for "sp_copy_all_qplans"	18656
*/

exec sp_instmsg 18656, "Unrecoverable error while copying the query plan %1!. Keeping all plans copied so far and interrupting the copy."
exec sp_instmsg 18657, "Recoverable error while copying the query plan %1!. Skipping this plan and continuing the copy."
exec sp_instmsg 18658, "Error while fetching the next query plan to copy. Keeping all plans copied so far and interrupting the copy."

/*
**Messages for "sp_aux_get_qpgroup"	18659
*/

exec sp_instmsg 18659, "Warning : there are %1! query plans groups in this database that are named '%2!'. Using the group with ID %3!."

/*
**Messages for "sp_ap_add_qpgroup"	18660
*/

exec sp_instmsg 18660, "There is already a query plans group named '%1!' in this database."

/*
**Messages for "sp_cmp_all_qplans"	18661
*/

exec sp_instmsg 18661, "If the two query plans groups are large, this might take some time."
exec sp_instmsg 18662, "Query plans that are the same"
exec sp_instmsg 18663, "Different query plans that have the same association key"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18664, "Query plans present only in group '%1!' :"
exec sp_instmsg 18665, "Query plans in group '%1!' that have hash collisions and should be checked manually with the corresponding hash key bucket in '%2!' :"
exec sp_instmsg 18666, "Error while fetching the next pair of query plans. If there are no other error messages and this error persists, please contact Sybase Technical Support."

/*
**Messages for "sp_copy_qplan"	18667
*/

exec sp_instmsg 18667, "The new query plan will give a hash collision with the existing query plan %1!, but the copy will be made."

/*
**Messages for "sp_displayroles"	18674
*/

exec sp_instmsg 18674, "Role password information can not be displayed for a login."

/*
**Messages for "sp_displaylogin"	18675
*/

exec sp_instmsg 18675, "Password expiration interval: %1!"
exec sp_instmsg 18676, "Password expired: %1!"
exec sp_instmsg 18677, "Minimum password length: %1!"
exec sp_instmsg 18678, "Maximum failed logins: %1!"
exec sp_instmsg 18679, "Current failed login attempts: %1!"

/*
**Messages for "sp_modifylogin"	18681
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18681, "You cannot specify both @value and @opt_val parameters. Specify only one of these parameters."

/*
**Messages for "sp_drop_qpgroup"	18682
*/

exec sp_instmsg 18682, "Cannot drop or rename the default query plans groups ap_stdin and ap_stdout."

/*
**Messages for "sp_deviceattr"	18683
*/

exec sp_instmsg 18683, "The device %1! is not a disk device."
exec sp_instmsg 18684, "Usage: sp_deviceattr device_name, %1!, { true | false }"
exec sp_instmsg 18685, "The attribute %1! is already turned %2!."

/*
**Messages for "sp_serveroption"	18686
*/

exec sp_instmsg 18686, "Server option 'server logins' cannot be set when @@servername is null"

/*
**Messages for "sp_setrepcol"	18687
*/

exec sp_instmsg 18687, "Cannot set replication status for in-row objects, use sp_setreptable to set the table's replication status instead. The replication status for '%1!.%2!' is not changed."

/*
**Messages for "sp_setrepproc"	18688
*/

exec sp_instmsg 18688, "Stored procedures with object parameters cannot be marked for replication yet at this time. Instead, use sp_setreptable to mark the invidual tables for replication. The replication status for '%1!' is not changed."

/*
**Messages for "sp_dtx_participants"	18689
*/

exec sp_instmsg 18689, "Invalid value specified for parameter 'query'."
exec sp_instmsg 18690, "Must provide the second parameter."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18691, "Invalid 'state' values specified. Valid values are {begun|prepared|committed|aborted}."

/*
**Messages for "sp_cmp_qplans"	18692
*/

exec sp_instmsg 18692, "The queries are the same."
exec sp_instmsg 18693, "The queries are different."
exec sp_instmsg 18694, "The queries are different but have the same hash key."
exec sp_instmsg 18695, "The query plans are the same."
exec sp_instmsg 18696, "The query plans are different."

/*
**Messages for "sp_helpjava"	18697
*/

exec sp_instmsg 18697, "Usage: sp_helpjava ['class' [, name [, 'detail' |, 'depends']] | 'jar' [, name [, 'depends']]]"
exec sp_instmsg 18698, "Class '%1!' is not a system class and is not installed in the current database."
exec sp_instmsg 18699, "Jar '%1!' does not exist in this database."

/*
**Messages for "sp_companion"	18703
*/

exec sp_instmsg 18703, "Please execute the procedure '%1!' from master database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18704, "HA services are disabled. Procedure '%1!' requires the server '%2!' booted with 'enable HA' configuration option. Please refer to System Administartion Manual for configuration of High Availability Services."
exec sp_instmsg 18705, "Single server"
exec sp_instmsg 18706, "Secondary normal"
exec sp_instmsg 18707, "Local server is currently configured with server '%1!'. The command '%2!' can only be run on the configured server."
exec sp_instmsg 18708, "Secondary suspended"
exec sp_instmsg 18709, "Secondary failedover"
exec sp_instmsg 18710, "Secondary failback"
exec sp_instmsg 18711, "Primary normal"
exec sp_instmsg 18712, "Primary suspended"
exec sp_instmsg 18713, "Primary failback"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18714, "Symmetric normal"
exec sp_instmsg 18715, "Symmetric suspended"
exec sp_instmsg 18716, "Symmetric failback"
exec sp_instmsg 18717, "Symmetric failedover"
exec sp_instmsg 18718, "Invalid server"
exec sp_instmsg 18719, "Server '%1!' is configured for HA services."
exec sp_instmsg 18720, "Server '%1!' is currently in '%2!' mode."
exec sp_instmsg 18721, "Server is already in normal companion mode."
exec sp_instmsg 18722, "Server is currently configured, drop and retry."
exec sp_instmsg 18723, "Handshake Failed."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18724, "Unable to access Master Device path from Companion."
exec sp_instmsg 18725, "Companion configuration verification failed."
exec sp_instmsg 18726, "Unable to initialize servers for configuration."
exec sp_instmsg 18727, "Cannot configure servers, state machine error."
exec sp_instmsg 18728, "Update to local server catalog failed, retry command."
exec sp_instmsg 18729, "Update to remote server catalog failed, retry command."
exec sp_instmsg 18730, "Synchronization of User information failed."
exec sp_instmsg 18731, "Unable to create system proxy databases."
exec sp_instmsg 18732, "Shutdown of failed-over user databases failed."
exec sp_instmsg 18733, "Shutdown of failed-over master database failed."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18734, "Drop of failed-over databases failed."
exec sp_instmsg 18735, "Drop of failed-over devices failed."
exec sp_instmsg 18736, "Server '%1!' is alive and cluster configured."
exec sp_instmsg 18737, "Server '%1!' is not cluster configured."
exec sp_instmsg 18738, "Database '%1!': a 'proxy' database or database having 'proxy' exists. Drop this database and retry the configuration again."
exec sp_instmsg 18739, "Database '%1!': a user database exists. Drop this database and retry the configuration again."
exec sp_instmsg 18740, "Server '%1!' has remote server definitions other than defaults. Drop the non-default servers and retry the configuration again."
exec sp_instmsg 18741, "Server '%1!' has remote logins defined. Please drop all remote logins and retry the configuration again."
exec sp_instmsg 18742, "Server '%1!' has logins defined other than defaults. Please drop all other logins and retry the configuration again."
exec sp_instmsg 18743, "Server '%1!' has login roles defined other than defaults. Please drop all other login roles and retry the configuration again."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18744, "Server '%1!' has roles defined other than defaults. Please drop all other roles and retry the configuration again."
exec sp_instmsg 18745, "Server '%1!' has alternate logins defined. Please drop all alternate logins and retry the configuration again."
exec sp_instmsg 18746, "Server '%1!' has users in masterdb defined other than defaults. Please drop all other users and retry the configuration again."
exec sp_instmsg 18747, "Server '%1!' has roles in masterdb defined other than defaults. Please drop all other roles and retry the configuration again."
exec sp_instmsg 18748, "Server '%1!' does not have 'SYB_HACMP' server. Please install HA services using 'installhasvss' and try again."
exec sp_instmsg 18749, "Server '%1!' does not have HA DLLs loaded. See System Administrator manual for how to correct this problem."
exec sp_instmsg 18750, "The command '%1!' can not be run in this server. The server is currently configured with mode '%2!'."
exec sp_instmsg 18751, "Cannot process under case-insensitive sort order."
exec sp_instmsg 18752, "Local server name can not be null. Please add the local servername using sp_addserver. Reboot the server for the change to take effect."
exec sp_instmsg 18753, "HA Cluster configurator requires name of the companion server. Server name specified is same as local server."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18754, "Omni-connection not enabled in server '%1!'. Please enable it and reboot the server."
exec sp_instmsg 18755, "Server '%1!' does not have '%2!' as one of the remote servers. Please add this server using sp_addsever."
exec sp_instmsg 18756, "Unable to setup omni-connection. Possible causes maybe, server is down, sa passwords are different or improper interface definitions."
exec sp_instmsg 18757, "Remote server '%1!' is not added as a local entry. Use sp_addserver to add it as local entry and try again."
exec sp_instmsg 18758, "Remote server '%1!' dose not have server '%2!' as a remote server. Use Sp_addserver at server '%3!' to add server '%4!'."
exec sp_instmsg 18759, "Unable to drop the '%1!' server to fix srvid."
exec sp_instmsg 18760, "Unable to add the '%1!' server to fix srvid."
exec sp_instmsg 18761, "Unable to Update the srvid with fixed srvid."
exec sp_instmsg 18762, "Server is already in suspended state."
exec sp_instmsg 18763, "Suspend operation is not allowed in current server state."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18764, "Please issue the command from your companion secondary."
exec sp_instmsg 18765, "Server is not in suspended/failingback state you can not resume."
exec sp_instmsg 18766, "Database '%1!' is still being shutdown. Please wait till all the databases are shutdown before issuing this command."
exec sp_instmsg 18767, "Internal Error: Transaction not active to run the procedure '%1!'."
exec sp_instmsg 18768, "Cluster object could not be found or accessed. Please contact System Administrator as how to correct this problem."
exec sp_instmsg 18769, "The HA cluster is currently in use for other cluster operations. Retry the command later. If the problem persists, it may be due to an earlier failed cluster command; check the System Administration Guide (Error %1!)."
exec sp_instmsg 18770, "Could not create System Proxy database for databse '%1!'."
exec sp_instmsg 18771, "Could not convert the state into varchar."
exec sp_instmsg 18772, "quiesce database."

/*
**Messages for "sp_addlogin"	18773
*/

exec sp_instmsg 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."

/*
**Messages for "sp_companion"	18774
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18774, "Language name '%1!' or alias '%2!' already exists in syslanguages."
exec sp_instmsg 18775, "Unable to find a language entry with language name '%1!' and language id '%2!'."

/*
**Messages for "sp_modify_resource_limit"	18776
*/

exec sp_instmsg 18776, "Please also run stored procedure '%1!' on the companion server '%2!'."

/*
**Messages for "sp_companion"	18777
*/

exec sp_instmsg 18777, "Login name '%1!' or login id '%2!' already exists in syslogins."

/*
**Messages for "sp_droplogin"	18778
*/

exec sp_instmsg 18778, "Unable to find login '%1!' with id '%2!' in syslogins."

/*
**Messages for "sp_drop_time_range"	18779
*/

exec sp_instmsg 18779, "Unable to find the time range '%1!' with id '%2!' in systimeranges."

/*
**Messages for "sp_addremotelogin"	18780
*/

exec sp_instmsg 18780, "Synchronization will not occur because server '%1!' is the companion server."

/*
**Messages for "sp_companion"	18781
*/

exec sp_instmsg 18781, "Unable to find a limit type with name '%1!' and id '%2!'."
exec sp_instmsg 18782, "Unable to find a server with name '%1!' and id '%2!'."

/*
**Messages for "sp_dropserver"	18783
*/

exec sp_instmsg 18783, "You cannot drop the companion server '%1!' because it is configured as a node of HA cluster."

/*
**Messages for "sp_companion"	18784
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18784, "HA Warning: Server is currently configured. Any change to SYB_HACMP or companion server can be serious."

/*
**Messages for "sp_dropserver"	18785
*/

exec sp_instmsg 18785, "Unable to drop the local server '%1!' because it is in HA companion mode."

/*
**Messages for "sp_companion"	18786
*/

exec sp_instmsg 18786, "A type with name '%1!' or id '%2!' already exists."
exec sp_instmsg 18787, "The type with name '%1!' does not exist."
exec sp_instmsg 18788, "HA Warning: Disk Mirroring can NOT be enabled because the server is booted with option -H."
exec sp_instmsg 18789, "Usage: sp_companion [srvname{,cmd}[,option|NULL[,srvlogin,srvpassword,cluslogin,cluspassword]]]; cmd is [configure|drop|suspend|resume|prepare_failback|do_advisory|show_cluster|set_cluster]; option is [with_proxydb] if cmd not [show_cluster|set_cluster]."

/*
**Messages for "sp_dropalias"	18790
*/

exec sp_instmsg 18790, "You cannot drop the alias for login '%1!' because '%2!' owns objects in the database."

/*
**Messages for "sp_companion"	18791
*/

exec sp_instmsg 18791, "Unable to drop system proxy databases"

/*
**Messages for "sp_dropgroup"	18792
*/

exec sp_instmsg 18792, "Unable to find a group with name '%1!' and id '%2!' in sysusers."
exec sp_instmsg 18793, "Unable to find a user with name '%1!' and id '%2!' in sysusers."

/*
**Messages for "sp_companion"	18794
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18794, "A group with id '%1!' already exists in sysusers."
exec sp_instmsg 18795, "Unable to find a user with name '%1!' and login id '%2!' in sysusers."

/*
**Messages for "sp_adduser"	18796
*/

exec sp_instmsg 18796, "A user with name '%1!' or login id '%2!' already exists in sysusers."

/*
**Messages for "sp_dropuser"	18797
*/

exec sp_instmsg 18797, "Unable to find a user with name '%1!' and login id '%2!' in sysusers."

/*
**Messages for "sp_companion"	18799
*/

exec sp_instmsg 18799, "Unable to find a server with name '%1!', id '%2!', and netname '%3!' in sysservers."
exec sp_instmsg 18800, "A server with name '%1!' and id '%2!' already exists in sysservers."
exec sp_instmsg 18801, "HA_LOG:Sortorder '%1!' is not installed on server '%2!."
exec sp_instmsg 18802, "HA_LOG:Charset '%1!' is not installed on server '%2!'."
exec sp_instmsg 18803, "HA_LOG:Language '%1!' is not installed on server '%2!'."
exec sp_instmsg 18804, "Companion server '%1!' has been configured with different 'default %2!'. Reconfigure local server and try again."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18805, "Warning: Server '%1!' is configured for ASE HA services. The network name in its SYB_HACMP entry does not point to the local server. If this is due to an earlier failed cluster command, refer to the System Administration Guide."

/*
**Messages for "sp_dropalias"	18806
*/

exec sp_instmsg 18806, "You cannot drop the alias for login '%1!' because '%2!' owns thresholds in the database."

/*
**Messages for "sp_deviceattr"	18807
*/

exec sp_instmsg 18807, "Changing attribute for master or master_companion device is not allowed"

/*
**Messages for "sp_companion"	18808
*/

exec sp_instmsg 18808, "Invalid attribute Id(%1!). Attribute Id should be greater than %2! for Attribute '%3!'."
exec sp_instmsg 18809, "Invalid Attribute Name or Id. Attribute '%1!' is an invalid name for a Group or Base type; or has invalid attribute id '%2!' for the attribute type."
exec sp_instmsg 18810, "Internal Error: Invalid Base attribute '%1!' for the Group attribute '%2!'."

/*
**Messages for "sp_locktable"	18811
*/

exec sp_instmsg 18811, "Cannot lock table '%1!'."

/*
**Messages for "sp_halockclustertables"	18812
*/

exec sp_instmsg 18812, "HA Internal Error: Cannot acquire locks for stored procedure '%1!' on server '%2!'. Retry later."

/*
**Messages for "sp_halocksptables"	18813
*/

exec sp_instmsg 18813, "HA Internal Error: Do not know how to lock system tables referred by stored procedure '%1!'."
exec sp_instmsg 18814, "HA Warning: The configuraton '%1!' on the two servers mismatch. On server '%2!', the value is '%3!'; on server '%4!', the value is '%5!'."

/*
**Messages for "sp_dropuser"	18815
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18815, "You cannot drop user '%1!' because it still owns objects, types, thresholds, privileges, and/or execution classes on the companion server '%2!'. Issue stored procedure '%3!' on server '%4!' for details."

/*
**Messages for "sp_configure"	18816
*/

exec sp_instmsg 18816, "Sybase mirroring services will not be allowed in HA configuration of ASE. Disabling Sybase mirroring configuration option."

/*
**Messages for "sp_helpjava"	18817
*/

exec sp_instmsg 18817, "Cannot run this command because Java services are not enabled. A user with  System Administrator (SA) role must reconfigure the system to enable Java."

/*
**Messages for "sp_add_time_range"	18819
*/

exec sp_instmsg 18819, "Time range '%1!' or id '%2!' already exists in systimeranges."

/*
**Messages for "sp_addserver"	18820
*/

exec sp_instmsg 18820, "You cannot change the physical name of server %1! because it is configured as a node of HA cluster."

/*
**Messages for "sp_getSourceID"	18821
*/

exec sp_instmsg 18821, "StructName '%1!' invalid for ResourceType '%2!'."

/*
**Messages for "sp_getaddSourceID"	18822
*/

exec sp_instmsg 18822, "StructName '%1!' invalid for ResourceType '%2!'."

/*
**Messages for "sp_GetSourceID"	18823
*/

exec sp_instmsg 18823, "SourceID not found for collector='%1!' and structure='%2!'."

/*
**Messages for "sp_isDST"	18824
*/

exec sp_instmsg 18824, "Date_IN must be non-NULL."

/*
**Messages for "sp_getStructData"	18825
*/

exec sp_instmsg 18825, "No StructName for SourceID='%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18826, "Procedure '%1!' not found."

/*
**Messages for "sp_check_text_index"	18827
*/

exec sp_instmsg 18827, "index name %1! is invalid"
exec sp_instmsg 18828, "last parameter of sp_check_text_index not valid"
exec sp_instmsg 18829, "Get list of index orphans failed"
exec sp_instmsg 18830, "Get list of source orphans failed"
exec sp_instmsg 18831, "Get list of all ID values failed"
exec sp_instmsg 18832, "Get list of duplicated ID values failed"

/*
**Messages for "sp_companion"	18833
*/

exec sp_instmsg 18833, "Remote server name '%1!' specified is different than your currently configured companion server name '%2!''."
exec sp_instmsg 18834, "Server '%1!' has a local server name different than '%2!'. Please rename the server to its original name '%3!' and try again."
exec sp_instmsg 18835, "Option 'with_proxydb' is valid only during Asymmetric ASE HA Configuration, not for Symmetric ASE HA Configuration."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18836, "Configuration operation '%1!' can not proceed due to Quorum Advisory Check failure. Please run 'do_advisory' command to find the incompatible attribute and fix it."
exec sp_instmsg 18837, "Could not release the resources back to server '%1!'. Please refer to System Administration manual as how to correct this problem."
exec sp_instmsg 18838, "Procedure 'sp_companion' can not be executed from a session with failover property."
exec sp_instmsg 18839, "Insufficient free open databases or connections for successful failover. Please refer to System Administration manual as how to correct this problem."

/*
**Messages for "sp_chgattribute"	18840
*/

exec sp_instmsg 18840, "The value specified for identity gap %1! is not legal; identity gap must be greater than or equal to 0."
exec sp_instmsg 18841, "Identity gap can be specified only for tables which have identity columns."

/*
**Messages for "sp_companion"	18842
*/

exec sp_instmsg 18842, "HA is enabled for Server '%1!', but procedure '%2!' is not HA-compliant. Verify that installhasvss has been run."

/*
**Messages for "sp_renamedb"	18843
*/

exec sp_instmsg 18843, "Please check the System Administration Guide to determine how to %1! the corresponding proxy or real database on the companion server '%2!'."

/*
**Messages for "sp_setrepproc"	18844
*/

exec sp_instmsg 18844, "log_current"
exec sp_instmsg 18845, "log_sproc"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18846, "Object name cannot be null when other parameters are non null."
exec sp_instmsg 18847, "The log mode for '%1!' is currently %2!."
exec sp_instmsg 18848, "The replication status for '%1!' is already set to %2!, with log mode set to %3!. Replication status for '%4!' does not change."
exec sp_instmsg 18849, "The log mode is set to %1!."

/*
**Messages for "sp_renamedb"	18850
*/

exec sp_instmsg 18850, "HA Error: Database '%1!' is a system proxy database. You must execute sp_renamedb on the primary server first."
exec sp_instmsg 18851, "HA Error: You must be in the master database in order to run '%1!' against a system proxy database."

/*
**Messages for "sp_companion"	18852
*/

exec sp_instmsg 18852, "Step: Access verified from Server:'%1!' to Server:'%2!'."
exec sp_instmsg 18853, "Step: Companion server's configuration check succeeded."
exec sp_instmsg 18854, "Step: Server handshake succeeded."
exec sp_instmsg 18855, "Step: Master device accessible from companion."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18856, "Could not cluster-configure the servers."
exec sp_instmsg 18857, "Local server:'%1!'."
exec sp_instmsg 18858, "Remote server:'%1!'."
exec sp_instmsg 18859, "Remote Server login:'%1!'."
exec sp_instmsg 18860, "Remote Server password:'%1!'."
exec sp_instmsg 18861, "Cluster login:'%1!'."
exec sp_instmsg 18862, "Cluster password:'%1!'."
exec sp_instmsg 18863, "Step: Added the servers '%1!' and '%2!' for cluster configuration."
exec sp_instmsg 18864, "Step: Server configuration initialization succeeded."
exec sp_instmsg 18865, "Step: User information synchronization succeeded."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18866, "Step: Server configured in normal companion mode."
exec sp_instmsg 18867, "Error: Could not remove de-cluster servers."
exec sp_instmsg 18868, "Step: Removed the servers '%1!' and '%2!' from cluster configuration."
exec sp_instmsg 18869, "Step: syssession information synchronization succeeded."
exec sp_instmsg 18870, "Step: Primary databases are shutdown in secondary."
exec sp_instmsg 18871, "Step: Primary databases dropped from current secondary."
exec sp_instmsg 18872, "Step: Primary devices released from current secondary."
exec sp_instmsg 18873, "Step: Prepare failback for primary server completed successfully."
exec sp_instmsg 18874, "Server '%1!' could not be added to '%2!'."
exec sp_instmsg 18875, "Server ID for '%1!' is missing in server '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18876, "Step: Checking to See if the remote server is up."
exec sp_instmsg 18877, "Usage: sp_companion <srvr_name>, do_advisory, <option> [,action] <option> can be either 'all', 'help', <Group|Base attrib> <action> can either be <'display'|'compute'> 'compute' is the default."
exec sp_instmsg 18878, "Internal Error: Unprocessed Base Attributes exists."
exec sp_instmsg 18879, "Internal Error: Attributes other than Base Attributes exist. Attrib_name: '%1!', Attrib_type:'%2!', Attrib_ID: '%3!', Attrib_Func:'%4!'."
exec sp_instmsg 18880, "You cannot run the PREPARE_FAILBACK command when master_companion is not present. Try to roll back and initiate failover before using this command. Refer to documentation on troubleshooting for more details."

/*
**Messages for "sp_addlogin"	18881
*/

exec sp_instmsg 18881, "Unable to generate %1! for HA use. Please Refer to documentation for details."

/*
**Messages for "sp_addserver"	18882
*/

exec sp_instmsg 18882, "There is already a server named '%1!' in sysservers."

/*
**Messages for "sp_modifystats"	18884
*/

exec sp_instmsg 18884, "No statistics exist for column '%1!'."

/*
**Messages for "sp_addexternlogin"	18886
*/

exec sp_instmsg 18886, "Users with role '%1!' will be known as '%2!' in remote server '%3!'."

/*
**Messages for "sp_addserver"	18887
*/

exec sp_instmsg 18887, "Cannot have more than one physical or logical server entry for the ASEJB class."

/*
**Messages for "sp_extengine"	18888
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18888, "The server name specified does not exist."
exec sp_instmsg 18889, "The specified command '%1!' does not exist."

/*
**Messages for "sp_serveroption"	18890
*/

exec sp_instmsg 18890, "Only the 'external engine auto start' option can be enabled for the ejb class of servers."

/*
**Messages for "sp_dropserver"	18891
*/

exec sp_instmsg 18891, "Unable to drop server '%1!' because the attempt to stop the EJB Server failed."

/*
**Messages for "sp_extengine"	18892
*/

exec sp_instmsg 18892, "Unable to start the EJB Server. Check server errorlog for any additional information."
exec sp_instmsg 18893, "Unable to stop the EJB Server. Check server errorlog for any additional information."
exec sp_instmsg 18894, "Unable to determine the status of the EJB Server. Check server errorlog for any additional information."

/*
**Messages for "sp_config_rep_agent"	18895
*/

exec sp_instmsg 18895, "Illegal send buffer size '%1!' specified, legal send buffer sizes are 2K, 4K, 8K and 16K."
exec sp_instmsg 18896, "Illegal data limits filter mode '%1!' specified, legal filter modes are off, stop, skip, and truncate."

/*
**Messages for "sp_modifylogin"	18897
*/

exec sp_instmsg 18897, "User's default database '%1!' and current database '%2!' are different. Use 'usedb' to set your current database to the default database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18898, "Login script '%1!' is not valid."

/*
**Messages for "sp_engine"	18899
*/

exec sp_instmsg 18899, "Invalid value supplied to parameter '%1!'."

/*
**Messages for "sp_helprotect"	18900
*/

exec sp_instmsg 18900, "Implicit grant to public for SQLJ functions."

/*
**Messages for "sp_helpjava"	18901
*/

exec sp_instmsg 18901, "Objects that depend on this class:"
exec sp_instmsg 18902, "Class name: '%1!"

/*
**Messages for "sp_sproc_phrases"	18903
*/

exec sp_instmsg 18903, "SQLJ function"
exec sp_instmsg 18904, "SQLJ procedure"

/*
**Messages for "sp_companion"	18905
*/

exec sp_instmsg 18905, "Default cluster is not set, please check if HA is enabled on the current server."
exec sp_instmsg 18906, "The default cluster does not have a name specified in the system table. Please report this to Sybase Inc."
exec sp_instmsg 18907, "The cluster '%1!' has not been supported. Please check the current supported cluster list."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18908, "The current cluster is set to %1!."
exec sp_instmsg 18909, "The default cluster is: %1!."
exec sp_instmsg 18910, "The current cluster does not have a name specified in the system table. Please report this to Sybase Inc."
exec sp_instmsg 18911, "Supported cluster systems for %1! are:"
exec sp_instmsg 18912, "Supported cluster systems are:"
exec sp_instmsg 18913, "Setting cluster failed, please check the error log."

/*
**Messages for "sp_displaylogin"	18914
*/

exec sp_instmsg 18914, "Auto Login Script: %1!"

/*
**Messages for "sp_configure"	18915
*/

exec sp_instmsg 18915, "An additional %1! K bytes of memory is available for reconfiguration. This is the difference between 'max memory' and 'total logical memory'."
exec sp_instmsg 18916, "Changing the value of '%1!' to '%2!' increases the amount of memory ASE uses by %3! K."
exec sp_instmsg 18917, "Changing the value of '%1!' to '%2!' reduces the amount of memory ASE uses by %3! K. The reduced memory may be reused when this configure value changes, but will not be released until ASE restarts."

/*
**Messages for "sp_modifystats"	18921
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18921, "Unable to execute stored procedure '%1!'.This version of the procedure is based on a '%2!' byte column ID and is incompatible with the server's column ID size."
exec sp_instmsg 18922, "Command failed. The 'value' argument for 'MODIFY_DENSITY' must be greater than or equal to 0.0 and not more than 1.0 when the 'absolute' method is specified."
exec sp_instmsg 18923, "The density value of column group '%1!' exceeded 1.0 and has been set to 1.0. Processing continues."

/*
**Messages for "sp_engine"	18924
*/

exec sp_instmsg 18924, "The engine number to shutdown must be specified"

/*
**Messages for "sp_rebuild_text"	18925
*/

exec sp_instmsg 18925, "sp_rebuild_text failed. Check the ASE error log file."

/*
**Messages for "sp_audit"	18926
*/

exec sp_instmsg 18926, "Audit process successfully restarted."
exec sp_instmsg 18927, "Invalid auditing configuration parameters."
exec sp_instmsg 18928, "Audit process is already being restarted."
exec sp_instmsg 18929, "Audit process has not terminated."
exec sp_instmsg 18930, "Cannot create the audit process. See error log for details."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18931, "Unknown error '%1!' occurred when trying to restart the audit process."

/*
**Messages for "sp_configure"	18932
*/

exec sp_instmsg 18932, "Resulting configuration value and memory use have not changed from previous values: new configuration value %1!, previous value %2!."

/*
**Messages for "sp_client_addr"	18934
*/

exec sp_instmsg 18934, "spid not found"

/*
**Messages for "sp_dropalias"	18935
*/

exec sp_instmsg 18935, "Warning: You have forced the drop of the alias for login '%1!' which owns objects in the database. This may result in errors when those objects are accessed from or contain references to another database."

/*
**Messages for "sp_helptext"	18936
*/

exec sp_instmsg 18936, "You cannot use a grouping number for non-procedures."
exec sp_instmsg 18937, "There is no text for object '%1!' with grouping number %2!."

/*
**Messages for "sp_rename"	18938
*/

exec sp_instmsg 18938, "Invalid third argument '%1!' entered. Valid values are 'index' or 'column'."
exec sp_instmsg 18939, "Both an index and a column named '%1!' exist. Use the third argument to specify whether you are renaming 'index' or 'column'."

/*
**Messages for "sp_estspace"	18940
*/

exec sp_instmsg 18940, "Error: Specified pagesize '%1!' is invalid. Valid values are '2048', '4096', '8192', '16384', or '2k', '4k', '8k', '16k'. Unit specifiers can also be 'K'."

/*
**Messages for "sp_tempdb"	18941
*/

exec sp_instmsg 18941, "Only the 'default' group is currently supported."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18942, "Internal Error: failed to create group."
exec sp_instmsg 18943, "Cannot drop '%1!' group."
exec sp_instmsg 18944, "Internal Error: failed to drop group."
exec sp_instmsg 18945, "'tempdb' is implicitly a member of 'default' group and cannot be a member of another group."
exec sp_instmsg 18946, "The database '%1!' does not exist or is not a user created temporary database."
exec sp_instmsg 18947, "Group '%1!' does not exist."
exec sp_instmsg 18948, "Database '%1!' is already a group member."
exec sp_instmsg 18949, "Internal Error: failed to add database to group."
exec sp_instmsg 18950, "Internal Error: failed to remove database from group."
exec sp_instmsg 18951, "'%1!' is not currently supported."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18952, "Only the 'sa' login is currently supported."
exec sp_instmsg 18953, "Internal Error: failed to add binding."
exec sp_instmsg 18954, "Usage:"
exec sp_instmsg 18955, "sp_tempdb 'help'"
exec sp_instmsg 18956, "sp_tempdb 'create', <groupname>"
exec sp_instmsg 18957, "sp_tempdb 'drop', <groupname>"
exec sp_instmsg 18958, "sp_tempdb 'add', <tempdbname>, <groupname>"
exec sp_instmsg 18959, "sp_tempdb 'remove', <tempdbname>, <groupname>"
exec sp_instmsg 18960, "sp_tempdb 'bind', <objtype>, <objname>, <bindtype>, <bindobj>, <scope>, <hardness>"
exec sp_instmsg 18961, "sp_tempdb 'unbind', <objtype>, <objname>, <scope>"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18962, "sp_tempdb 'show', <command>, <name>"
exec sp_instmsg 18963, "<objtype> = ['LG' ('login_name') | 'AP' ('application_name')]; <bindtype> = ['GR' ('group') | 'DB' ('database')]"
exec sp_instmsg 18964, "<command> = ['all' | 'gr' | 'db' | 'login' | 'app']"
exec sp_instmsg 18965, "sp_tempdb : Unrecognized command '%1!'. Execute 'sp_tempdb help' for usage."
exec sp_instmsg 18966, "sp_tempdb 'show', 'who', <dbname>"
exec sp_instmsg 18967, "Group '%1!' exists."

/*
**Messages for "sp_addauditrecord"	18968
*/

exec sp_instmsg 18968, "The database '%1!' does not have a database id of '%2!'."
exec sp_instmsg 18969, "The object '%1!' does not have an object id of '%2!'."

/*
**Messages for "sp_tempdb"	18970
*/

exec sp_instmsg 18970, "sp_tempdb 'who', <dbname>"
exec sp_instmsg 18971, "sp_tempdb 'unbindall_db', <tempdbname>"
go

dump transaction master with truncate_only
go

exec sp_instmsg 18972, "The system tempdb cannot be specified for this command."
exec sp_instmsg 18973, "<hardness> = ['hard' | 'soft']"

/*
**Messages for "sp_dboption"	18974
*/

exec sp_instmsg 18974, "Warning: Attempting to change database options for a temporary database. Database options must be kept consistent across all temporary databases."

/*
**Messages for "sp_tempdb"	18975
*/

exec sp_instmsg 18975, "Database '%1!' is not a member of the '%2!' group."
exec sp_instmsg 18976, "The '%1!' login can not have a hard binding."

/*
**Messages for "sp_companion"	18977
*/

exec sp_instmsg 18977, "Action `begin' failed for prepare_failback."
exec sp_instmsg 18978, "Action `end' failed for prepare_failback."

/*
**Messages for "sp_dboption"	18982
*/

exec sp_instmsg 18982, "async log service"

/*
**Messages for "sp_chgattribute"	18983
*/

exec sp_instmsg 18983, "The '%1!' attribute is not applicable to tables with datarow or datapage lock schemes."

/*
**Messages for "sp_dboption"	18984
*/

exec sp_instmsg 18984, "The 'async log service' option is not valid for system databases."

/*
**Messages for "sp_chgattribute"	18985
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 18985, "The value for '%1!' attribute must be either 0 or 1."

/*
**Messages for "sp_dboption"	18986
*/

exec sp_instmsg 18986, "The 'async log service' option is not valid for databases with log and data on the same device."

/*
**Messages for "sp_chgattribute"	18987
*/

exec sp_instmsg 18987, "The '%1!' attribute could not be set to the specified value for the object."

/*
**Messages for "sp_dbcc_updateconfig"	18990
*/

exec sp_instmsg 18990, "You must be the System Administrator (SA) to execute this procedure with a NULL database name (dbname) parameter."
exec sp_instmsg 18991, "Illegal value for 'max worker processes' encountered. Choose a value between 1 and 128 inclusive."
exec sp_instmsg 18992, "The default value of the dbcc configuration parameter '%1!' has been updated."
exec sp_instmsg 18993, "The value of the dbcc configuration parameter '%1!' for database %2! has been updated."
exec sp_instmsg 18994, "The dbcc configuration of '%1!' for database %2! does not exist. Your request to delete the corresponding configuration value has been ignored."
exec sp_instmsg 18995, "The dbcc configuration of '%1!' for database %2! has been deleted and replaced with the default value."

/*
**Messages for "sp_dbcc_recommendations"	18997
*/

exec sp_instmsg 18997, "At least one of the parameters 'date', or 'opid' must be non-NULL to execute this procedure."
go

dump transaction master with truncate_only
go

exec sp_instmsg 18998, "The checkstorage run corresponding to dbid '%1!', opid '%2!', reported no faults; therefore, no corrective action is necessary."
exec sp_instmsg 18999, "An error occurred while fetching data from a temporary table. If there are no other error messages and this error persists, please contact Sybase Technical Support."

/*
**Messages for "sp_dbcc_configreport"	19000
*/

exec sp_instmsg 19000, "You cannot run the stored procedure %1! because the dbccdb database does not exist."

/*
**Messages for "sp_dbcc_updateconfig"	19001
*/

exec sp_instmsg 19001, "The default value of the dbcc configuration parameter '%1!' has been deleted."
exec sp_instmsg 19002, "The dbcc configuration of '%1!' for database %2! has been deleted."
exec sp_instmsg 19003, "dbcc configuration parameter '%1!' does not have a default value. The delete request has been ignored."

/*
**Messages for "sp_dbcc_run_exclusions"	19004
*/

exec sp_instmsg 19004, "You must specify the operation (@op) to be performed for the specified exclusion list (@exclusion_list)."
exec sp_instmsg 19005, "You cannot specify a database name or an exclusion list for the 'listall' operation."
exec sp_instmsg 19006, "You must specify an exclusion list and its type for the '%1!' operation."
exec sp_instmsg 19007, "The specified operation '%1!' is invalid. Valid operations are 'add', 'drop', 'listall', and null."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19008, "Invalid exclusion list type '%1!' specified. Valid types are 'faults', 'tables', and 'combo'."
exec sp_instmsg 19009, "Ignoring invalid combo token '%1!'."
exec sp_instmsg 19010, "Error while parsing the exclusion list. Ignoring invalid token '%1!'."
exec sp_instmsg 19011, "Invalid fault type '%1!', ignoring token '%2!'."
exec sp_instmsg 19012, "Aborted dbcc exclusion list '%1!' operation due to error '%2!'."
exec sp_instmsg 19013, "Added %1! '%2!' dbcc exclusions for database '%3!'."
exec sp_instmsg 19014, "Dropped %1! '%2!' dbcc exclusions for database '%3!'."

/*
**Messages for "sp_dboption"	19015
*/

exec sp_instmsg 19015, "The 'async log service' option is only valid for configurations with at least 4 engines online."

/*
**Messages for "sp_dbcc_faultreport"	19016
*/

exec sp_instmsg 19016, "Ignoring the exclusion lists since the exclusion mode is not specified."
exec sp_instmsg 19017, "You must specify at least one of the exclusion lists to run this report with the 'extend' exclusion mode."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19018, "Invalid exclusion mode '%1!' specified. Valid modes are 'ignore', 'extend', and null."
exec sp_instmsg 19019, "Error '%1!' while inserting the temporary '%2!' exclusion '%3!'. Aborting fault report."

/*
**Messages for "sp_dbcc_recommendations"	19020
*/

exec sp_instmsg 19020, "The checkstorage run corresponding to dbid '%1!', object name '%2!', opid '%3!', reported no faults; therefore, no corrective action is necessary."

/*
**Messages for "sp_dbcc_patch_finishtime"	19021
*/

exec sp_instmsg 19021, "Cannot patch the finish time of the operation (opid '%1!', database '%2!'%3!). Check opid and retry."

/*
**Messages for "sp_dbcc_configreport"	19022
*/

exec sp_instmsg 19022, "The '%1!' parameter must be 'true' or 'false'."

/*
**Messages for "sp_dbcc_patch_finishtime"	19023
*/

exec sp_instmsg 19023, "Finish time must be earlier than the current time and later than the start time '%1!'."
exec sp_instmsg 19024, "Invalid operation type '%1!'. Valid types are 'checkstorage' and 'checkverify'."

/*
**Messages for "sp_dbcc_configreport"	19025
*/

exec sp_instmsg 19025, "Reporting default DBCC configuration information."

/*
**Messages for "sp_dbcc_updateconfig"	19026
*/

exec sp_instmsg 19026, "Database name is required when specifying type 'scan workspace' or 'text workspace'."
exec sp_instmsg 19027, "Aborted %1! operation due to error '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19028, "Ignoring redundant parameter ('%1!' = '%2!')."

/*
**Messages for "sp_optimal_text_space"	19029
*/

exec sp_instmsg 19029, "The status for '%1!' is set to %2!."
exec sp_instmsg 19030, "Usage: sp_optimal_text_space table_name, {true | false}"
exec sp_instmsg 19031, "Table '%1!' does not have a text or image column."
exec sp_instmsg 19032, "Due to system failure, the status for '%1!' has not been changed."

/*
**Messages for "sp_dbcc_help_fault"	19033
*/

exec sp_instmsg 19033, "Description of the fault corresponding to checkstorage type_code %1!:"
exec sp_instmsg 19034, "Suggested corrective actions for the fault corresponding to checkstorage type_code %1!, listed in recommended order:"
exec sp_instmsg 19035, "Recommended corrective action for the fault corresponding to checkstorage type_code %1!:"
exec sp_instmsg 19036, "Contact Sybase Technical Support if the recommended corrective action does not resolve the faults."

/*
**Messages for "sp_dbcc_summaryreport"	19037
*/

exec sp_instmsg 19037, "Recommended corrective action for faults reported by the checkstorage run corresponding to database %1!, opid %2!:"

/*
**Messages for "sp_dbcc_recommendations"	19038
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19038, "Suggested corrective actions for object %1!, objid %2!, listed in recommended order:"
exec sp_instmsg 19039, "Recommended corrective action for object %1!, objid %2!:"
exec sp_instmsg 19040, "Generating recommendations for database %1!."
exec sp_instmsg 19041, "Allocation page errors were found in the database corresponding to database id '%1!'."
exec sp_instmsg 19042, "Database level recommendations:"

/*
**Messages for "sp_dbcc_run_exclusions"	19044
*/

exec sp_instmsg 19044, "Added %1! '%2!' default dbcc exclusions applicable for all databases."
exec sp_instmsg 19045, "Dropped %1! '%2!' default dbcc exclusions."

/*
**Messages for "sp_updstatsneeded"	19046
*/

exec sp_instmsg 19046, "Table name: '%1!', index name: '%2!' not monitored for update stats, run sp_inittabstats on the specific table/index."

/*
**Messages for "sp_reorgneeded"	19047
*/

exec sp_instmsg 19047, "Index name should be prefixed with table name for index: '%1!'."

/*
**Messages for "sp_js_check_id"	19048
*/

exec sp_instmsg 19048, "Procedure %1!, parameter %2!, was not supplied, NULL or empty."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19049, "Procedure %1!, parameter %2!, requires an id value, not a name."
exec sp_instmsg 19050, "Procedure %1!, parameter %2!, the specified job does not exist."
exec sp_instmsg 19051, "Procedure %1!, parameter %2!, the specified schedule does not exist."
exec sp_instmsg 19052, "Procedure %1!, parameter %2!, the specified scheduled job does not exist."
exec sp_instmsg 19053, "Procedure %1!, parameter %2!, the specified table name is not known."
exec sp_instmsg 19054, "Procedure %1!, parameter %2!, requires a name, not an id value."
exec sp_instmsg 19055, "Procedure %1!, parameter %2!, may either be a name, which must begin with a non digit character, or a number which must be all digits."
exec sp_instmsg 19056, "Procedure %1!, parameter %2!, a zero value is not allowed."
exec sp_instmsg 19057, "Procedure %1!, parameter %2!, cannot be larger than 2147483647."

/*
**Messages for "sp_js_getkey"	19058
*/

exec sp_instmsg 19058, "Procedure %1!, jskey_name %2! unable to allocate a new id."

/*
**Messages for "sp_js_checksched"	19059
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19059, "Procedure %1!, a %2! entry already exists with the name %3!."
exec sp_instmsg 19060, "Procedure %1!, %2! must be a positive integer."
exec sp_instmsg 19061, "Procedure %1!, a repeating schedule must specify a value for @units."
exec sp_instmsg 19062, "Procedure %1!, units must be days, hours, minutes, dd, mm, hh, d, h or m."
exec sp_instmsg 19063, "Procedure %1!, both @days and @dates may not be used in a single schedule."
exec sp_instmsg 19064, "Procedure %1!, @days is incorrect. It should be a colon separated list of days of the week."
exec sp_instmsg 19065, "Procedure %1!, @dates is incorrect. It should be a colon separated list of dates in a month."
exec sp_instmsg 19066, "Procedure %1!, the @startdate is later than the @enddate."
exec sp_instmsg 19067, "Procedure %1!, the @starttime is later than the @endtime."

/*
**Messages for "sp_sjobcontrol"	19068
*/

exec sp_instmsg 19068, "Procedure %1!, failed to enable scheduled job, update error %2!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19069, "Procedure %1!, failed to disable scheduled job, update error %2!."

/*
**Messages for "sp_sjobcreate"	19070
*/

exec sp_instmsg 19070, "Procedure %1!, cannot set option (%2!) to value (%3!)."

/*
**Messages for "sp_unbindscheduledjob"	19071
*/

exec sp_instmsg 19071, "Procedure %1!, parameter %2!, more than one scheduled job exists with that name."

/*
**Messages for "sp_sjobdrop"	19072
*/

exec sp_instmsg 19072, "Procedure %1!, unable to perform the operation while running jobs are using %2!."
exec sp_instmsg 19073, "Procedure %1!, failed to delete an entry in the %2! table, delete error %3!."

/*
**Messages for "sp_sjobmodify"	19074
*/

exec sp_instmsg 19074, "Procedure %1!, failed to update an entry in the %2! table, update error %3!."

/*
**Messages for "sp_sjobcreate"	19075
*/

exec sp_instmsg 19075, "Procedure %1!, failed to insert an entry in the %2! table, insert error %3!."

/*
**Messages for "sp_sjobmodify"	19076
*/

exec sp_instmsg 19076, "Procedure %1!, failed to read an entry in the %2! table, select error %3!."

/*
**Messages for "sp_sjobhistory"	19077
*/

exec sp_instmsg 19077, "Procedure %1!, only a user with the js_admin role can specify the owner or all_users."

/*
**Messages for "sp_sjobhelp"	19078
*/

exec sp_instmsg 19078, "Procedure %1!, unknown option (%2!)."

/*
**Messages for "sp_sjobdrop"	19079
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19079, "Procedure %1!, unable to perform the operation while scheduled jobs are still using %2!."

/*
**Messages for "sp_sjobmodify"	19080
*/

exec sp_instmsg 19080, "Procedure %1!, %2! is not a valid server username."

/*
**Messages for "sp_sjobcontrol"	19081
*/

exec sp_instmsg 19081, "Procedure %1!, the cmd %2! is not valid with a running job id."
exec sp_instmsg 19082, "Procedure %1!, parameter %2!, the specified runid does not exist."

/*
**Messages for "sp_sjobmodify"	19083
*/

exec sp_instmsg 19083, "Procedure %1!, you do not have permission to access the specified scheduledjob, job, schedule or running job - %2!."
exec sp_instmsg 19084, "Procedure %1!, you do not have permission to modify information for the specified scheduled job, job, schedule or running job."

/*
**Messages for "sp_sjobhistory"	19085
*/

exec sp_instmsg 19085, "Procedure %1!, all the arguments are NULL, at least one must be supplied."

/*
**Messages for "sp_sjobcontrol"	19086
*/

exec sp_instmsg 19086, "Procedure %1!, internal error duplicate rows with runid %2!, in table %3!."

/*
**Messages for "sp_sjobmodify"	19087
*/

exec sp_instmsg 19087, "Procedure %1!, only the owner of a job may set the run_as_owner property."
exec sp_instmsg 19088, "Procedure %1!, @properties='%2!', invalid property name or value."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19089, "Procedure %1!, @properties='%2!', a property cannot be used with the scheduledjob, job or schedule."

/*
**Messages for "sp_sjobcreate"	19090
*/

exec sp_instmsg 19090, "Procedure %1!, @option='%2!', <%3!> the option name or value is missing or invalid."

/*
**Messages for "sp_js_check_id"	19091
*/

exec sp_instmsg 19091, "Procedure %1!, %2! is not a valid name."

/*
**Messages for "sp_sjobcreate"	19092
*/

exec sp_instmsg 19092, "Procedure %1!, the name or id of a scheduled job or a job is needed when options for jobs are supplied."
exec sp_instmsg 19093, "Procedure %1!, the name or id of a scheduled job or a schedule is needed when options for schedules are supplied."
exec sp_instmsg 19094, "Procedure %1!, the name or id of a scheduled job is needed when options for scheduledjobs are supplied."
exec sp_instmsg 19095, "Procedure %1!, cannot modify job fields in an existing job."
exec sp_instmsg 19096, "Procedure %1!, cannot modify schedule fields in an existing schedule."

/*
**Messages for "sp_js_check_id"	19097
*/

exec sp_instmsg 19097, "Procedure %1!, %2! is a non-unique name for a scheduledjob, job or schedule, the id value must be used."

/*
**Messages for "sp_sjobcreate"	19098
*/

exec sp_instmsg 19098, "Procedure %1!, @name='%2!' the name or id is missing or invalid."

/*
**Messages for "sp_js_history_thresh"	19099
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19099, "Procedure %1!, Warning the free data space threshold in database %2! has been exceeded. Segment %3! has %4! free pages, attempting to create space by cleaning job history and output."
exec sp_instmsg 19100, "Procedure %1!, the caller must have js_admin_role or sa_role role and be within the sybmgmtdb database."
exec sp_instmsg 19101, "Procedure %1!, after cleaning job history and output the free space is %2!."
exec sp_instmsg 19102, "Procedure %1!, WARNING: at least %2! free space is needed. Intervention is required to create space in the database."
exec sp_instmsg 19103, "Procedure %1!, History (rows): current %2!, target %3!. Output (rows): current %4!, target %5!. Free space (pages): current %6!, target %7!."

/*
**Messages for "sp_deviceattr"	19104
*/

exec sp_instmsg 19104, "'%1!' attribute of device '%2!' turned '%3!'. Restart Adaptive Server for the change to take effect."

/*
**Messages for "sp_configure"	19106
*/

exec sp_instmsg 19106, "Cannot change the value of configuration parameter 'global cache partition number' when the server is in recovery."
exec sp_instmsg 19107, "Cannot change the value of configuration parameter 'max concurrently recovered dbs' because the server is still in recovery setup."
exec sp_instmsg 19108, "Cannot change the configuration parameter 'max concurrently recovered dbs' to %1! when the server is in recovery. The only value allowed is 1."
exec sp_instmsg 19109, "Cannot change the value of configuration parameter 'global async prefetch limit' when the server is in recovery."

/*
**Messages for "sp_dbrecovery_order"	19110
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19110, "%1!: Illegal mode for recovery order. The only legal modes are 'strict' or 'relax'."

/*
**Messages for "sp_do_poolconfig"	19111
*/

exec sp_instmsg 19111, "Cannot change the pool configurations in the '%1!' when the server is in recovery."

/*
**Messages for "sp_dboption"	19112
*/

exec sp_instmsg 19112, "Running CHECKPOINT on database '%1!' for option '%2!' to take effect."
exec sp_instmsg 19113, "CHECKPOINT command failed. Run the CHECKPOINT command in database '%1!' for the change to take effect."

/*
**Messages for "sp_configure"	19114
*/

exec sp_instmsg 19114, "The value of 'number of open databases' cannot be reduced during recovery."

/*
**Messages for "sp_chgattribute"	19115
*/

exec sp_instmsg 19115, "A value must be specified for attribute '%1!'."
exec sp_instmsg 19116, "Table '%1!' does not have an identity column."
exec sp_instmsg 19117, "The value %1! for '%2!' attribute must be greater than or equal to the current maximum identity value %3!."
exec sp_instmsg 19118, "Object '%1!' is currently being accessed by other users. Failed to update attribute '%2!'."

/*
**Messages for "sp_unbindcache_all"	19119
*/

exec sp_instmsg 19119, "You cannot use sp_unbindcache_all since 'tempdb' is bound to this cache. Instead use sp_unbindcache for each object bound to this cache or runsp_unbindcache_all after unbinding 'tempdb' with sp_unbindcache."

/*
**Messages for "sp_bindcache"	19120
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19120, "Cache binding changes for 'tempdb' are not dynamic. Adaptive Server must be restarted for the change to take effect."

/*
**Messages for "sp_sysmon_collect_mda"	19121
*/

exec sp_instmsg 19121, "%1!: Permission denied. This operation requires mon_role"

/*
**Messages for "sp_sysmon_collect"	19122
*/

exec sp_instmsg 19122, "%1! is not installed. Please run '%2!' script with appropriate role %3!"

/*
**Messages for "sp_jst_dump_dbs_to_disk"	19123
*/

exec sp_instmsg 19123, "%1! value of %2! is invalid."

/*
**Messages for "sp_jst_dump_db_to_disk"	19124
*/

exec sp_instmsg 19124, "Backup for database %1! on %2! failed."
exec sp_instmsg 19125, "Database %1! successfully backed up on %2!."

/*
**Messages for "sp_jst_update_statistics"	19126
*/

exec sp_instmsg 19126, "UPDATE STATISTICS command for table %1! failed."
exec sp_instmsg 19127, "UPDATE STATISTICS command for table %1!, index %2! failed."
exec sp_instmsg 19128, "UPDATE STATISTICS command for table %1! succeeded."
exec sp_instmsg 19129, "UPDATE STATISTICS command for table %1!, index %2! succeeded."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19130, "Threshold values not exceeded so UPDATE STATISTICS did not run for table %1!."

/*
**Messages for "sp_jst_delete_stats"	19131
*/

exec sp_instmsg 19131, "Cannot delete statistics for table %1!."
exec sp_instmsg 19132, "Cannot recompile stored procedures and triggers for table %1!."

/*
**Messages for "sp_jst_get_mdcache_type_config"	19133
*/

exec sp_instmsg 19133, "Procedure %1!, invalid metadata cache type, value must be 0, 1, or 2."

/*
**Messages for "sp_jst_reclaim_index_space"	19134
*/

exec sp_instmsg 19134, "There are no indexes associated with table %1! for which to reclaim space."
exec sp_instmsg 19135, "NUMBER OF MINUTES is required when RESUME option is specified."
exec sp_instmsg 19136, "REORG RECLAIM SPACE for table %1!, index %2! failed."
exec sp_instmsg 19137, "REORG RECLAIM SPACE for table %1!, index %2! succeeded."

/*
**Messages for "sp_jst_reclaim_table_space"	19138
*/

exec sp_instmsg 19138, "REORG RECLAIM SPACE for table %1! failed."
exec sp_instmsg 19139, "REORG RECLAIM SPACE for table %1! succeeded."

/*
**Messages for "sp_jst_reconf_locks"	19140
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19140, "number of locks changed to %1!"

/*
**Messages for "sp_jst_reconf_usr_conns"	19141
*/

exec sp_instmsg 19141, "Adaptive Server version %1! does not support dynamically changing the memory allocation method."
exec sp_instmsg 19142, "Cannot reconfigure user connections."
exec sp_instmsg 19143, "UPPER BUFFER PERCENTAGE value for number of user connections was not supplied, NULL, or empty."
exec sp_instmsg 19144, "LOWER BUFFER PERCENTAGE value for number of user connections was not supplied, NULL, or empty."
exec sp_instmsg 19145, "User connections reconfigured to %1!."

/*
**Messages for "sp_jst_rebuild_indexes"	19146
*/

exec sp_instmsg 19146, "Not enough space to run Reorg Rebuild command on table %1!."

/*
**Messages for "sp_jst_dump_tran_log"	19147
*/

exec sp_instmsg 19147, "Transaction log backup for database %1! failed on %2!."
exec sp_instmsg 19148, "Transaction log backup for database %1! succeeded on %2!."

/*
**Messages for "sp_dbextend"	19149
*/

exec sp_instmsg 19149, "Usage: sp_dbextend [ arguments ... ]"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19150, "Usage: sp_dbextend help [, <command type> ]"
exec sp_instmsg 19151, "Usage: sp_dbextend 'set', { %1! } {, arguments ...}. Use: sp_dbextend 'help','set' for more information."
exec sp_instmsg 19152, "Usage: sp_dbextend 'set', 'threshold', @dbname, @segmentname, @freespace"
exec sp_instmsg 19153, "Usage: sp_dbextend 'set', 'database', @dbname, @segmentname { [, @growby ] [, @maxsize ] }"
exec sp_instmsg 19154, "Usage: sp_dbextend 'set', 'device', @devicename { [, @growby ] [, @maxsize ] }"
exec sp_instmsg 19155, "Usage: sp_dbextend 'clear', { %1! } {, arguments ...}. Use: sp_dbextend 'help', 'clear' for more information."
exec sp_instmsg 19156, "Usage: sp_dbextend 'clear', 'threshold', @dbname, @segmentname [, @freespace ]"
exec sp_instmsg 19157, "Usage: sp_dbextend 'clear', 'database' [, @dbname [, @segmentname ] ]"
exec sp_instmsg 19158, "Usage: sp_dbextend 'clear', 'device' [, @devicename ]"
exec sp_instmsg 19159, "Usage: sp_dbextend 'modify', { 'database' | 'device' } {, arguments ...}. See: sp_dbextend 'help', 'modify' for more information."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19160, "Usage: sp_dbextend 'modify', 'database', @dbname, @segmentname, { 'growby' | 'maxsize' }, @newvalue"
exec sp_instmsg 19161, "Usage: sp_dbextend 'modify', 'device', @devicename, { 'growby' | 'maxsize' }, @newvalue"
exec sp_instmsg 19162, "Usage: sp_dbextend { 'list' | 'listfull' } [, 'database' [, @dbname [, @segmentname [, @ORDER_BY_clause ] ] ] ]"
exec sp_instmsg 19163, "Examples: sp_dbextend 'list'"
exec sp_instmsg 19164, "          sp_dbextend 'list', 'dat', mypubs2"
exec sp_instmsg 19165, "          sp_dbextend 'list', 'dat', mypubs2, logsegment"
exec sp_instmsg 19166, "          sp_dbextend 'list', 'dat', mypubs2, logsegment, 'order by segment, item'"
exec sp_instmsg 19167, "Usage: sp_dbextend { 'list' | 'listfull' } [, 'device' [, @devicename [, @ORDER_BY_clause ] ] ]"
exec sp_instmsg 19168, "Examples: sp_dbextend 'list', 'dev', pubs2_datadev1"
exec sp_instmsg 19169, "          sp_dbextend 'list', 'dev', NULL, 'order by name, item'"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19170, "Usage: sp_dbextend %1!, @dbname, @segmentname [, @iterations ]"
exec sp_instmsg 19171, "Valid command types are: %1!"
exec sp_instmsg 19172, "Usage: sp_dbextend 'trace', {'on' | 'off' }"
exec sp_instmsg 19173, "Usage: sp_dbextend 'reload [defaults]'"
exec sp_instmsg 19174, "Set space expansion threshold and rules for a database, segment."
exec sp_instmsg 19175, "Set space expansion rules for a device."
exec sp_instmsg 19176, "Size specifiers must be >= 0. Examples for size specifiers:"
exec sp_instmsg 19177, "  @freespace can be : '100', '200m', '0.5g'"
exec sp_instmsg 19178, "@growby can be : '100', '200m', '0.5g', '10%%', '0', '0%%'"
exec sp_instmsg 19179, "  @maxsize can be : '100', '200m', '0.5g'"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19180, "Use 'default' as the @dbname, @devicename argument for server-wide default properties."
exec sp_instmsg 19181, "Clear space expansion threshold for a database."
exec sp_instmsg 19182, "Clear space expansion rules for a database or device."
exec sp_instmsg 19183, "List any existing space expansion rules for a database or device."
exec sp_instmsg 19184, "NO REAL WORK WILL BE DONE. Simulate database / device expansion in a dry-run mode %1! time(s)."
exec sp_instmsg 19185, "These are the series of database/device expansions that would have happened if the threshold on database '%1!', segment '%2!' were to fire %3! time(s)."
exec sp_instmsg 19186, "Execute database / device expansion thresholds *NOW* %1! time(s)."
exec sp_instmsg 19187, "Reload system-defaults for auto-expansion, leaving user-specified values unchanged."
exec sp_instmsg 19188, "database"
exec sp_instmsg 19189, "device"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19190, "freespace"
exec sp_instmsg 19191, "growby"
exec sp_instmsg 19192, "maxsize"
exec sp_instmsg 19193, "Command '%1!' is either invalid, or non-unique. Valid command types are: %2!"
exec sp_instmsg 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
exec sp_instmsg 19195, "Modify space expansion rules for a database or device."
exec sp_instmsg 19196, "Space expansion policy already exists for object '%1!'. Use the MODIFY command to change the policy. Or, CLEAR this policy first, and then reissue the SET command. Use the LIST command to view the current policy."
exec sp_instmsg 19197, "Usage: %1! @dbname, @segname [, @space_left_lpages [, @status ] ]."
exec sp_instmsg 19198, "Threshold fires: Iteration: %1!."
exec sp_instmsg 19199, "You must be in database '%1!' to run this command. Issue: 'USE %2!', then run this procedure again."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19200, "No policy information exists in master.dbo.sysattributes for the requested arguments."
exec sp_instmsg 19201, "%1!: Permission denied. This operation requires System Administrator (sa_role) role, or DBO of database '%2!'."
exec sp_instmsg 19202, "Warning! The command %1! may fail at runtime as it requires the following roles that you do not possess: %2!."
exec sp_instmsg 19203, "No policy found for database '%1!', segment name '%2!' for property '%3!'."
exec sp_instmsg 19204, "No policy found for device '%1!' for property '%2!'."
exec sp_instmsg 19205, "%1!Internal Error. %2!."

/*
**Messages for "sp_exec_SQL"	19206
*/

exec sp_instmsg 19206, "%1!: Execute immediate SQL failed. SQL statement is: %2!"

/*
**Messages for "sp_dbextend"	19207
*/

exec sp_instmsg 19207, "%1!: Pattern specifiers are not allowed for the argument '%2!' to this command."
exec sp_instmsg 19208, "The 'set' operation for 'default' objects is not permitted. Users authorized with 'sa_role' should run the 'reload [defaults]' commands, instead."
exec sp_instmsg 19209, "Deleted %1! rows and inserted %2! new rows for system defaults."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19210, "Syntax error. Extra arguments passed to '%1!' command. Run: %2! 'help', '%3!' for usage information."
exec sp_instmsg 19211, "Simulate execution of space expansion thresholds <n> times."
exec sp_instmsg 19212, "The 'modify' operation for 'threshold' is not supported. Use the sp_modifythreshold procedure to perform the desired modification."
exec sp_instmsg 19213, "Invalid argument or unsupported command: %1!."
exec sp_instmsg 19214, "Threshold action procedure '%1!' fired in db '%2!' on segment '%3!'. Space left: %4! logical pages ('%5!M')."
exec sp_instmsg 19215, "To actually expand the database manually for this threshold, issue: %1! '%2!', '%3!', '%4!', '%5!'"
exec sp_instmsg 19216, "%1!Device %2! of size %3!M resized by %4!M to a total size of %5!M."
exec sp_instmsg 19217, "Summary of device/database sizes after %1! simulated extensions:"
exec sp_instmsg 19218, "Database '%1!', segment '%2!' would be altered from an initial size of '%3!M' by '%4!M' for a resultant total size of '%5!M'."
exec sp_instmsg 19219, "Database '%1!', segment '%2!' is configured for auto expansion at a free space of %3! logical pages ('%4!M') which is less than or within the hysteresis region of the current last-chance threshold at %5! logical pages ('%6!M')."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19220, "Auto-expansion threshold procedure for database '%1!', segment '%2!' already exists at a free space of %3! pages ('%4!M'). Use the CLEAR sub-command to clear it first. Or, use the %5! procedure to drop the existing threshold procedure."
exec sp_instmsg 19221, "Usage: sp_dbextend 'check', 'database' [, @dbname [, @segmentname ] ]"
exec sp_instmsg 19222, "Check existing auto-expansion rules for a database, segment pair."
exec sp_instmsg 19223, "Segments '%1!' and '%2!' in database '%3!' are mapped to the same set of devices, and segment '%4!' is already set for auto-expansion. This makes it unnecessary to set the '%5!' segment for auto-expansion."
exec sp_instmsg 19224, "Segment name cannot be specified when database name is '%1!'. %2!"
exec sp_instmsg 19225, "Rules for 'default' databases apply to all segments."
exec sp_instmsg 19226, "Segment name should be NULL when clearing rules for databases that no longer exist."
exec sp_instmsg 19227, "Cannot modify rules for database '%1!' as it does not exist. Only operation possible on nonexistent database(s) is: %2! '%3!'"
exec sp_instmsg 19228, "Usage: sp_dbextend { 'list' | 'listfull' }, [ 'threshold' [ , @dbname [, @segmentname ] ] ]"

/*
**Messages for "sp_date_time_types"	19229
*/

exec sp_instmsg 19229, "The following objects have columns or parameters of type date or time. Change these types and rerun this procedure before returning to a pre-12.5.1 version of Adaptive Server."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19230, "The following remote/external tables use date or time types. Remove each table or run ALTER TABLE with trace flag 11221 to change only the proxy table schema."
exec sp_instmsg 19231, "There are no more stored procedures or tables that have either columns or parameters of type date or time. Procedural objects are being marked for recompilation and when complete you can reboot with a pre-12.5.1 version of Adaptive Server."

/*
**Messages for "sp_dbextend"	19232
*/

exec sp_instmsg 19232, "%1! Internal error. This procedure should be executed in database '%2!' but was instead executed in database '%3!'."
exec sp_instmsg 19233, "%1! Internal error. Temp table '%2!' already contains %3! rows for database '%4!' inserted by procedure '%5!'."

/*
**Messages for "sp_date_time_types"	19234
*/

exec sp_instmsg 19234, "The following user types were created on date or time system types and should be removed before returning to a pre-12.5.1 version of Adaptive Server."

/*
**Messages for "sp_dbextend"	19235
*/

exec sp_instmsg 19235, "Database '%1!' was altered by total size '%2!M' for segment '%3!'."

/*
**Messages for "sp_addthreshold"	19236
*/

exec sp_instmsg 19236, "Cannot add or modify a threshold for this table."

/*
**Messages for "sp_select_autoformat"	19237
*/

exec sp_instmsg 19237, "No columns were found in syscolumns in database '%1!' for table '%2!'."
exec sp_instmsg 19238, "Internal error: Column's AS-name value '%1!' (AS-list column number %2!) resulted in multiple rows (%3!) being updated."

/*
**Messages for "sp_addthreshold"	19239
*/

exec sp_instmsg 19239, "Cannot add or modify thresholds."

/*
**Messages for "sp_jst_dump_tran_logs"	19240
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19240, "Transaction log dump for database %1! was skipped because row and time thresholds of %2! and %3! were not met."

/*
**Messages for "sp_dbextend"	19241
*/

exec sp_instmsg 19241, "Automatic expansion policy disabled for database '%1!' segment '%2!' due to error %3!. User with appropriate privileges can re-enable the policy using the 'ENABLE' command."
exec sp_instmsg 19242, "Automatic expansion policy disabled server-wide due to fatal error %1! in the master database encountered when expanding database '%2!' for segment '%3!'. Please resolve these errors and re-enable automatic expansion using the ENABLE sub-command."
exec sp_instmsg 19243, "Usage: sp_dbextend { 'enable' | 'disable' }, 'database' [, @dbname [, @segmentname ] ]"
exec sp_instmsg 19244, "Enable, or disable, automatic expansion policy for a database, segment pair, or server-wide."

/*
**Messages for "sp_helpthreshold"	19245
*/

exec sp_instmsg 19245, "disabled"
exec sp_instmsg 19246, "disabled by LCT"
exec sp_instmsg 19247, "enabled"
exec sp_instmsg 19248, "last-chance"
exec sp_instmsg 19249, "Log segment free space currently is %1! logical pages (%2!K)."

/*
**Messages for "sp_dbextend"	19250
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19250, "Usage: sp_dbextend 'who' [, '<spid>' | 'block' | 'all' ]"
exec sp_instmsg 19251, "Show who is running the automatic database expansion currently; on what database/segment, or device. Argument 'block' shows only those tasks that are currently blocked in this process, if any."
exec sp_instmsg 19252, "Consider installing the auto expansion procedure at a free space value sufficiently above that of the current last-chance threshold, separated from it by more than %1! pages."
exec sp_instmsg 19253, "Free space accounting is currently disabled for database '%1!'. This makes it impossible to trigger auto expansion thresholds for segment '%2!'. Use sp_dboption to set '%3!' to FALSE for this database."
exec sp_instmsg 19254, "Automatic database expansion is currently disabled server-wide. Skip expansion of database '%1!' segment '%2!'. User with '%3!' role can use the 'ENABLE' command to re-enable database expansion server-wide."

/*
**Messages for "sp_serveroption"	19255
*/

exec sp_instmsg 19255, "The option '%1!' can be set for '%2!' server class only."

/*
**Messages for "sp_maplogin"	19256
*/

exec sp_instmsg 19256, "Client authentication mapping updated."
exec sp_instmsg 19257, "The authentication mechanism '%1!' is not valid."

/*
**Messages for "sp_displaylogin"	19258
*/

exec sp_instmsg 19258, "Authenticate with: %1!"

/*
**Messages for "sp_maplogin"	19259
*/

exec sp_instmsg 19259, "Warning. Authentication mechanism '%1!' is not enabled."

/*
**Messages for "sp_monitor"	19260
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19260, "Invalid argument or unsupported command. Use sp_monitor 'help' to get usage information."
exec sp_instmsg 19261, "Executing option '%1!' '%2!' requires the '%3!' '%4!' option to be executed first."

/*
**Messages for "sp_monitor_connection"	19262
*/

exec sp_instmsg 19262, "%1!' '%2!' requires the parameter '%3!' to be set to at least '%4!' bytes. Set the configuration parameter to '%5!' bytes and restart Adaptive Server"

/*
**Messages for "sp_monitor_help"	19263
*/

exec sp_instmsg 19263, "Usage: sp_monitor"
exec sp_instmsg 19264, "Usage: sp_monitor [ connection, [ cpu | diskio | elapsed time]]"
exec sp_instmsg 19265, "Examples: sp_monitor 'connection', 'elapsed time'"
exec sp_instmsg 19266, "Usage: sp_monitor [ event, [spid]]"
exec sp_instmsg 19267, "Examples: sp_monitor 'event', '5'"
exec sp_instmsg 19268, "Usage: sp_monitor [ procedure, [ dbname , [ procname, [, summary | detail]]]]"
exec sp_instmsg 19269, "Examples: sp_monitor 'procedure'"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19270, "Usage: sp_monitor [ enable ]"
exec sp_instmsg 19271, "Examples: sp_monitor 'enable'"
exec sp_instmsg 19272, "Usage: sp_monitor [ disable ]"
exec sp_instmsg 19273, "Examples: sp_monitor 'disable'"
exec sp_instmsg 19274, "Usage: sp_monitor [ statement, [ cpu | diskio | elapsed time]]"
exec sp_instmsg 19275, "Examples: sp_monitor 'statement', 'elapsed time'"

/*
**Messages for "sp_monitor_procedure"	19278
*/

exec sp_instmsg 19278, "Enter a valid database name"

/*
**Messages for "sp_monitor_help"	19279
*/

exec sp_instmsg 19279, "Examples: sp_monitor 'procedure','employee_db'"
exec sp_instmsg 19280, "Examples: sp_monitor 'procedure', 'employee_db', 'sp_get_salary'"
exec sp_instmsg 19281, "Examples: sp_monitor 'procedure','detail'"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19282, "Examples: sp_monitor 'procedure', 'employee_db', 'sp_get_employee_id', 'detail'"

/*
**Messages for "sp_msgadmin"	19283
*/

exec sp_instmsg 19283, "Usage: sp_msgadmin 'list', 'provider' [, provider_name]"
exec sp_instmsg 19284, "Usage: sp_msgadmin 'list', 'login' [, provider_name [,login_name]]"
exec sp_instmsg 19285, "Usage: sp_msgadmin 'register', 'provider', provider_name, provider_class, messaging_provider_URL"
exec sp_instmsg 19286, "Usage: sp_msgadmin 'register', 'login', provider_name, local_login, provider_login, provider_password [,role_name]"
exec sp_instmsg 19287, "Usage: sp_msgadmin 'register', 'subscription', subscription_name, endpoint [,selector [,delivery_option [, durable_name, client_id]]]"
exec sp_instmsg 19289, "Usage: sp_msgadmin 'default', 'login', provider_name, provider_login, provider_password"
exec sp_instmsg 19290, "Usage: sp_msgadmin 'remove', 'provider', provider_name"
exec sp_instmsg 19291, "Usage: sp_msgadmin 'remove', 'login', provider_name, local_login [,role]"
exec sp_instmsg 19292, "Usage: sp_msgadmin 'remove', 'subscription', subscription_name"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19293, "Unrecognized command for 'sp_msgadmin, %1! %2!' call."
exec sp_instmsg 19294, "Unrecognized subcommand for 'sp_msgadmin %1!, %2!' call."
exec sp_instmsg 19295, "Extra argument(s) for 'sp_msgadmin %1! %2!' call."
exec sp_instmsg 19296, "The 'sp_msgadmin %1! %2!' call requires the '%3!' argument."
exec sp_instmsg 19297, "Subscription name '%1!' is already registered."
exec sp_instmsg 19298, "Unable to register subscription name ('%1!')."
exec sp_instmsg 19299, "The length of '%1!' cannot be greater than 127 bytes."
exec sp_instmsg 19300, "There is already a subscription with the same durable name and client id."
exec sp_instmsg 19301, "Usage: sp_msgadmin 'list', 'subscription' [,subscription_name]"
exec sp_instmsg 19302, "Cannot run this command because real time messaging is not enabled. A user with System Administrator (SA) role must reconfigure the system to enable real time messaging."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19303, "The 'delivery_option' argument must be 'local', 'nolocal', or null."
exec sp_instmsg 19304, "Only one of the 'local_login' and 'role' parameters can be non-null"

/*
**Messages for "sp_helpartition"	19305
*/

exec sp_instmsg 19305, "There is no partition named '%1!' for table '%2!', index '%3!'."

/*
**Messages for "sp_msgadmin"	19306
*/

exec sp_instmsg 19306, "If the 'client_id' argument is specified, the 'durable_name' argument must also be specified."

/*
**Messages for "sp_webservices"	19307
*/

exec sp_instmsg 19307, "Generating proxy tables using sds [%1!] for WSDL URI: [%2!]"
exec sp_instmsg 19308, "Found WSDL Match for [%1!]"
exec sp_instmsg 19309, "The WSDL URI [%1!] was not found in the system."
exec sp_instmsg 19310, "Updating timeout entries for WSDL URI [%1!] with [%2!]"
exec sp_instmsg 19311, "Removing all web service meta data...."
exec sp_instmsg 19312, "Deleting entries for WSDL URI [%1!]"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19313, "To remove a webservice, a valid SDS server must be supplied. The SDS server [%1!] was not found. Please use sp_addserver to add the SDS server."
exec sp_instmsg 19316, "Command line options for sp_webservices sp_webservices 'add', 'wsdl uri', [, sds name] sp_webservices 'list' ['wsdl uri'], [, sds name] sp_webservices 'remove' 'wsdl uri' [, sds name] sp_webservices 'modify', 'wsdl uri', timeout=value sp_webservices help"
exec sp_instmsg 19317, "Modify attribute information for a WSDL URI.  sp_webservices 'modify', 'wsdl uri', 'timeout=value wsdl uri -- Location of the WSDL URI to modify. timeout -- Length of time in seconds to wait for a web method to respond before aborting the operation."
exec sp_instmsg 19319, "To add a webservice, a valid SDS server must be supplied. The SDS server [%1!] was not found. Please use sp_addserver to add the SDS server."
exec sp_instmsg 19320, "Verify Consumer is running"
exec sp_instmsg 19321, "To add a webservice, a valid WSDL URI must be specified."
exec sp_instmsg 19322, "The WSDL URI [%1!] specified is already in the system. Please use sp_webservices remove first."
exec sp_instmsg 19323, "To list information about a webservice not loaded in the system, a SDS server must be supplied. The SDS server [%1!] was not found. Please use sp_addserver to add the SDS server."
exec sp_instmsg 19324, "Must specify a specific wsdl uri to modify."
exec sp_instmsg 19325, "Must specify something to change for modify."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19326, "[%1!] is not a valid option for sp_webservices modify."
exec sp_instmsg 19327, "Must specify item=value syntax for modify."

/*
**Messages for "sp_msgadmin"	19328
*/

exec sp_instmsg 19328, "Argument '%1!' is not a message provider."

/*
**Messages for "sp_dbcc_recommendations"	19329
*/

exec sp_instmsg 19329, "Suggested corrective actions for object %1! (id %2!), indid %3!, partition %4! (id %5!), listed in recommended order:"
exec sp_instmsg 19330, "Recommended corrective action for object %1! (id %2!), indid %3!, partition %4! (id %5!):"

/*
**Messages for "sp_webservices"	19331
*/

exec sp_instmsg 19331, "Cannot run this command as webservices is not enabled. A user with System Administrator (SA) role must reconfigure the system to enable webservices."
exec sp_instmsg 19332, "No matches found in sysattributes for WSDL URI: [%1!]."
exec sp_instmsg 19333, "To remove a webservice, a valid WSDL URI must be specified."

/*
**Messages for "sp_helpcomputedcolumn"	19334
*/

exec sp_instmsg 19334, "Warning: Configuration Parameter 'allow select on syscomments.text' is set to 0. Only the object owner or user with sa_role can access the text. The text for the computed column(s) cannot be displayed."
exec sp_instmsg 19335, "Warning: Configuration Parameter 'allow select on syscomments.text' is set to 0. Only the object owner or user with sa_role can access the text. The text for the functional index key(s) cannot be displayed."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19336, "Table '%1!' does not have any computed columns."
exec sp_instmsg 19337, "Text is encrypted."
exec sp_instmsg 19338, "Object has the following functional index keys"
exec sp_instmsg 19339, "Object has the following computed columns"

/*
**Messages for "sp_helpartition"	19340
*/

exec sp_instmsg 19340, "Warning: Configuration Parameter 'allow select on syscomments.text' is set to 0. Only the object owner or user with sa_role can access the text. The text for the partition condition cannot be displayed."

/*
**Messages for "sp_helpsegment"	19341
*/

exec sp_instmsg 19341, "Objects currently bound to segment '%1!':"
exec sp_instmsg 19342, "Objects on segment '%1!':"

/*
**Messages for "sp_countmetadata"	19343
*/

exec sp_instmsg 19343, "There are %1! user partitions in %2! database(s), requiring %3! Kbytes of memory. The 'open partitions' configuration parameter is currently set to %4!."

/*
**Messages for "sp_drop_metrics"	19344
*/

exec sp_instmsg 19344, "No qpmetrics record with id = '%1!' exists in this database."
exec sp_instmsg 19345, "No qpmetrics group with group id = '%1!' exists in this database."

/*
**Messages for "sp_backup_metrics"	19346
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19346, "qpmetrics group '%1!' is invalid or a group with this group ID already exists in this database."

/*
**Messages for "sp_help_metrics"	19347
*/

exec sp_instmsg 19347, "Usage: sp_metrics [ 'command', [ '@arg1', [ '@arg2' ] ] ]"
exec sp_instmsg 19348, "help - get help on a command"
exec sp_instmsg 19349, "flush - flush all metrics from memory to system tables"
exec sp_instmsg 19350, "drop - drop a metric ID or a group of metrics"
exec sp_instmsg 19351, "backup - move the metrics in the default group to a backup group"
exec sp_instmsg 19352, "Usage: sp_metrics 'help' [, 'command' ]"
exec sp_instmsg 19353, "Usage: sp_metrics 'flush'"
exec sp_instmsg 19354, "Usage: sp_metrics 'drop', '@gid' [, '@id' ]"
exec sp_instmsg 19355, "Usage: sp_metrics 'backup', '@gid'"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19356, "'%1!' is an unsupported command. Check command and retry sp_metrics"

/*
**Messages for "sp_metrics"	19357
*/

exec sp_instmsg 19357, "Syntax error. Extra arguments passed to '%1!' command. Run: sp_metrics 'help', '%2!' for usage information."

/*
**Messages for "sp_bindefault"	19358
*/

exec sp_instmsg 19358, "You cannot bind a default to a computed column."

/*
**Messages for "sp_bindrule"	19359
*/

exec sp_instmsg 19359, "You cannot bind a rule to a function-based index key."

/*
**Messages for "sp_msgadmin"	19360
*/

exec sp_instmsg 19360, "There is no subscription named '%1!'."

/*
**Messages for "sp_sysmon"	19361
*/

exec sp_instmsg 19361, "sp_sysmon cannot be executed with the noclear option unless a sample interval is specified."
exec sp_instmsg 19362, "It appears that the monitor counters have been cleared by another application since the beginning of the sample period. Please run the report again ensuring that the monitor counters are not cleared during the sample period."

/*
**Messages for "sp_sysmon_collect"	19363
*/

exec sp_instmsg 19363, "The specified sample interval is less than the time required to generate the baseline table (%1! seconds). Please specify a longer sample interval."

/*
**Messages for "sp_rjs_register"	19364
*/

exec sp_instmsg 19364, "'%1!' is not a valid server name."
exec sp_instmsg 19365, "A Job Scheduler server name is required; enter the name of the server with JS installed that you want to register."

/*
**Messages for "sp_registerjs"	19366
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19366, "%1!' is not a valid value for a host name."

/*
**Messages for "sp_rjs_register"	19367
*/

exec sp_instmsg 19367, "A host name is required when registering a Job Scheduler server."
exec sp_instmsg 19368, "A host port number is required when registering a Job Scheduler server."

/*
**Messages for "sp_rjs_unregister"	19369
*/

exec sp_instmsg 19369, "A Job Scheduler server name is required; enter the name of the server with JS installed that you want to unregister."
exec sp_instmsg 19370, "A host name is required when unregistering a Job Scheduler server."
exec sp_instmsg 19371, "A host port number is required when unregistering a Job Scheduler server."

/*
**Messages for "sp_rjs_register"	19372
*/

exec sp_instmsg 19372, "A host port number can not be negative. Enter a valid port number."

/*
**Messages for "sp_add_resource_limit"	19373
*/

exec sp_instmsg 19373, "WARNING: This limit will not take effect until resource limits are enabled for this server. Use sp_configure 'allow resource limits', 1."

/*
**Messages for "sp_sysmon_collect"	19374
*/

exec sp_instmsg 19374, "The monitor counter usage count was not decremented as expected when sp_sysmon end_sample was executed. If you wish to decrement the monitor counter usage count, execute the dbcc monitor decrement or dbcc monitor reset command."

/*
**Messages for "sp_encryption"	19376
*/

exec sp_instmsg 19376, "Invalid name '%1!'. This encryption key does not exist in the current database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19377, "Invalid option '%1!'. Should be 'display_cols'."

/*
**Messages for "sp_version"	19378
*/

exec sp_instmsg 19378, "Delete from the table %1! affected %2! rows but expected %3! rows to be deleted. Command aborted."
exec sp_instmsg 19379, "Update of the table %1! affected %2! rows but expected %3! rows to be updated. Command aborted."
exec sp_instmsg 19380, "Error in accessing the table %1!."
exec sp_instmsg 19381, "Invalid argument to %1!. It requires a non-null value."

/*
**Messages for "sp_encryption"	19382
*/

exec sp_instmsg 19382, "User '%1!' does not have select permission on encryption key '%2!'."
exec sp_instmsg 19384, "The '%1!' parameter is required with '%2!' parameter."
exec sp_instmsg 19387, "The 'encrypted columns' feature must be configured to run sp_encryption 'help'."

/*
**Messages for "sp_logintrigger"	19388
*/

exec sp_instmsg 19388, "Global loging trigger updated."

/*
**Messages for "sp_deviceattr"	19389
*/

exec sp_instmsg 19389, "The attributes %1! and %2! can not be both set to ON for the same device."

/*
**Messages for "sp_locklogin"	19390
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19390, "One or more accounts do not exist on the companion server."
exec sp_instmsg 19391, "Warning: One or more accounts specified are active."
exec sp_instmsg 19392, "Permission Denied. The current account is already locked."
exec sp_instmsg 19393, "The sets of sa/sso logins on the primary and companion servers are not same."
exec sp_instmsg 19394, "The set of logins specified is empty."
exec sp_instmsg 19395, "The login or role to be excluded from locking/unlocking is invalid."

/*
**Messages for "sp_shmdumpconfig"	19396
*/

exec sp_instmsg 19396, "Include errorlog in dump file: %1!"
exec sp_instmsg 19397, "Merge parallel files after dump: %1!"
exec sp_instmsg 19398, "Number of dump threads: %1!"
exec sp_instmsg 19399, "Dump on conditions: %1!"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19400, "You must run 'sp_configure 'dump on conditions',1' to enable the shared memory dump facility."
exec sp_instmsg 19401, "Invalid dump configuration option: %1!"
exec sp_instmsg 19402, "Invalid configuration value '%1!' for option %2!"

/*
**Messages for "sp_msgadmin"	19403
*/

exec sp_instmsg 19403, "IBM MQ servers cannot have a registered login."
exec sp_instmsg 19404, "IBM MQ servers cannot have a default login."

/*
**Messages for "sp_js_checksched"	19405
*/

exec sp_instmsg 19405, "Procedure %1!, @days and @dates restrictions are not allowed for schedules with an interval of more than one day."

/*
**Messages for "sp_jst_update_statistics"	19406
*/

exec sp_instmsg 19406, "Current datachange value of %1! for table %2!, columns/indexes %3!, partition %4! does not meet or exceed the datachange threshold."
exec sp_instmsg 19407, "Datachange threshold is only applicable for ASE 15.0 and later. This value is being ignored."

/*
**Messages for "sp_webservices"	19408
*/

exec sp_instmsg 19408, "Cannot drop alias because it does not exist."
exec sp_instmsg 19409, "Specify the name of the alias to add."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19410, "Specify the database name associated with this alias."

/*
**Messages for "sp_create_text_index"	19411
*/

exec sp_instmsg 19411, "Text index name '%1!' is too long. Maximum length is %2!."

/*
**Messages for "sp_rename"	19412
*/

exec sp_instmsg 19412, "Cannot rename a deployed service."

/*
**Messages for "sp_estspace"	19414
*/

exec sp_instmsg 19414, "We estimate that index '%1!' will have more than 256 levels. ASE cannot create an index that deep."

/*
**Messages for "sp_encryption"	19415
*/

exec sp_instmsg 19415, "The '%1!' parameter is required for the '%2!' command."

/*
**Messages for "sp_configure"	19416
*/

exec sp_instmsg 19416, "Provider class '%1!' is not a recognized messaging provider class."

/*
**Messages for "sp_filter_metrics"	19417
*/

exec sp_instmsg 19417, "predicate '%1!' is an invalid filter condition."

/*
**Messages for "sp_help_metrics"	19418
*/

exec sp_instmsg 19418, "filter - delete metrics records based on filtering condition"
exec sp_instmsg 19419, "Usage: sp_metrics 'filter', '@gid' [, '@predicate' ]"

/*
**Messages for "sp_webservices"	19420
*/

exec sp_instmsg 19420, "Cannot specify an alias name that is longer than 255 characters."

/*
**Messages for "sp_metrics"	19421
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19421, "Syntax error. '%1!' should be a string representation of an integer, such as '100'."

/*
**Messages for "sp_webservices"	19422
*/

exec sp_instmsg 19422, "Specify an 'optionName' and an 'optionValue'."

/*
**Messages for "sp_dboption"	19423
*/

exec sp_instmsg 19423, "scratch"
exec sp_instmsg 19424, "Cannot run '%1!' on an archive database."

/*
**Messages for "sp_passwordpolicy"	19425
*/

exec sp_instmsg 19425, "This option checks to see if password contains login name as substring."
exec sp_instmsg 19426, "This option checks to see if the password contains the specified minimum number of digits."
exec sp_instmsg 19427, "This option checks to see if the password contains the specified minimum number of alphabetic characters."
exec sp_instmsg 19428, "This option checks to see if the password contains the specified minimum number of upper case characters."
exec sp_instmsg 19429, "This option checks to see if the password contains the specified minimum number of lower case characters."
exec sp_instmsg 19430, "This option checks to see if the password contains the specified minimum number of special characters."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19431, "This option specifies the number of days before password expiration, after which password expiration warning messages are displayed."
exec sp_instmsg 19432, "This option checks to see if a login needs to have an expired status on first login, after the login has just been created or the password reset by the SSO."

/*
**Messages for "sp_help_metrics"	19433
*/

exec sp_instmsg 19433, "threshold - set a threshold for dumping metrics to the catalog"
exec sp_instmsg 19434, "Usage: sp_metrics 'threshold', '{ lio_max | pio_max | exec_max | elap_max }' [, '@value' ]"

/*
**Messages for "sp_passwordpolicy"	19435
*/

exec sp_instmsg 19435, "Password expiration warning interval cannot be set unless the password expiration is set."
exec sp_instmsg 19436, "Password expiration warning interval cannot be greater than password expiration."
exec sp_instmsg 19437, "The sum of minimum number of uppercase characters and minimum number of lowercase characters in the password cannot be greater than minimum number of alphabetic characters."
exec sp_instmsg 19438, "The sum of the minimum numbers of alphabetic characters, digits, and special characters in a password cannot be greater than minimum length of the password."

/*
**Messages for "sp_shmdumpconfig"	19439
*/

exec sp_instmsg 19439, "WARNING: The maxdumps value for this dump condition is greater than 1. Using a configured file name may cause the dump file to be overwritten if more than one shared memory dump is performed."
exec sp_instmsg 19440, "WARNING: There is a dump file name configured for this dump condition. Setting maxdumps to a value greater than 1 may cause the dump file to be overwritten if more than one shared memory dump is performed."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19441, "The shared memory dump file name must be 30 characters or less in length."

/*
**Messages for "sp_js_checksched"	19442
*/

exec sp_instmsg 19442, "Procedure %1!, @days and @dates restrictions are not allowed for schedules with an interval of more than one day."

/*
**Messages for "sp_dboption"	19443
*/

exec sp_instmsg 19443, "You cannot set the 'scratch database' option for a temporary database."

/*
**Messages for "sp_passwordpolicy"	19444
*/

exec sp_instmsg 19444, "The range for %1! is %2! to %3!."

/*
**Messages for "sp_maplogin"	19445
*/

exec sp_instmsg 19445, "External name '%1!' is already a local login -- map request denied."

/*
**Messages for "sp_addlogin"	19446
*/

exec sp_instmsg 19446, "A login mapping for the name '%1!' already exists in this Server. Drop an existing mapping before creating a new mapping."

/*
**Messages for "sp_maplogin"	19447
*/

exec sp_instmsg 19447, "User '%1!' allows only '%2!' authentication mechanism to be used -- request denied."

/*
**Messages for "sp_modifylogin"	19448
*/

exec sp_instmsg 19448, "An existing login mapping for user '%1!' allows only '%2!' authentication mechanism to be used."

/*
**Messages for "sp_sysmon"	19449
*/

exec sp_instmsg 19449, "Invalid parameters. Both noclear and clear cannot be specified at the same time."

/*
**Messages for "sp_maplogin"	19450
*/

exec sp_instmsg 19450, "A mapping with authentication mechanism '%1!' is not allowed, only action 'drop' is permitted."

/*
**Messages for "sp_countmetadata"	19451
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19451, "Metadata counts in database '%1!' are:"
exec sp_instmsg 19452, "Metadata counts in all databases are:"

/*
**Messages for "sp_maplogin"	19453
*/

exec sp_instmsg 19453, "Cannot define a mapping for ALL authentications and ALL logins -- map request denied."

/*
**Messages for "sp_help"	19456
*/

exec sp_instmsg 19456, "Object is a computed column in table '%1!'."
exec sp_instmsg 19457, "Object is a function-based index key in table '%1!'."

/*
**Messages for "sp_help_metrics"	19459
*/

exec sp_instmsg 19459, "show - display the number of records in each metrics group"
exec sp_instmsg 19460, "Usage: sp_metrics `show`"

/*
**Messages for "sp_engine"	19461
*/

exec sp_instmsg 19461, "You can take this engine offline."

/*
**Messages for "sp_msgadmin"	19462
*/

exec sp_instmsg 19462, "Configuration value of jvmmaxthreads cannot be less than 1."
exec sp_instmsg 19463, "Configuration value of jvmmaxthreads '%1!' cannot be less than the configuration value of jvmminthreads '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19464, "Configuration value of jvmminthreads cannot be less than 0."
exec sp_instmsg 19465, "Configuration value of jvmthreadtimeout cannot be less than 0."
exec sp_instmsg 19466, "The value '%1!' is incorrect for '%2!' configuration."
exec sp_instmsg 19467, "Usage: sp_msgadmin 'config', 'jvmlogging', logging_level"
exec sp_instmsg 19468, "Usage: sp_msgadmin 'config', 'jvmpropertyfile', filepath"
exec sp_instmsg 19469, "Usage: sp_msgadmin 'config', 'jvmlogfile', filepath"
exec sp_instmsg 19470, "Usage: sp_msgadmin 'config', 'jvmmaxthreads', thread number"
exec sp_instmsg 19471, "Usage: sp_msgadmin 'config', 'jvmminthreads', thread number"
exec sp_instmsg 19472, "Usage: sp_msgadmin 'config', 'jvmthreadtimeout', thread timeout"
exec sp_instmsg 19473, "Usage: sp_msgadmin 'config', 'jvm' , jvm_parameter"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19474, "Illegal logging level '%1!' specified, legal logging level are off, all, etc."

/*
**Messages for "sp_ddlgen_database"	19475
*/

exec sp_instmsg 19475, "%1! not supported for archive databases. One or more of the databases named in this operation is an archive database."

/*
**Messages for "sp_monitor"	19476
*/

exec sp_instmsg 19476, "No monitoring features are currently enabled via %1!."
exec sp_instmsg 19477, "Monitoring related configuration options found to be enabled via %1!:"
exec sp_instmsg 19478, "Valid monitoring <type> is one of: %1!."

/*
**Messages for "sp_monitor_disable"	19479
*/

exec sp_instmsg 19479, "Disabling monitoring type '%1!'."

/*
**Messages for "sp_monitor_verify_setup"	19480
*/

exec sp_instmsg 19480, "%1! '%2!' requires the parameter '%3!' to be set, for example, to %4!. Set the configuration parameter using: %5!."

/*
**Messages for "sp_monitor_report"	19481
*/

exec sp_instmsg 19481, "Reporting from an archive is currently supported for only these monitoring types: %1!."
exec sp_instmsg 19482, "options supported for monitoring_type"
exec sp_instmsg 19483, "Example: Report deadlock events from a default archive named '%1!' in the current database:"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19484, "Example: Report deadlock events from an archive named '%1!%2!' in database %3!:"
exec sp_instmsg 19485, "Example: Report deadlock events for a particular day from an archive named '%1!%2!' in database '%3!':"

/*
**Messages for "sp_monitor_archive"	19486
*/

exec sp_instmsg 19486, "Archiving is currently supported for only these monitoring types: %1!."
exec sp_instmsg 19487, "Example: Archive deadlock events to a default archive named '%1!' in the current database:"
exec sp_instmsg 19488, "Example: Archive deadlock events to an archive named '%1!%2!' in %3!:"
exec sp_instmsg 19489, "Created new archive '%1!'."
exec sp_instmsg 19490, "Archived %1! rows to archive table '%2!' with timestamp '%3!'."
exec sp_instmsg 19491, "Archive prefix name '%1!' cannot exceed %2! bytes as this can cause the extended name of the archive table to be an invalid identifier."
exec sp_instmsg 19492, "Cannot use database '%1!' as a database to archive data as it is a '%2!' database."
exec sp_instmsg 19493, "Cannot use database '%1!' as a database to archive data as it does not have the '%2!' option set."

/*
**Messages for "sp_monitor"	19494
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19494, "Configuration: %1!"

/*
**Messages for "sp_monitor_procstack"	19495
*/

exec sp_instmsg 19495, "%1!Monitor a given spid (that may possibly be in a hung state), and if possible%2!generate a back trace of the procedures it is currently executing."
exec sp_instmsg 19496, "%1!To generate a procstack of your current connection, with a context block of 10 lines, do:"

/*
**Messages for "sp_monitor_deadlock"	19497
*/

exec sp_instmsg 19497, "Configure '%1!' config option to some reasonable value, say, %2!."
exec sp_instmsg 19498, "Examples: Deadlock Analysis from %1!:"
exec sp_instmsg 19499, "%1!Generate deadlock analysis for all deadlocks:"
exec sp_instmsg 19500, "%1!Generate deadlock analysis for a particular deadlock ID:"
exec sp_instmsg 19501, "%1!Generate verbose deadlock analysis for a particular deadlock ID:"
exec sp_instmsg 19502, "%1!Generate verbose deadlock analysis with page diagnostics for a particular deadlock ID:"
exec sp_instmsg 19503, "%1!Generate frequency of deadlocks by application name:"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19504, "%1!Generate frequency of deadlocks by table name:"
exec sp_instmsg 19505, "Examples: Deadlock Analysis from data archived in '%1!' table:"
exec sp_instmsg 19506, "%1!First archive deadlock analysis for all data into '%2!' table in current database '%3!':"
exec sp_instmsg 19507, "%1!Generate deadlock analysis for all data from '%2!..%3!' table:"
exec sp_instmsg 19508, "%1!Generate deadlock analysis from archived data '%2!' for a particular deadlock ID:"
exec sp_instmsg 19509, "%1!Generate verbose ouput for a particular deadlock ID from '%2!' in current database '%3!':"
exec sp_instmsg 19510, "%1!Generate deadlock analysis from archived data for all deadlocks on a given date from '%2!':"
exec sp_instmsg 19511, "%1!Generate frequency of deadlocks by date:"
exec sp_instmsg 19512, "%1!Generate frequency of deadlocks by application name:"
exec sp_instmsg 19513, "%1!Generate frequency of deadlocks by table name:"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19514, "Examples: Use 'prefix' sub-clause under 'archive', 'report' commands to name the archive table uniquely:"
exec sp_instmsg 19515, "%1!Archive all data to table named '%2!%3!' in current database '%4!':"
exec sp_instmsg 19516, "%1!Report from table named '%2!%3!' in current database '%4!':"

/*
**Messages for "sp_dbcc_plandb"	19517
*/

exec sp_instmsg 19517, "Recommended compression memory size is %1!."

/*
**Messages for "sp_dboption"	19518
*/

exec sp_instmsg 19518, "Warning: Attempting to change database options for a local temporary database. Database options must be kept consistent across all local temporary databases."

/*
**Messages for "sp_configure"	19519
*/

exec sp_instmsg 19519, "Cannot run sp_configure for server '%1!' since you are not connecting to it."
exec sp_instmsg 19520, "Cannot configure '%1!' for an instance, since it is a strictly cluster-wide option."
exec sp_instmsg 19521, "Cannot configure '%1!' to cluster-wide since all active instances have instance-specific setting on this option."

/*
**Messages for "sp_tempdb_markdrop"	19522
*/

exec sp_instmsg 19522, "Local system temporary database '%1!' is now marked for drop. If currently in use, then it can be dropped after shutting down cluster instance that owns it."
exec sp_instmsg 19523, "Drop mark is now cleared for database '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19524, "Usage: sp_tempdb_markdrop dbname [, {'mark' | 'unmark'}]"
exec sp_instmsg 19525, "Database '%1!' is not a local system temporary database. Only a local system temporary database can be marked for drop."
exec sp_instmsg 19526, "This stored procedure requires that ASE be in shared disk cluster mode."

/*
**Messages for "sp_crtsybsystemprocs"	19527
*/

exec sp_instmsg 19527, "The '%1!' database cannot be created. Terminating the installation."

/*
**Messages for "sp_dbextend"	19528
*/

exec sp_instmsg 19528, "The '%1!' database does not exist. Terminating the installation."

/*
**Messages for "sp_a_auditoptions"	19529
*/

exec sp_instmsg 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."

/*
**Messages for "sp_spaceusage"	19530
*/

exec sp_instmsg 19530, "Argument '%1!' is invalid with argument '%2!'. Type '%3!' for usage information."

/*
**Messages for "sp_spaceusage_object"	19531
*/

exec sp_instmsg 19531, "Either no match found for %1! '%2!' in database '%3!', or, no physical space is allocated for the object."
exec sp_instmsg 19532, "Warning: Some output column values in the result set may be incorrect. Running '%1!' may help correct them."
exec sp_instmsg 19533, "All the page counts in the result set are in the unit '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19534, "All the data in the result set are dated '%1!'."
exec sp_instmsg 19535, "Data was successfully archived into table '%1!'."

/*
**Messages for "sp_spaceusage"	19536
*/

exec sp_instmsg 19536, "No value for the %1! name given."
exec sp_instmsg 19537, "Invalid syntax or illegal use of the USING clause."

/*
**Messages for "sp_spaceusage_runcmd"	19538
*/

exec sp_instmsg 19538, "Command '%1!' successful."

/*
**Messages for "sp_spaceusage_showhelp"	19539
*/

exec sp_instmsg 19539, "For more information, use:"
exec sp_instmsg 19540, "For entity '%1!':"
exec sp_instmsg 19541, "Examples:"

/*
**Messages for "sp_spaceusage_showhelp_display"	19542
*/

exec sp_instmsg 19542, "%1!Display %2!information in '%3!' for"
exec sp_instmsg 19543, "%1!Display %2!information in '%3!' for any index starting with '%4!' on"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19544, "%1!Display summary information in '%2!' for table '%3!' owned by you"
exec sp_instmsg 19545, "%1!Display summary information in '%2!' for all index on table '%3!' owned by you"

/*
**Messages for "sp_spaceusage_showhelp"	19546
*/

exec sp_instmsg 19546, "%1!any table starting with '%2!' owned by %3!"
exec sp_instmsg 19547, "%1!Run '%2!' on each."
exec sp_instmsg 19548, "%1!where %2!"
exec sp_instmsg 19549, "%1!where %2!%3!ordered by %4! descending"
exec sp_instmsg 19550, "%1!any table starting with '%2!' owned by anyone"

/*
**Messages for "sp_spaceusage_showhelp_report"	19551
*/

exec sp_instmsg 19551, "%1!Report %2!information in '%3!' for"
exec sp_instmsg 19552, "%1!Report %2!information in '%3!' for any index starting with '%4!' on"
exec sp_instmsg 19553, "%1!from archive table '%2!' in current database"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19554, "%1!from archive table '%2!' in '%3!' database"
exec sp_instmsg 19555, "%1!and dated between '%2!' and %3!"
exec sp_instmsg 19556, "%1!and dated before %2!"
exec sp_instmsg 19557, "%1!Report summary information in '%2!' for table '%3!' owned by you"
exec sp_instmsg 19558, "%1!Report summary information in '%2!' for all index on table '%3!' owned by you"

/*
**Messages for "sp_spaceusage_showhelp_archive"	19559
*/

exec sp_instmsg 19559, "%1!Archive %2!information in '%3!' for"
exec sp_instmsg 19560, "%1!Archive %2!information in '%3!' for any index starting with '%4!' on"
exec sp_instmsg 19561, "%1!into table '%2!' in current database"
exec sp_instmsg 19562, "%1!into table '%2!' in '%3!' database"

/*
**Messages for "sp_spaceusage_showhelp"	19563
*/

exec sp_instmsg 19563, "%1!Print usage help on the display action"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19564, "%1!Print usage help on the report action for the index entity"
exec sp_instmsg 19565, "The USING clause can be used with the action keyword (except 'help') as follows:"
exec sp_instmsg 19566, "%1!for 'display' and 'display summary' action"
exec sp_instmsg 19567, "%1!for 'archive', 'report' and 'report summary' action"

/*
**Messages for "sp_displaylogin"	19568
*/

exec sp_instmsg 19568, "No login with specified Server User ID exists."

/*
**Messages for "sp_modifystats"	19569
*/

exec sp_instmsg 19569, "UPDATE STATISTICS permission denied on object '%1!'."

/*
**Messages for "sp_configure"	19570
*/

exec sp_instmsg 19570, "Cannot drop the instance-specific configuration for configuration parameter '%1!' on the current instance since the configuration setting does not exist."

/*
**Messages for "sp_extendsegment"	19571
*/

exec sp_instmsg 19571, "You cannot extend a segment with a virtually hashed table on device %1!, because this device has other segments."

/*
**Messages for "sp_addsegment"	19572
*/

exec sp_instmsg 19572, "A segment with a virtually hashed table exists on device %1!."

/*
**Messages for "sp_chgattribute"	19573
*/

exec sp_instmsg 19573, "sp_chgattribute is not allowed for %1!, as it is a virtually hashed table."

/*
**Messages for "sp_configure"	19574
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19574, "An instance name needs to be provided."

/*
**Messages for "sp_changedbowner"	19575
*/

exec sp_instmsg 19575, "Warning: The stored procedure '%1!' may not execute; check database owner's threshold authorization."

/*
**Messages for "sp_spaceusage_tranlog"	19576
*/

exec sp_instmsg 19576, "No match found for transaction log %1! for database '%2!'."

/*
**Messages for "sp_tempdb"	19580
*/

exec sp_instmsg 19580, "Either the database '%1!' does not exist or is not a temporary database."
exec sp_instmsg 19581, "The %1! '%2!' is already bound to a group. To bind it to a database, first remove existing group binding to it."
exec sp_instmsg 19582, "The %1! '%2!' already has one or more database bindings. To bind it to a group, first remove existing database bindings to it."
exec sp_instmsg 19583, "sp_tempdb 'unbindall_gr', <groupname>"

/*
**Messages for "sp_chgattribute"	19585
*/

exec sp_instmsg 19585, "virtually hashed table"

/*
**Messages for "sp_help"	19586
*/

exec sp_instmsg 19586, "Object is Virtually Hashed."

/*
**Messages for "sp_droplogin"	19587
*/

exec sp_instmsg 19587, "User exists or is an alias or is a database owner in %1! database(s)."

/*
**Messages for "sp_tempdb"	19588
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19588, "sp_tempdb 'unbind', <objtype>, <objname>[, <scope>[, <instancename>]]"

/*
**Messages for "sp_spaceusage_showhelp"	19589
*/

exec sp_instmsg 19589, "Display the space usage information for an entity in the current database."
exec sp_instmsg 19590, "Report from an archive table the space usage information for an entity in the current database."
exec sp_instmsg 19591, "Archive into an archive table the space usage information for an entity in the current database."
exec sp_instmsg 19592, "The USING clause may be used to specify the unit, the archive database name, and the prefix string for the archive table."
exec sp_instmsg 19593, "By default, unit is assumed 'KB', current database is the archive database and no prefix string is assumed."

/*
**Messages for "sp_tempdb"	19594
*/

exec sp_instmsg 19594, "Unable to determine owner instance of the database '%1!'. An internal inconsistency is encountered in the row for this database in master..sysdatabases. Please contact Sybase Technical Support."
exec sp_instmsg 19595, "Instance '%1!' does not exist."

/*
**Messages for "sp_fixindex"	19596
*/

exec sp_instmsg 19596, "Database '%1!' can not be put into single user mode as it is a temporary database. Set %2! to '%3!' for rebuilding the index."
exec sp_instmsg 19597, "Database '%1!' is a user database. %2! is only used for temporary database."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19598, "Index name '%2!' (ID = %3!) is not the name of an index on '%1!'. Use a valid index name or index id."
exec sp_instmsg 19599, "You must specify either index name or index id but not both."
exec sp_instmsg 19600, "%1! cannot be used to rebuild a text/image column."
exec sp_instmsg 19601, "In procedure '%1!', %2! command failed to rebuild the index on table '%3!'."
exec sp_instmsg 19602, "sp_fixindex database, systemcatalog [, ind_id | null] [,index_name | null] [, true | false]."

/*
**Messages for "sp_encryption"	19603
*/

exec sp_instmsg 19603, "There are no encryption keys (key copies) like '%1!' in '%2!'."
exec sp_instmsg 19604, "There are no encrypted columns like '%1!'."
exec sp_instmsg 19605, "There are no columns encrypted with key like '%1!' in the current database."

/*
**Messages for "sp_locklogin"	19606
*/

exec sp_instmsg 19606, "To lock inactive accounts, you must run 'sp_passwordpolicy 'set','enable last login updates',1'."
exec sp_instmsg 19607, "You cannot specify both 'inactive_days' and 'unlock' at the same time."

/*
**Messages for "sp_deviceattr"	19608
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19608, "No such parameter: '%1!"

/*
**Messages for "sp_helprotect"	19610
*/

exec sp_instmsg 19610, "%1! is an invalid permission name."

/*
**Messages for "sp_showplan"	19611
*/

exec sp_instmsg 19611, "The statement id value cannot be NULL or negative."
exec sp_instmsg 19612, "Could not find a plan for the statement id '%1!'."

/*
**Messages for "sp_options"	19613
*/

exec sp_instmsg 19613, "The session id %1! does not exist."
exec sp_instmsg 19614, "The combination of input parameters %1! is invalid. Check user documentation and reenter command."
exec sp_instmsg 19615, "No option or category matching '%1!' is found. Valid categories are:"

/*
**Messages for "sp_encryption"	19616
*/

exec sp_instmsg 19616, "There are no encryption keys (key copies) for user name like '%1!'."

/*
**Messages for "sp_query_tuning"	19617
*/

exec sp_instmsg 19617, "Syntax error. Extra arguments passed to '%1!' command. Run: sp_query_tuning 'help', '%2!' for usage information."
exec sp_instmsg 19618, "Unsupported command '%1!'. Check command and retry sp_query_tuning."

/*
**Messages for "sp_help_query_tuning"	19619
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19619, "Usage: sp_query_tuning [ 'command' [, '@arg1' [, '@arg2' [, '@arg3' ] ] ] ]"
exec sp_instmsg 19620, "flush - flush all query_tuning metrics from memory to system tables"
exec sp_instmsg 19621, "drop - drop a query_tuning object or a query_tuning ID or a group of query_tuning objects"
exec sp_instmsg 19622, "show - display the query_tuning status in each query_tuning group"
exec sp_instmsg 19623, "Usage: sp_query_tuning 'help' [, 'command' ]"
exec sp_instmsg 19624, "Usage: sp_query_tuning flush"
exec sp_instmsg 19625, "Usage: sp_query_tuning 'drop', '@gid' [, '@id' [, '@lrnid' ] ]"

/*
**Messages for "sp_help_learning"	19626
*/

exec sp_instmsg 19626, "Usage: sp_learning show, ase125_better_plan|ase15_better_plan|learning_query|aborted_learning_plan"

/*
**Messages for "sp_drop_query_tuning"	19627
*/

exec sp_instmsg 19627, "No query_tuning object with id = '%1!' exists in this database."
exec sp_instmsg 19628, "No query_tuning group with group id = '%1!' exists in this database."

/*
**Messages for "sp_encryption"	19630
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19630, "There are no encryption keys (key copies) encrypted with the system encryption password in current database."
exec sp_instmsg 19632, "You are not authorized to check keys (key copies) for user name like '%1!'."

/*
**Messages for "sp_passwordpolicy"	19633
*/

exec sp_instmsg 19633, "Network password encryption keypair will be regenerated at %1!."

/*
**Messages for "sp_monitor"	19634
*/

exec sp_instmsg 19634, "Monitoring is currently active for the following types:"

/*
**Messages for "sp_passwordpolicy"	19635
*/

exec sp_instmsg 19635, "This option determines if the last login date should be recorded in syslogins."
exec sp_instmsg 19636, "This option determines if login and role passwords can be downgraded to before Adaptive Server 15.0.2 format."

/*
**Messages for "sp_monitor_deadlock"	19637
*/

exec sp_instmsg 19637, "Frequency of deadlocks, by '%1!' from '%2!.dbo.%3!':"

/*
**Messages for "sp_monitor_list"	19638
*/

exec sp_instmsg 19638, "Monitoring types that are enabled but require some additional configuration options to be turned ON:"

/*
**Messages for "sp_showtext"	19639
*/

exec sp_instmsg 19639, "%1!Parameters '%2!' and '%3!' are mutually exclusive. Ignore '%4!'."

/*
**Messages for "sp_deviceattr"	19640
*/

exec sp_instmsg 19640, "Warning: '%1!', is a file system device. A system failure may cause data loss if the dsync and directio options are both set to false."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19641, "Warning: '%1!', is a file system device. A system failure may cause data loss if the dsync option is set to false."
exec sp_instmsg 19642, "Warning: Sybase recommends not to use '%1!' as a database device, because it is a block device and may cause data loss in case of system failure."

/*
**Messages for "sp_locklogin"	19643
*/

exec sp_instmsg 19643, "No account(s) locked."

/*
**Messages for "sp_displaylogin"	19644
*/

exec sp_instmsg 19644, "Login Password Encryption: %1!"
exec sp_instmsg 19645, "Password column corrupted"

/*
**Messages for "sp_encryption"	19646
*/

exec sp_instmsg 19646, "The execution of the stored procedure '%1!' in database '%2!' was aborted because the system encryption password already exists for this database."
exec sp_instmsg 19647, "There are no encryption keys (key copies) encrypted with the system encryption password for user '%1!' in the current database."
exec sp_instmsg 19648, "There are no encryption key copies like '%1!' assigned to '%2!' in '%3!'."

/*
**Messages for "sp_tab_suspectptn"	19649
*/

exec sp_instmsg 19649, "Tables with suspect partitioning in database %1!:"
exec sp_instmsg 19650, "There are no tables with suspect partitioning in database %1!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19651, "Suspect partitioning on table %1!:"
exec sp_instmsg 19652, "There is no suspect partitioning on table %1!."

/*
**Messages for "sp_stop_rep_agent"	19653
*/

exec sp_instmsg 19653, "Failed to stop the Replication Agent thread for database '%1!'."

/*
**Messages for "sp_configure"	19654
*/

exec sp_instmsg 19654, "Warning: In Shared Disk Cluster, all instances share the same configuration file. Please run sp_configure to read the configuration file for all other instances to keep the configuration consistent."

/*
**Messages for "sp_cacheconfig"	19656
*/

exec sp_instmsg 19656, "Deleting instance-specific configuration of 'default data cache' is not dynamic; restart instance '%1!' to effect the changes."

/*
**Messages for "sp_encryption"	19657
*/

exec sp_instmsg 19657, "There are no columns encrypted with key like '%1!' in all available databases."

/*
**Messages for "sp_passwordpolicy"	19658
*/

exec sp_instmsg 19658, "You cannot use CLEAR to unset the 'allow password downgrade' option."

/*
**Messages for "sp_addexeclass"	19659
*/

exec sp_instmsg 19659, "Class '%1!' is bound to instance '%2!'."

/*
**Messages for "sp_dropserver"	19660
*/

exec sp_instmsg 19660, "Cannot drop server '%1!' because it stores information of existing cluster instance '%2!'."

/*
**Messages for "sp_serveroption"	19661
*/

exec sp_instmsg 19661, "Cannot set server option; server '%1!' is not a cluster instance."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19662, "Cannot set server option; server name '%1!' does not match with its netname '%2!'."
exec sp_instmsg 19663, "Cannot unset server option; server '%1!' is a cluster instance."

/*
**Messages for "sp_aux_encr_verify_downgrade"	19664
*/

exec sp_instmsg 19664, "Alter key to drop key copy"
exec sp_instmsg 19665, "Alter key to encrypt by system encryption password"
exec sp_instmsg 19667, "Revoke privileges from role"
exec sp_instmsg 19668, "Revoke keycustodian_role from user"
exec sp_instmsg 19669, "Reset system encryption password with length <= 64 bytes"
exec sp_instmsg 19670, "Alter table to drop decrypt default"
exec sp_instmsg 19671, "Turn off the configuration option parameter 'restricted decrypt permission"
exec sp_instmsg 19672, "Alter table to decrypt column"

/*
**Messages for "sp_encryption"	19674
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19674, "The following encrypted column items must be addressed before performing downgrade."
exec sp_instmsg 19675, "The following issues need to be resolved in the database before downgrade is performed."
exec sp_instmsg 19676, "Checking databases for downgrade readiness."
exec sp_instmsg 19677, "There are no errors which involve encrypted columns."

/*
**Messages for "sp_passwordpolicy"	19678
*/

exec sp_instmsg 19678, "Password downgrade is allowed."
exec sp_instmsg 19679, "New master database."
exec sp_instmsg 19680, "Last Password downgrade was allowed on"

/*
**Messages for "sp_displaylogin"	19681
*/

exec sp_instmsg 19681, "Last login date: %1!"
exec sp_instmsg 19682, "Account locked by ASE by manually executing sp_locklogin"
exec sp_instmsg 19683, "Account locked by ASE since account was inactive"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19684, "Account locked by ASE due to failed login attempts reaching max failed logins"
exec sp_instmsg 19685, "Account locked by ASE since login has not transitioned to SHA-256, after password downgrade"

/*
**Messages for "sp_bindcache"	19686
*/

exec sp_instmsg 19686, "Warning! Binding a local temporary database to a local named cache that doesn't exist on the instance that owns the temporary database."

/*
**Messages for "sp_aux_encr_verify_downgrade"	19687
*/

exec sp_instmsg 19687, "Alter key to drop key recovery"

/*
**Messages for "sp_clusterlogical_show"	19688
*/

exec sp_instmsg 19688, "Logical cluster '%1!' has no defined instances."
exec sp_instmsg 19689, "Logical cluster '%1!' has no defined routes."
exec sp_instmsg 19690, "Logical cluster '%1!' has no associated actions."
exec sp_instmsg 19691, "Logical cluster '%1!' is the system logical cluster."
exec sp_instmsg 19692, "Logical cluster '%1!' is the open logical cluster."

/*
**Messages for "sp_clusterlogical"	19693
*/

exec sp_instmsg 19693, "Logical cluster '%1!' does not exist."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19694, "%1!' is not a valid route type. Valid types are 'login', 'application', and 'alias'."

/*
**Messages for "sp_clusterlogical_show"	19695
*/

exec sp_instmsg 19695, "%1!' is not a valid option. Valid options are NULL, 'action', and 'route'."
exec sp_instmsg 19696, "'%1!' is not a valid action state. Valid states are 'active', 'cancelled' and 'complete'."

/*
**Messages for "sp_clusterlogical"	19697
*/

exec sp_instmsg 19697, "You must specify a logical cluster name (@lcname)."
exec sp_instmsg 19698, "You cannot run the '%1! %2!' command against the system logical cluster."
exec sp_instmsg 19699, "Aborting drop of logical cluster '%1!' because '%2!' route '%3!' could not be dropped."
exec sp_instmsg 19700, "Internal Error: Failed to drop logical cluster '%1!'."
exec sp_instmsg 19701, "Dropped logical cluster '%1!'."
exec sp_instmsg 19702, "'%1!' is not a valid option to the '%2!' command."

/*
**Messages for "sp_addengine"	19703
*/

exec sp_instmsg 19703, "Instance id '%1!' is not valid under instance system view."

/*
**Messages for "sp_clusterlogical"	19704
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19704, "The rename logical cluster command requires a new name."
exec sp_instmsg 19705, "You cannot rename logical cluster '%1!' to '%2!' because a logical cluster with that name already exists."
exec sp_instmsg 19706, "Internal Error: Failed to rename logical cluster '%1!'."
exec sp_instmsg 19707, "Renamed logical cluster '%1!' to '%2!'"
exec sp_instmsg 19708, "Onlined logical cluster '%1!' on %2! instances."
exec sp_instmsg 19709, "Encountered an error attempting to %1! logical cluster '%2!'."
exec sp_instmsg 19710, "Action '%1!' has been issued for the '%2! %3!' command."
exec sp_instmsg 19711, "The '%1!' command requires a sub command of either 'instance' or 'cluster'."
exec sp_instmsg 19712, "The 'action' command requires an action handle to be specified (@opt2)."
exec sp_instmsg 19713, "The 'action' command requires a subcommand of either 'cancel', 'modify_wait', or 'release'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19714, "Action with handle '%1!' against logical cluster '%2!' has been cancelled."
exec sp_instmsg 19715, "Action with handle '%1!' against logical cluster '%2!' has been released."
exec sp_instmsg 19716, "The action command encountered an internal error. Please consult the Adaptive Server error log for more information."
exec sp_instmsg 19717, "Modified the wait option for action with handle '%1!' against logical cluster '%2!'."
exec sp_instmsg 19718, "Cannot create logical cluster '%1!' because a logical cluster with that name already exists."
exec sp_instmsg 19719, "Internal Error: Failed to create logical cluster '%1!'."
exec sp_instmsg 19720, "Created logical cluster '%1!' with id '%2!'."
exec sp_instmsg 19721, "'%1!' is not a recognized logical cluster command."
exec sp_instmsg 19722, "The '%1! instance' command requires an instance list."

/*
**Messages for "sp_clusterlogical_show"	19723
*/

exec sp_instmsg 19723, "Remember to issue the `sp_cluster logical, action, <logical cluster name>, release, <handle>' command for any cancelled or completed actions."

/*
**Messages for "sp_clusterlogical_instance"	19724
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19724, "You cannot modify the instance or failover settings for the system logical cluster."
exec sp_instmsg 19725, "'%1!' is not a valid instance command. Valid commands are 'add' and 'drop'."
exec sp_instmsg 19726, "'%1!' is not a valid instance type. Valid types are 'instance' and 'failover'."
exec sp_instmsg 19727, "'%1!' is not a legal failover group. Legal failover groups are between 1 and 31."
exec sp_instmsg 19728, "The failover group parameter may only be specified for the 'add failover' command."
exec sp_instmsg 19729, "The generated failover group id of '%1!' is not legal. Please specify a failover group id between 1 and 31."
exec sp_instmsg 19730, "Instance '%1!' is already a %2! instance for logical cluster '%3!'."
exec sp_instmsg 19731, "'%1!' is not a %2! instance for logical cluster '%3!'."
exec sp_instmsg 19732, "Internal error occured for %1! '%2!' instance '%3!' with logical cluster '%4!'."
exec sp_instmsg 19733, "Added base instance '%1!' to logical cluster '%2!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19734, "Added failover instance '%1!' to group %2! for logical cluster '%3!'."
exec sp_instmsg 19735, "Dropped '%1!' instance '%2!' from logical cluster '%3!'."
exec sp_instmsg 19736, "You cannot drop instance '%1!' from logical cluster '%2!' because the logical cluster is currently running on that instance."

/*
**Messages for "sp_clusterlogical"	19737
*/

exec sp_instmsg 19737, "You cannot drop logical cluster '%1!' because it is currently running."

/*
**Messages for "sp_clusterlogical_route"	19738
*/

exec sp_instmsg 19738, "%1!' is not a valid route command. Valid commands are 'add', 'alter', and 'drop'."
exec sp_instmsg 19739, "'%1!' is not a valid route type."
exec sp_instmsg 19740, "Route of type '%1!' with key '%2!' is already bound to logical cluster '%3!'"
exec sp_instmsg 19741, "Route of type '%1!' with key '%2!' does not exist."
exec sp_instmsg 19742, "Route of type '%1!' with key '%2!' is bound to logical cluster '%3!', not logical cluster '%4!'"
exec sp_instmsg 19743, "Internal error occured for %1! '%2!' route '%3!' with logical cluster '%4!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19744, "Added '%1!' route '%2!' to logical cluster '%3!'."
exec sp_instmsg 19745, "Dropped '%1!' route '%2!' from logical cluster '%3!'."

/*
**Messages for "sp_clusterlogical_set"	19746
*/

exec sp_instmsg 19746, "The open logical cluster accepts connections without defined routes."
exec sp_instmsg 19747, "The failover mode determines when and how failover instances are activated."
exec sp_instmsg 19748, "The system view determines how connections in a logical cluster see the system."
exec sp_instmsg 19749, "The startup mode determines if a logical cluster is brought online during instance boot."
exec sp_instmsg 19750, "The down routing mode determines how connections that cannot be routed to their logical cluster are handled."
exec sp_instmsg 19751, "Sets the profile used by the logical cluster for load scoring and distribution."
exec sp_instmsg 19752, "The fail_to_any option determines if only defined failover instances can be used."
exec sp_instmsg 19753, "'instance' failover mode immediately replaces each failed instance with a failover instance."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19754, "'group' failover mode brings a failover group online only when all active instances have failed."
exec sp_instmsg 19755, "'instance' system_view limits procedures such as sp_who to the current instance."
exec sp_instmsg 19756, "'cluster' system_view allows procedures such as sp_who to reflect the entire cluster."
exec sp_instmsg 19757, "'automatic' startup mode onlines a logical cluster as soon as its base instances come online."
exec sp_instmsg 19758, "manual' startup mode requires the administrator to manually online a logical cluster."
exec sp_instmsg 19759, "'disconnect' down routing mode will disconnect a connection when it cannot be routed to its logical cluster."
exec sp_instmsg 19760, "'open' down routing mode will route a connection to the open logical cluster when it cannot be routed to its logical cluster."
exec sp_instmsg 19761, "'system' down routing mode will route a connection to the system logical cluster when it cannot be routed to its logical cluster."
exec sp_instmsg 19762, "When fail_to_any is on, the workload manager can use any instance as a failover for a logical cluster."
exec sp_instmsg 19763, "When fail_to_any is off, the workload manager may only use defined failover instances for a logical cluster."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19764, "'%1!' is not a valid logical cluster set option."
exec sp_instmsg 19765, "Load profile '%1!' does not exist."
exec sp_instmsg 19766, "'%1!' is not a legal value for the logical cluster '%2!' setting."
exec sp_instmsg 19767, "Set option '%1!' for logical cluster '%2!' is already set to '%3!'."
exec sp_instmsg 19768, "Set '%1!' attribute of logical cluster '%2!' to '%3!'."
exec sp_instmsg 19769, "Internal Error: Failed to set '%1!' attribute of logical cluster '%2!' to '%3!'."
exec sp_instmsg 19770, "Internal Error: Failed to set the open logical cluster."
exec sp_instmsg 19771, "Logical cluster '%1!' is now the open logical cluster."

/*
**Messages for "sp_clusterlogical_help"	19772
*/

exec sp_instmsg 19772, "'login' routes are resolved based on the login name in the TDS login record."
exec sp_instmsg 19773, "'application' routes are resolved based on the application name in the TDS login record."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19774, "'alias' routes are resolved based on the server name in the TDS login record."

/*
**Messages for "sp_clusterlogical_set"	19775
*/

exec sp_instmsg 19775, "You cannot set the '%1!' attribute of the system logical cluster."

/*
**Messages for "sp_bindcache"	19776
*/

exec sp_instmsg 19776, "Cache binding changes for local system temporary databases are not dynamic. The owner instance must be rebooted for the change to take effect."
exec sp_instmsg 19777, "Cache binding change for local tempdb '%1!' failed due to owning instance '%2!' status change. Please try again after the owning instance change completes."

/*
**Messages for "sp_unbindcache_all"	19778
*/

exec sp_instmsg 19778, "You cannot use sp_unbindcache_all when system or remote local temporary databases are bound to this cache. Instead use sp_unbindcache to unbind each of these databases first."

/*
**Messages for "sp_downgrade"	19779
*/

exec sp_instmsg 19779, "ERROR: Cannot downgrade to '%1!' server, which does not support server's current default sortorder '%2!'."

/*
**Messages for "sp_encryption"	19780
*/

exec sp_instmsg 19780, "You must be the Database Owner (DBO), or possess either the System Security Officer (SSO) or Key Custodian (KC) role to execute this command/procedure."
exec sp_instmsg 19781, "The system encryption password has not been set for the current database."
exec sp_instmsg 19782, "The system encryption password has not been set for all available databases."

/*
**Messages for "sp_msgadmin"	19783
*/

exec sp_instmsg 19783, "Usage: sp_msgadmin 'show', 'qmgr', provider_name, [options_clause]"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19784, "Usage: sp_msgadmin 'show', 'queues', provider_name, [options_clause]"
exec sp_instmsg 19785, "Usage: sp_msgadmin 'show', 'channels', provider_name, [options_clause]"

/*
**Messages for "sp_clusterprofile"	19786
*/

exec sp_instmsg 19786, "'%1!' is not a valid profile command."
exec sp_instmsg 19787, "You must supply a profile name for command '%1!"
exec sp_instmsg 19788, "Load profile '%1!' does not exist. The '%2!' command requires an existing profile."
exec sp_instmsg 19789, "You cannot create load profile '%1!' because a profile with that name already exists."
exec sp_instmsg 19790, "Notification for creation of load profile '%1!' failed."
exec sp_instmsg 19791, "Insert to sysattribute for creation of load profile '%1!' failed."
exec sp_instmsg 19792, "Created load profile '%1!' with id '%2!'."
exec sp_instmsg 19793, "Cannot drop profile '%1!' because it is a system profile."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19794, "Cannot drop profile '%1!' because it is being used by one or more logical clusters."
exec sp_instmsg 19795, "Notification for drop of load profile '%1!' failed."
exec sp_instmsg 19796, "Deletion from sysattribute for drop of load profile '%1!' failed."
exec sp_instmsg 19797, "Dropped load profile '%1!' with id '%2!'."
exec sp_instmsg 19798, "'%1!' is not a valid category for the set command."
exec sp_instmsg 19800, "'%1!' is not a valid element for the 'set %2!' command."
exec sp_instmsg 19801, "The value parameter must be between %1! and %2! for the 'set %3! %4!' command."
exec sp_instmsg 19802, "Notification for set %1! %2! of load profile %3! to %4! failed."
exec sp_instmsg 19803, "Update to sysattribute for set %1! %2! of load profile %3! to %4! failed."
exec sp_instmsg 19804, "Set %1! %2! of load profile %3! to %4!."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19805, "An unexpected syntax error has occured."

/*
**Messages for "sp_clusterprofile_show"	19806
*/

exec sp_instmsg 19806, "'%1!' is not a valid profile command. Valid options are NULL, 'profile', 'cluster', and 'instance'."
exec sp_instmsg 19807, "Profile '%1!' is not loaded by any instances."
exec sp_instmsg 19808, "Profiles are not loaded by any instances."
exec sp_instmsg 19809, "Profile '%1!' is not loaded by any logical clusters."
exec sp_instmsg 19810, "Profiles are not loaded by any logical clusters."

/*
**Messages for "sp_modifylogin"	19812
*/

exec sp_instmsg 19812, "There is no login-specific '%1!' attribute set for this user."
exec sp_instmsg 19813, "The login-specific '%1!' attribute has been removed."

/*
**Messages for "sp_cluster_show"	19814
*/

exec sp_instmsg 19814, "You are in system logical cluster '%1!' on instance '%2!'."
exec sp_instmsg 19815, "You are in logical cluster '%1!' on instance '%2!'."

/*
**Messages for "sp_configure"	19816
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19816, "You cannot set configuration values from inside a local temporary database."

/*
**Messages for "sp_cacheconfig"	19817
*/

exec sp_instmsg 19817, "Cannot create another configuration for the cache '%1!' due to existing cache bindings and an instance specific configuration. Use 'sp_unbindcache_all' to remove cache bindings for cache '%2!' to create another configuration."

/*
**Messages for "sp_dbcc_faultreport"	19818
*/

exec sp_instmsg 19818, "Local temporary database '%1!' is skipped for this operation. The database is accessible from the owner instance '%2!' only."

/*
**Messages for "sp_rename"	19819
*/

exec sp_instmsg 19819, "Warning: Changing an object or column name could break existing stored procedures, cached statements or other compiled objects."

/*
**Messages for "sp_forceonline_db"	19820
*/

exec sp_instmsg 19820, "The database '%1!' is only accessible from the owner instance '%2!'. Please execute the procedure on that instance."

/*
**Messages for "sp_clusterlogical"	19821
*/

exec sp_instmsg 19821, "Could not bring any instances online for logical cluster '%1!'. This may be because the target instances are not physically online."

/*
**Messages for "sp_addlogin"	19822
*/

exec sp_instmsg 19822, "A local temporary database is not permitted as the default database for a login."

/*
**Messages for "sp_dbcc_run_updateconfig"	19823
*/

exec sp_instmsg 19823, "The cache %1! cannot be used because it is an instance only cache."

/*
**Messages for "sp_msgadmin"	19824
*/

exec sp_instmsg 19824, "Usage: sp_msgadmin 'config', 'ibmmq_keystore', key_repository"

/*
**Messages for "sp_clusterprofile"	19827
*/

exec sp_instmsg 19827, "Cannot create a user load profile that begins with sybase_profile."

/*
**Messages for "sp_bindcache"	19828
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19828, "Cache binding failed for database '%1!'."

/*
**Messages for "sp_encryption"	19829
*/

exec sp_instmsg 19829, "Execute this procedure on ASE instance '%1!' to see any columns encrypted with key '%2!' on database '%3!'."

/*
**Messages for "sp_refit_admin"	19830
*/

exec sp_instmsg 19830, "You need to run DISK REFIT on the following instances to refit their private devices."
exec sp_instmsg 19831, "No device found for which refit is pending."
exec sp_instmsg 19832, "WARNING: You must run DISK REFIT before resuming normal operation."
exec sp_instmsg 19833, "Running DISK REFIT now will refit all the devices."
exec sp_instmsg 19834, "Running DISK REFIT now on instance '%1!' will refit all its private devices."
exec sp_instmsg 19835, "Invalid argument '%1!'. Use '%2!' for help/usage information."
exec sp_instmsg 19836, "Either device '%1!' does not exist, or it is not a database device."
exec sp_instmsg 19837, "Display help/usage information:"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19838, "Display status of the DISK REFIT process:"
exec sp_instmsg 19839, "Reset the DISK REFIT process:"
exec sp_instmsg 19840, "Skip the DISK REFIT proces:"
exec sp_instmsg 19841, "Remove a device from the DISK REFIT process:"
exec sp_instmsg 19842, "'%1!' encountered an error and could not succeed."
exec sp_instmsg 19843, "'%1!' is not allowed for device '%2!'."

/*
**Messages for "sp_passwordpolicy"	19844
*/

exec sp_instmsg 19844, "There is no password protected role like '%1!'."

/*
**Messages for "sp_errorlog"	19845
*/

exec sp_instmsg 19845, "Change in errorlog path complete. New file: '%1!'."
exec sp_instmsg 19846, "Update the -e argument in the runserver file with the new ASE error log path to reflect the error log change."
exec sp_instmsg 19847, "File '%1!' did not open for writing."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19848, "Command already in use by another user or session."
exec sp_instmsg 19849, "Command is used to dynamically switch to a new ASE error log at location <new_path>."
exec sp_instmsg 19850, "Internal error encountered in opening a new ASE error log. Check current ASE error log for details."
exec sp_instmsg 19851, "Warning: Previous ASE error log file could not be closed."
exec sp_instmsg 19852, "Attempting to change the Job Scheduler Agent log from its current directory to the directory where new ASE error log is residing. Check the JS Agent log and/or new ASE error log for details."
exec sp_instmsg 19853, "The Job Scheduler is not running; therefore, no attempt made to change the location of JS Agent log."
exec sp_instmsg 19854, "If 'jslog true' - ASE will attempt to change JS Agent error log to the same directory where the new ASE error log is residing provided that JS Agent is running. Success or failure of command is reported in the JS Agent log and/or the new ASE error log."
exec sp_instmsg 19855, "If 'jslog false' - ASE will not attempt to change the log location of the Job Scheduler. Note that 'jslog true' is the default option."
exec sp_instmsg 19856, "Error encountered when moving the Job Scheduler Agent log from its current directory to the directory where the new ASE error log is residing. Check the previous JS Agent log and/or new ASE error log for details."

/*
**Messages for "sp_changedbowner"	19857
*/

exec sp_instmsg 19857, "Can't change the owner of the master, model, sybsystemprocs, tempdb or local system temporary databases."

/*
**Messages for "sp_dbcc_run_updateconfig"	19858
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19858, "The workspace '%1!' is already configured as %2!. Use sp_dbcc_configreport to display the current configuration and then execute sp_dbcc_updateconfig to correct the problem."

/*
**Messages for "sp_showtext"	19859
*/

exec sp_instmsg 19859, "Argument '%1!' is not valid for '%2!'."

/*
**Messages for "sp_listener"	19862
*/

exec sp_instmsg 19862, "Invalid input: Server name '%1!' matches the remote instance."

/*
**Messages for "sp_clusterconnection"	19863
*/

exec sp_instmsg 19863, "Migrating connection '%1!' to logical cluster '%2!'."
exec sp_instmsg 19864, "Migrated connection '%1!' to logical cluster '%2!'."
exec sp_instmsg 19865, "You must specify a cluster name and/or instance name."
exec sp_instmsg 19866, "Migrations cancelled."
exec sp_instmsg 19867, "Instance '%1!' is not a defined instance for logical cluster '%2!'."
exec sp_instmsg 19868, "Connection '%1!' is already on instance '%2!' of logical cluster '%3!'."
exec sp_instmsg 19869, "No instances are online for logical cluster '%1!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19870, "Instance '%1!' of logical cluster '%2!' is not online."
exec sp_instmsg 19871, "Encountered an error attempting to migrate connection '%1!'."

/*
**Messages for "sp_configure"	19874
*/

exec sp_instmsg 19874, "Cannot configure '%1!' to cluster-wide since it is an instance-specific-only option."

/*
**Messages for "sp_tempdb"	19875
*/

exec sp_instmsg 19875, "Parameter '%1!' is too long. Maximum length is '%2!'."

/*
**Messages for "sp_update_authmech_value"	19882
*/

exec sp_instmsg 19882, "sp_update_authmech_value should not be executed on this release of Adaptive Server, no changes made."
exec sp_instmsg 19883, "Updated authentication mechanism for %1! row(s) on %2! server."

/*
**Messages for "sp_dboption"	19884
*/

exec sp_instmsg 19884, "You cannot set the '%1!' option to '%2!' for a temporary database."
exec sp_instmsg 19886, "Please execute DUMP DATABASE before executing DUMP TRANSACTION."

/*
**Messages for "sp_setrepdbmode"	19887
*/

exec sp_instmsg 19887, "Usage: sp_setrepdbmode dbname [, 'UDIS' [, 'on' | 'off'] | 'threshold' [,'value']]"
exec sp_instmsg 19888, "The attempt to set the replication mode failed. Please, set the database replication level to 'ALL' or to 'L1' using the stored procedure sp_reptostandby prior to setting the replication mode."

/*
**Messages for "sp_downgrade"	19891
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19891, "ERROR: Unable to downgrade this server from ASE version '%1!' to ASE version '%2!'. Please reconfigure the remote servers that are using SSL to avoid specification of common name and to ensure that the remote server names are less than 32 characters:"

/*
**Messages for "sp_dboption"	19892
*/

exec sp_instmsg 19892, "DUMP TRANSACTION is not allowed when '%1!' is ON. Use DUMP DATABASE or DUMP TRANSACTION ... WITH TRUNCATE_ONLY or WITH NO_LOG instead."

/*
**Messages for "sp_reptostandby"	19893
*/

exec sp_instmsg 19893, "The replication mode for database '%1!' is '%2!'."

/*
**Messages for "sp_setrepdbmode"	19895
*/

exec sp_instmsg 19895, "off"

/*
**Messages for "sp_setreptable"	19896
*/

exec sp_instmsg 19896, "never"

/*
**Messages for "sp_setrepdefmode"	19897
*/

exec sp_instmsg 19897, "on"

/*
**Messages for "sp_slotsyscalls"	19898
*/

exec sp_instmsg 19898, "Syntax Error: missing arguments ( correct syntax: %1! )"
exec sp_instmsg 19899, "Supplied value matches multiple syscall names: '%1!'"
exec sp_instmsg 19900, "record not found: '%1!'"

/*
**Messages for "sp_pci_engine_slot_bind"	19901
*/

exec sp_instmsg 19901, "Syntax Error: slot number value must be greater than 0"

/*
**Messages for "sp_jreconfig"	19902
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19902, "Duplicates are not permitted! The value is already in the table: '%1!'"
exec sp_instmsg 19903, "Internal error: units type is not recognized: '%1!'"
exec sp_instmsg 19904, "list command option is invalid or ambiguous: '%1!'"
exec sp_instmsg 19906, "record not found: '%1!', '%2!'"
exec sp_instmsg 19907, "No records found! There are no records in the database for this argument: '%1!'"
exec sp_instmsg 19908, "Supplied value matches multiple records: '%1!'"
exec sp_instmsg 19909, "Supplied values match multiple records: '%1!', '%2!'"
exec sp_instmsg 19910, "Syntax Error: %1! parameter is missing ( correct syntax: %2!)"
exec sp_instmsg 19911, "Syntax Error: disable by database only, no support for disabling individual jar files"
exec sp_instmsg 19912, "Syntax Error: enable by database only, no support for enabling individual jar files"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19913, "Syntax Error: the supplied value is not numeric: '%1!'"
exec sp_instmsg 19914, "Syntax Error: the supplied command is either invalid or ambiguous: '%1!'"
exec sp_instmsg 19915, "Syntax Error: invalid paren(s) found"
exec sp_instmsg 19916, "Syntax Error: unmatched paren found"
exec sp_instmsg 19917, "Unload command failed - the PCA/JVM is not in the correct state to do an Unload operation - make sure the JVM has not been initialized"
exec sp_instmsg 19918, "Load command failed - the PCA/JVM is not in the correct state to do a Load operation - make sure the JVM has not been initialized"
exec sp_instmsg 19919, "Unload command was successful, the PCA/JVM configuration has been Unloaded"
exec sp_instmsg 19920, "Load command was successful, the PCA/JVM configuration has been Loaded"
exec sp_instmsg 19921, "Delete Failed - Transaction Rolled Back"
exec sp_instmsg 19922, "Insert Failed - Transaction Rolled Back"
go

dump transaction master with truncate_only
go

exec sp_instmsg 19923, "Update Failed - Transaction Rolled Back"
exec sp_instmsg 19924, "Supplied value matches multiple argument names: '%1!'"
exec sp_instmsg 19925, "Supplied value matches multiple directive names: '%1!'"
exec sp_instmsg 19926, "The '%1!' command cannot be used with Directives"
exec sp_instmsg 19927, "The '%1!' command does not support arguments of type: '%2!'"

/*
**Messages for "sp_js_agent"	19929
*/

exec sp_instmsg 19929, "master.dbo.sp_extrapwdchecks exists. Manually create jstask login account before retrying Job Scheduler installation."
exec sp_instmsg 19930, "Correct password complexity validation errors or manually create jstask login account before retrying Job Scheduler installation."

/*
**Messages for "sp_setrepdefmode"	19931
*/

exec sp_instmsg 19931, "threshold"

/*
**Messages for "sp_setrepdbmode"	19932
*/

exec sp_instmsg 19932, "The replication threshold for '%1!' is '%2!'."

/*
**Messages for "sp_setrepdefmode"	19933
*/

exec sp_instmsg 19933, "Failed to change the replication threshold for table '%1!' because of an internal error."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19934, "The replication threshold provided for table '%1!' is '%2!'. This threshold is invalid. Please choose a threshold larger than 0 and smaller than '%3!'."
exec sp_instmsg 19935, "u"
exec sp_instmsg 19936, "d"
exec sp_instmsg 19937, "i"
exec sp_instmsg 19938, "udi"

/*
**Messages for "sp_maplogin"	19940
*/

exec sp_instmsg 19940, "Client authentication mapping overwritten. Previous values were @authentication_mech='%1!', @client_name='%2!' and @login_name='%3!'."

/*
**Messages for "sp_dropuser"	19941
*/

exec sp_instmsg 19941, "You cannot drop the user because the suid value for user '%1!' is not unique in the database."

/*
**Messages for "sp_downgrade"	19943
*/

exec sp_instmsg 19943, "ERROR: Unable to downgrade this server from ASE version '%1!' to ASE version '%2!'. Note: Versions previous to 15.0.3 do not support the CN= syntax in a directory service entry. Please disable SSL on the following listeners:"

/*
**Messages for "sp_clusterlogical"	19944
*/

exec sp_instmsg 19944, "All actions against logical cluster '%1!' have been released."

/*
**Messages for "sp_clusterconnection"	19945
*/

exec sp_instmsg 19945, "Connection '%1!' not found."

/*
**Messages for "sp_clusterlogical"	19946
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19946, "Gathering connections to logical cluster '%1!'."

/*
**Messages for "sp_clusterconnection"	19947
*/

exec sp_instmsg 19947, "No migrations cancelled."

/*
**Messages for "sp_setrepdefmode"	19948
*/

exec sp_instmsg 19948, "The replication threshold for '%1!' has been cleared."
exec sp_instmsg 19949, "There is no replication threshold defined for '%1!'."

/*
**Messages for "sp_setrepdbmode"	19950
*/

exec sp_instmsg 19950, "The replication threshold for '%1!' has been reset to '%2!'."

/*
**Messages for "sp_configure"	19953
*/

exec sp_instmsg 19953, "Cannot change the value of configuration parameter 'config file version' because it is server generated."

/*
**Messages for "sp_downgrade"	19954
*/

exec sp_instmsg 19954, "ERROR: Cannot downgrade to '%1!' server, which does not support the current charset '%2!'."

/*
**Messages for "sp_addserver"	19958
*/

exec sp_instmsg 19958, "Backup Server policy is set to '%1!'."

/*
**Messages for "sp_dumpoptimize"	19959
*/

exec sp_instmsg 19959, "Attempting to execute RPC for Backup Server '%1!'."

/*
**Messages for "sp_configure"	19961
*/

exec sp_instmsg 19961, "WARNING: Compatibility mode will not be used when 'abstract plan dump/load/replace' is on."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19962, "WARNING: Compatibility mode may not be used when statement cache and literal autoparam are enabled."

/*
**Messages for "sp_compatmode"	19963
*/

exec sp_instmsg 19963, "Compatibility mode is not enabled."
exec sp_instmsg 19964, "Compatibility mode is enabled."
exec sp_instmsg 19965, "WARNING: The configuration option 'histogram tuning factor' is configured with value '%1!', which is not the default value in ASE 12.5. This may lead to different accuracy of statistics and different query plans."

/*
**Messages for "sp_configure"	19966
*/

exec sp_instmsg 19966, "WARNING: Enabling compatibility mode will not affect the query plans already stored in the procedure cache."
exec sp_instmsg 19967, "WARNING: The configuration option 'statement cache size' is configured with value '%1!'. Enabling compatibility mode will not affect the query plans already stored in the statement cache."

/*
**Messages for "sp_addserver"	19968
*/

exec sp_instmsg 19968, "Backup Server '%1!' is not configured in sysservers."
exec sp_instmsg 19969, "Multiple Backup Server in Cluster can not be enabled."

/*
**Messages for "sp_volchanged"	19970
*/

exec sp_instmsg 19970, "Attempting to execute RPC for Backup Server '%1!'('%2!')."

/*
**Messages for "sp_addserver"	19971
*/

exec sp_instmsg 19971, "You cannot change the server class of existing server '%1!' from '%2!' to '%3!'."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19972, "Local server must use the cluster name as the server name."

/*
**Messages for "sp_poolconfig"	19973
*/

exec sp_instmsg 19973, "Configuring large I/O pools for in-memory storage cache '%1!' is not allowed."

/*
**Messages for "sp_bindcache"	19974
*/

exec sp_instmsg 19974, "Individual object or database cannot be bound to or unbound from cache, '%1!', which is an in-memory storage cache."

/*
**Messages for "sp_deviceattr"	19975
*/

exec sp_instmsg 19975, "You cannot set attribute %1! for %2! device '%3!'."

/*
**Messages for "sp_cacheconfig"	19976
*/

exec sp_instmsg 19976, "The specified cache replacement policy '%1!' for cache '%2!' is invalid. Replacement policy 'none' is applicable to cache of type 'inmemory_storage' and replacement policy 'strict | relaxed' is applicable to cache of type 'logonly | mixed'."
exec sp_instmsg 19977, "Changing the cache type for cache '%1!' from or to type '%2!' is not allowed."
exec sp_instmsg 19978, "Changing the cache replacement policy between '%1!' and '%2!' is not allowed."

/*
**Messages for "sp_unbindcache"	19979
*/

exec sp_instmsg 19979, "Cannot run '%1!' for in-memory database '%2!'."

/*
**Messages for "sp_querysmobj"	19980
*/

exec sp_instmsg 19980, "You are not authorized to execute this stored procedure. Only the system administrator (sa) or a user with oper_role authorization can execute this stored procedure."

/*
**Messages for "sp_cacheconfig"	19981
*/

exec sp_instmsg 19981, "The cache type for the 'default data cache' cannot be modified."
go

dump transaction master with truncate_only
go

exec sp_instmsg 19982, "The cache type for '%1!' cannot be modified to '%2!' as it is already configured as '%3!' on other instance(s). A cache can be configured to be either 'mixed', or 'logonly', but not both."

/*
**Messages for "sp_helpdb"	19983
*/

exec sp_instmsg 19983, "in-memory"
exec sp_instmsg 19984, "template"

/*
**Messages for "sp_downgrade"	19985
*/

exec sp_instmsg 19985, "ERROR: Cannot downgrade to '%1!' server, which does not support bigdatetime and bigtime datatypes."

/*
**Messages for "sp_depends"	19986
*/

exec sp_instmsg 19986, "The dependencies of the stored procedure cannot be determined until the first successful execution."

/*
**Messages for "sp_dboption"	19987
*/

exec sp_instmsg 19987, "You cannot set the '%1!' option for temporary databases or for databases with durability %2!."

/*
**Messages for "sp_bindcache"	19991
*/

exec sp_instmsg 19991, "You cannot bind an in-memory database, or individual objects in an in-memory database, to cache '%1!', which is a regular named cache."

/*
**Messages for "sp_help"	19992
*/

exec sp_instmsg 19992, "full dml logging"
exec sp_instmsg 19993, "minimal dml logging"
exec sp_instmsg 19994, "incremental transfer on"

/*
**Messages for "sp_dbrecovery_order"	19995
*/

go

dump transaction master with truncate_only
go

exec sp_instmsg 19995, "You must define the recovery order of the database '%1!' before defining the recovery order of any database that uses it as a template database."
exec sp_instmsg 19996, "The recovery order of database '%1!' cannot precede the recovery order '%2!' of its template database '%3!'."
exec sp_instmsg 19997, "You must delete the recovery order of any database that uses this database as template before changing the template database recovery order."
go


drop PROC sp_instmsg
go

dump transaction master with truncate_only
go

set nocount off
go

go
/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! 
**
** Make sure to add the new reserved word in both conditional 
**       compile blocks. 
**
** The UPGRADE conditional block is used to install
** 	  things in previous version of the server that is getting upgraded
**	  Do not add any new specific column info in that block
*/

/*
** Any new reserved word can be added at the end. Trying to keep the reserved
** words in alphabetical order is a maintenance nightmare.
*/
use master
go

delete spt_values
	where type = "W"
go

/*
** All the ASE keywords are inserted here. The ansi_w can have the values
** 0 or > 0. The value 0 indicates that the keyword is an ASE specific 
** keywords and it is not a standard SQL92 keywords. 
** The value 1 indicates that the keywords is an SQL92 keywords. 
** For the future, the values > 1 indicate that the keyword is part of 
** SQL99 and above keywords.
**
**	  
*/


insert spt_values (name, number, type, ansi_w)  values ("add",   1 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("all",   2 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("alter",   3 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("and",   4 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("any",   5 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("arith_overflow",   6 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("as",   7 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("asc",   8 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("at",   9 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("authorization",  10 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("avg",  11 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("begin",  12 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("between",  13 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("break",  14 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("browse",  15 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("bulk",  16 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("by",  17 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("cascade",  18 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("case",  19 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("char_convert",  20 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("check",  21 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("checkpoint",  22 , "W", 0)
go
insert spt_values (name, number, type, ansi_w) values ("close",  23 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("clustered",  24 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("coalesce",  25 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("commit",  26 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("compute",  27 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("confirm",  28 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("connect",  29 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("constraint",  30 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("continue",  31 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("controlrow",  32 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("convert",  33 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("count",  34 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("create",  35 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("current",  36 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("cursor",  37 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("proxy_table",  38 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("database",  39 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("dbcc",  40 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("deallocate",  41 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("declare",  42 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("default",  43 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("delete",  44 , "W", 1)
go
insert spt_values (name, number, type, ansi_w) values ("desc",  45 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("disk",  46 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("distinct",  47 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("drop",  49 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("dummy",  50 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("dump",  51 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("else",  52 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("end",  53 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("endtran",  54 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("errlvl",  55 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("errordata",  56 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("errorexit",  57 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("escape",  58 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("except",  59 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("exclusive",  60 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("exec",  61 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("execute",  62 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("exists",  63 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("exit",  64 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("exp_row_size", 65, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("external",  66 , "W", 1)
go
insert spt_values (name, number, type, ansi_w) values ("fetch",  67 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("fillfactor",  68 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("for",  69 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("foreign",  70 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("from",  71 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("goto",  72 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("grant",  73 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("group",  74 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("having",  75 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("holdlock",  76 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("identity",  77 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("identity_start",  79 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("identity_gap", 104 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("if",  80 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("in",  81 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("index",  82 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("insert",  83 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("install",  84 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("intersect",  85 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("into",  86 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("is",  87 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("isolation",  88 , "W", 1)
go
insert spt_values (name, number, type, ansi_w) values ("jar",  89 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("join",  90 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("key",  91 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("kill",  92 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("level",  93 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("like",  94 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("lineno",  95 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("load",  96 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("lock", 97, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("max",  98 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("max_rows_per_page",  99 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("min",  100 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("mirror",  101 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("mirrorexit",  102 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("national",  103 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("noholdlock",  105 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("nonclustered",  106 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("not",  107 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("null",  108 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("nullif",  109 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("numeric_truncation",  110 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("of",  111 , "W", 1)
go
insert spt_values (name, number, type, ansi_w) values ("off",  112 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("offsets",  113 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("on",  114 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("once", 115 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("online",  116 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("only", 117 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("open", 118 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("option", 119 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("or", 120 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("order", 121 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("over", 122 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("partition", 123 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("perm", 124 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("permanent", 125 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("plan", 126 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("prepare", 128 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("primary", 129 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("print", 130 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("privileges", 131 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("proc", 132 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("procedure", 133 , "W", 1)
go
insert spt_values (name, number, type, ansi_w) values ("processexit", 134 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("public", 135 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("raiserror", 136 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("read", 137 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("readpast", 138, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("readtext", 139 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("reconfigure", 140 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("references", 141 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("remove", 142 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("reorg", 143 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("replace", 144 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("quiesce", 145 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("reservepagegap", 146, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("return", 147 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("revoke", 148 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("role", 149 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("rollback", 150 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("rowcount", 151 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("rows", 152 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("rule", 153 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("save", 154 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("schema", 155 , "W", 1)
go
insert spt_values (name, number, type, ansi_w) values ("select", 156 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("set", 157 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("setuser", 158 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("shared", 159 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("shutdown", 160 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("some", 161 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("statistics", 162 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("stripe", 163 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("sum", 164 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("syb_identity", 165 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("syb_restree", 166 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("syb_terminate", 167 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("table", 168 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("temp", 169 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("temporary", 170 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("textsize", 171 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("to", 172 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("tran", 173 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("transaction", 174 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("trigger", 175 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("truncate", 176 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("tsequal", 177 , "W", 0)
go
insert spt_values (name, number, type, ansi_w) values ("union", 178 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("unique", 179 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("unpartition", 180 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("update", 181 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("use", 182 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("replication", 183 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("user", 184 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("user_option", 185 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("using", 186 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("values", 187 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("varying", 188 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("view", 189 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("waitfor", 190 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("when", 191 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("where", 192 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("while", 193 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("with", 194 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("work", 195 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("writetext", 196 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("modify", 197 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("deterministic", 198 , "W", 0)
go
insert spt_values (name, number, type, ansi_w) values ("inout", 201 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("out", 203 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("output", 204 , "W", 1)
insert spt_values (name, number, type, ansi_w) values ("returns", 205 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("stringsize", 206 , "W", 0)
insert spt_values (name, number, type, ansi_w) values ("xmltest", 207, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("xmlextract", 208, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("xmlparse", 209, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("encrypt", 210, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("decrypt", 211, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("materialized", 212, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("count_big", 213, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("tracefile", 214, "W", 0)
insert spt_values (name, number, type, ansi_w) values ("scroll", 215, "W", 1)
insert spt_values (name, number, type, ansi_w) values ("decrypt_default", 216, "W", 0)

insert spt_values (name, number, type, ansi_w) values ("insensitive", 217, "W", 1)
insert spt_values (name, number, type, ansi_w) values ("semi_sensitive", 218, "W", 0)
/* ansi_w = 3 has been used for SQL 2003. */
insert spt_values (name, number, type, ansi_w) values ("xmltable", 219, "W", 3)

go
go
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*
** This file creates the tables needed for the Resource Governor 
** stored procedures.
**
** It also loads the needed values into those tables.
** The tables are:
**      spt_limit_types
**
** Under no circumstances should changes be made to the tables 
** stored in this routine unless they are to add new limit types to 
** Resource Governor.
** These tables interface with the stored procedures:
**      sp_add_resource_limit
**      sp_drop_resource_limit
**      sp_modify_resource_limit
**
*/

set nocount on
go
use master
go
if exists (select *
	from sysobjects
		where name = "spt_limit_types")
begin
	drop table spt_limit_types
end
go

create table spt_limit_types
	(name		char(30),
	 id		smallint,
	 enforced	tinyint,
	 object_type	smallint,
	 scope		smallint,
	 units		char(60)
	)
go

grant select on spt_limit_types to public
go

insert spt_limit_types values("io_cost", 1, 3, 1, 1, "derived from optimizer's costing formula")
insert spt_limit_types values("elapsed_time", 2, 2, 1, 6, "in seconds")
insert spt_limit_types values("row_count", 3, 2, 1, 1, "# of row returned to client")
insert spt_limit_types values("tempdb_space", 4, 2, 1, 1, "in pages")
go
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addconf')
begin
	drop procedure sp_addconf
end
go
print "Installing sp_addconf"
go

/*
** A_CONFIGURES - Insert new configuration parameters in sysconfigures that 
**		have been added since the GA version of the server.
**		THIS IS NOT TO INSERT NEW CONFIGURATION PARAMETERS IN A NEW
**		MAJOR RELEASE OF THE SERVER. In that case the upgrade program
**		will insert new configuration parameters.
*/
set nocount on
go
use master
go
/*
** SP_ADDCONF
**	Insert configuration in sysconfigures when it does not exist.
**	When the configuration exists, but the status or parent are
**	different, sysconfigures is updated.
**	Parameters should match values in the file 
**	generic/source/utils/cfg_options
**
** Parameters:
**	@config		'config number' from cfg_options
**	@name		'config name' from cfg_options
**	@status		'status' from cfg_options
**	@parent		'parent' from cfg_options
**
*/
create procedure sp_addconf
	@config	smallint,
	@name	varchar(255),
	@status	int,
	@parent	smallint,
	@value2	varchar(255)	= null,
	@value3	int 		= null,
	@value4	int		= null
as
	declare @value	int

	select @value = value 
		from syscurconfigs 
		where config = @config

	if @value is null
	begin
		/* 
		** No row in syscurconfigs, so this is not a valid config
		** for this server version, return.
		*/
		return 1
	end


	if exists (select * 
		from sysconfigures 
		where config = @config 
		and name = @name
		and status = @status
		and parent = @parent)
	begin
		/*
		** Row with same config, name, status and parent already exists,
		** return.
		*/
		return 2
	end

	if exists (select * 
		from sysconfigures 
		where config = @config )
	begin
		/* update existing row */
		update sysconfigures
			set	name = @name,
				comment = @name,
				parent = @parent,
				status = @status
			where 	config = @config

		return 3
	end

	/* The option does not exist, thus insert a new row. */
	insert sysconfigures (
		config, value, comment, status, name, parent,
		value2, value3, value4)
	select	@config, @value, @name, @status, @name, @parent, 
		@value2, @value3, @value4

	return 0
go

/* add param, 'cis idle connection timeout' */
exec sp_addconf 271, 'cis idle connection timeout', 9, 32
go

exec sp_addconf 410, 'number of histogram steps', 9, 31
go

/* Add new param, 'sampling percent' */
exec sp_addconf 411, 'sampling percent', 9, 31
go

/* Add new param, 'performance monitoring option' */
exec sp_addconf 412, 'performance monitoring option', 262153, 42
go

/* Add new param, 'i/o batch size' */
exec sp_addconf 413, 'i/o batch size', 9, 14
go

/* Add new param, 'statement cache size' */
exec sp_addconf 414, 'statement cache size', 73, 14 

/* Add new param, 'max concurrently recovered db' */
exec sp_addconf 415, 'max concurrently recovered db', 9, 3
go

/* Add new param, 'number of checkpoint tasks' */
exec sp_addconf 416, 'number of checkpoint tasks', 9, 3
go

/* Add new param, 'send doneinproc tokens' */
exec sp_addconf 417, 'send doneinproc tokens', 9, 8
go

/* Add new param, 'enable ldap user auth' */
exec sp_addconf 418, 'enable ldap user auth', 262153, 29
go

/* Add new param, 'enable xml' */
exec sp_addconf 419, 'enable xml', 262153, 14
go

/* Add new param, 'enable webservices' */
exec sp_addconf 420, 'enable webservices', 262153, 14
go

/* Add new param, 'enable job scheduler' */
exec sp_addconf 421, 'enable job scheduler', 9, 14

/* Add new param, 'job scheduler tasks' */
exec sp_addconf 422, 'job scheduler tasks', 9, 14

/* Add new param, 'job scheduler interval' */
exec sp_addconf 423, 'job scheduler interval', 9, 14

/* Add new param, 'percent database for history' */
exec sp_addconf 424, 'percent database for history', 9, 14

/* Add new param, 'percent history free' */
exec sp_addconf 425, 'percent history free', 9, 14

/* Add new param, 'percent database for output' */
exec sp_addconf 426, 'percent database for output', 9, 14

/* Add new param, 'percent output free' */
exec sp_addconf 427, 'percent output free', 9, 14

/* Add new param, 'maximum job output' */
exec sp_addconf 428, 'maximum job output', 9, 14
go

/* Add new param, 'enable real time messaging' */
exec sp_addconf 429, 'enable real time messaging', 262153, 14
go

/* Add new param, 'messaging memory' */
exec sp_addconf 430, 'messaging memory', 262217, 12
go

/* Add new param, 'extended cache size' */
exec sp_addconf 431, 'extended cache size', 262217, 4
go

/* Add new param, 'enable pam user auth' */
exec sp_addconf 432, 'enable pam user auth', 262153, 29
go

/* Add new param, 'histogram tuning factor' */
exec sp_addconf 433, 'histogram tuning factor', 9, 14

/* Add new param, 'numbre of dump threads' */
exec sp_addconf 434, 'number of dump threads', 9, 41
go

/* Add new param, 'max native threads per engine' */
exec sp_addconf 440, 'max native threads per engine', 9, 9
go

/* Add new param, 'rtm thread idle wait period' */
exec sp_addconf 441, 'rtm thread idle wait period', 9, 14
go

/* Add new param 'enable encrypted columns' */
exec sp_addconf 442, 'enable encrypted columns', 262217, 29
go

/* Add new param, 'number of startup MQ engines' */
exec sp_addconf 447, 'max online Q engines', 69, 13
go

/* Add new param, 'number of startup MQ engines' */
exec sp_addconf 448, 'number of Q engines at startup', 262149, 13
go

/* Add new param, 'metrics_lio_max' */
exec sp_addconf 450, 'metrics lio max', 9, 31
go

/* Add new param, 'metrics_pio_max' */
exec sp_addconf 451, 'metrics pio max', 9, 31
go

/* Add new param, 'metrics_elap_max' */
exec sp_addconf 452, 'metrics elap max', 9, 31
go

/* Add new param, 'metrics_exec_max' */
exec sp_addconf 453, 'metrics exec max', 9, 31
go

/* Add new param, 'engine memory log size' */
exec sp_addconf 454, 'engine memory log size', 73, 41
go

/* Add new param, 'compression memory size' */
exec sp_addconf 455, 'compression memory size', 73, 12
go

/* Add new param, 'enable logins during recovery' */
exec sp_addconf 456, 'enable logins during recovery', 9, 29
go

exec sp_addconf 459, 'min pages for parallel scan', 9, 31
go

exec sp_addconf 460, 'prod-consumer overlap factor', 9, 31
go

/* Add new param, 'start xp server during boot' */
exec sp_addconf 461, 'start xp server during boot', 5, 35
go

exec sp_addconf 462, 'enable literal autoparam', 9, 31
go

exec sp_addconf 463, 'max query parallel degree', 9, 31
go

exec sp_addconf 464, 'session tempdb log cache size', 65541, 16
go

exec sp_addconf 468, 'cost of a logical io', 9, 31
go

exec sp_addconf 469, 'cost of a physical io', 9, 31
go

exec sp_addconf 470, 'cost of a cpu unit', 9, 31
go

exec sp_addconf 471, 'net password encryption reqd', 9, 29
go

exec sp_addconf 473, 'identity reservation size', 9, 14
go

exec sp_addconf 474, 'enable stmt cache monitoring', 9, 42
go

/* Add new param 'enable sql debugger' */
exec sp_addconf 475, 'enable sql debugger', 5, 14
go

exec sp_addconf 476, 'auto query tuning', 9, 31
go

exec sp_addconf 477, 'enable query tuning mem limit', 9, 31
go

exec sp_addconf 478, 'query tuning plan executions', 9, 31
go

/* Add new param 'restricted decrypt permission' */
exec sp_addconf 480, 'restricted decrypt permission', 262153, 29
go

/* Add new param 'merge_join' */
exec sp_addconf 484, 'enable merge join', 9, 31 
go

exec sp_addconf 485, 'enable query tuning time limit', 9, 31
go

/* Add new param 'max buffers per lava operator' */
exec sp_addconf 487, 'max buffers per lava operator', 9, 31
go

/* Add new param 'max nesting level' */
exec sp_addconf 496, 'max nesting level', 69, 16
go

/* Add new param 'mnc_full_index_filter' */
exec sp_addconf 497, 'mnc_full_index_filter', 9, 31
go

/* Add new param 'capture missing statistics' */
exec sp_addconf 498, 'capture missing statistics', 9, 31
go

/* Add new param 'cluster redundancy level' */
exec sp_addconf 510, 'cluster redundancy level', 524357, 14 
go

/* Add new param 'enable pci' */
exec sp_addconf 499, 'enable pci', 5, 14
go

/* Add new param 'max pci slots' */
exec sp_addconf 500, 'max pci slots', 9, 14
go

/* Add new param 'pci memory size' */
exec sp_addconf 501, 'pci memory size', 73, 14
go

/* Add new param 'enable compatibility mode' */
exec sp_addconf 502, 'enable compatibility mode', 9, 31
go

/* Add new param 'config file version' */
exec sp_addconf 504, 'config file version', 9, 2 
go

/* Add new param 'enable procedure deferred compilation' */
exec sp_addconf 505, 'procedure deferred compilation', 9, 31
go
/* Add new param 'optimizer level' */
exec sp_addconf 507, 'optimizer level', 9, 31
go

/* Add new param 'search engine timeout factor' */
exec sp_addconf 508, 'search engine timeout factor', 9, 31
go

/* Add new param, 'rtm thread idle wait period' */
exec sp_addconf 509, 'number of backup connections', 9, 16
go

/* Add new param 'FIPS login password encryption' */
exec sp_addconf 511, 'FIPS login password encryption', 5, 29
go

/* Add new param 'deferred name resolution' */
exec sp_addconf 512, 'deferred name resolution', 8, 31
go

/* Add new param 'deferred name resolution' */
exec sp_addconf 513, 'max transfer history', 9, 14
go

drop procedure sp_addconf
go

/*
** Delete rows from sysconfigures that are not valid for this server version.
** This could happen when going back to a previous ESD of the server.
** For example if when a new configuration parameter is added in 12004 ESD#2,
** the above sp_addconf will add this new configuration parameter. When going
** back to 12004 ESD#1, the row is still in sysconfigures,  
*/
delete sysconfigures 
	from sysconfigures con
	where not exists 
		(select * 
			from syscurconfigs cur 
			where cur.config = con.config)
go


dump transaction master with truncate_only
go

set nocount off
go
go
set nocount on
go
use master
go
if not exists (select *
	from sysobjects
		where name = "syblicenseslog")
begin
	exec ( " 
		create table syblicenseslog 
		(status smallint, logdate datetime, maxlicenses int)
		lock allpages 
		" )
end
go

set nocount off
go
go
/*
** Confidential property of Sybase, Inc.
** (c) Copyright Sybase, Inc. 1998.
** All rights reserved
*/

/*
**
** Tables created:
**
**      Name                    Default Location
**      ----------------------- ----------------
**      spt_ijdbc_table_types    master
**      spt_ijdbc_mda                 master
**      spt_ijdbc_conversion     master
**      ijdbc_function_escapes   master
**
*/



/*
**  spt_ijdbc_table_types
*/


/** SECTION BEGIN: CLEANUP **/
use master
go

if (exists (select * from sysobjects
                where name = 'spt_ijdbc_table_types'))
    drop table spt_ijdbc_table_types
go
/** SECTION END: CLEANUP **/
 

create table spt_ijdbc_table_types (TABLE_TYPE char(15))
go
    insert into spt_ijdbc_table_types values('TABLE')
    insert into spt_ijdbc_table_types values('SYSTEM TABLE')
    insert into spt_ijdbc_table_types values('VIEW')
go
 
commit
go
 
grant select on spt_ijdbc_table_types to public
go

/*
**  End of spt_ijdbc_table_types
*/


/*
**  spt_ijdbc_mda
*/


/** SECTION BEGIN: CLEANUP **/
use master
go

if exists (select * from sysobjects where name = 'spt_ijdbc_mda')
begin
    drop table spt_ijdbc_mda
end
go
/** SECTION END: CLEANUP **/

/*
** querytype: 1 == RPC, 2 == LANGUAGE, 3 == NOT_SUPPORTED,
**            4 == LITERAL (boolean), 5 == LITERAL (integer),
**            6 == LITERAL (string), 7 == LITERAL (string, not tokenizable)
**
** note: querytypes 4 through 6 were added in version level 4 
**       of the metadata access.
** note: querytype 7 was added in version level 5 of the metadata access
**	 to fix 168844
** note: sp_ijdbc_mda version does NOT refer to the jConnect version!!
*/
create table spt_ijdbc_mda (mdinfo varchar(30), querytype tinyint, 
pre_query varchar(600) null, query varchar(255) null, post_query varchar(255) null , mdaver_start tinyint, mdaver_end tinyint, srvver_start int, srvver_end int)
go

create unique nonclustered index spt_ijdbc_mda_ind 
    on spt_ijdbc_mda (mdinfo, mdaver_end, srvver_end)
go

grant select on spt_ijdbc_mda to public
go

insert spt_ijdbc_mda values ('CLASSFORNAME', 1, 'create table #tmp_class_for_name (xtbinaryoffrow image null)', 'sp_ijdbc_class_for_name(?)','select * from #tmp_class_for_name', 1, 7, 12000, -1)

insert spt_ijdbc_mda values ('JARFORCLASS', 1, 'create table #tmp_jar_for_class (jbinary image null) ', 'sp_ijdbc_jar_for_class(?)', 'select * from #tmp_jar_for_class', 1, 7, 12000, -1)

 insert spt_ijdbc_mda values ('JARBYNAME', 1, ' create table #tmp_jar_by_name (jbinary image null) ', 'sp_ijdbc_jar_by_name(?)', 'select * from #tmp_jar_by_name', 1, 7, 12000, -1)

insert spt_ijdbc_mda values ('CLASSESINJAR', 1,'create table #tmp_classes_in_jar (xtname char(255) null)', 'sp_ijdbc_classes_in_jar(?)','select * from #tmp_classes_in_jar', 1, 7, 12000, -1)

insert spt_ijdbc_mda values ('CANRETURNJARS', 4, null, '0',null, 4, 7, 0, 11950)
insert spt_ijdbc_mda values ('CANRETURNJARS', 2, null, 'select 0',null, 1, 3, 0, 11950)

insert spt_ijdbc_mda values ('CANRETURNJARS', 4, null,'1', null, 4, 7, 12000, -1)

insert spt_ijdbc_mda values ('CANRETURNJARS', 2, null,'select 1', null, 1, 3, 12000, -1)

insert spt_ijdbc_mda values ('FUNCTIONCALL', 1, 'create table #tmp_function_escapes  (escape_name varchar(40) null, map_string varchar(40) null )', 'sp_ijdbc_function_escapes', 'select * from #tmp_function_escapes', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('TYPEINFO', 1, 'create table #tmp_datatype_info(TYPE_NAME varchar(32) null,DATA_TYPE smallint null,PRECISION int null,LITERAL_PREFIX varchar(32) null,LITERAL_SUFFIX varchar(32) null,CREATE_PARAMS varchar(32) null,NULLABLE smallint null,CASE_SENSITIVE smallint null,SEARCHABLE smallint null,UNSIGNED_ATTRIBUTE smallint null,FIXED_PREC_SCALE smallint null,AUTO_INCREMENT smallint null,LOCAL_TYPE_NAME varchar(128) null,MINIMUM_SCALE smallint null,MAXIMUM_SCALE smallint null,SQL_DATA_TYPE smallint null,SQL_DATETIME_SUB smallint null,NUM_PREC_RADIX smallint null,INTERVAL_PRECISION smallint null)', 'sp_ijdbc_datatype_info', 'select * from #tmp_datatype_info', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('TABLES', 1, 'create table #tmp_tables ( TABLE_CAT  varchar(32) null, TABLE_SCHEM varchar(32) null, TABLE_NAME varchar(32) null, TABLE_TYPE varchar(32) null, REMARKS varchar(254) null) ', 'sp_ijdbc_tables(?,?,?,?)', 'select * from #tmp_tables', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('COLUMNS', 1, 'create table #tmp_columns (TABLE_CAT varchar(30) null,TABLE_SCHEM varchar(30) null,TABLE_NAME varchar(30) null,COLUMN_NAME varchar(30) null,DATA_TYPE int null,TYPE_NAME varchar(255) null,COLUMN_SIZE int null,BUFFER_LENGTH int null,DECIMAL_DIGITS int null,NUM_PREC_RADIX smallint null,NULLABLE smallint null,REMARKS varchar(254) null,COLUMN_DEF varchar(30) null,SQL_DATA_TYPE int null,SQL_DATETIME_SUB int null,CHAR_OCTET_LENGTH int null,ORDINAL_POSITION smallint null,IS_NULLABLE varchar(10) null)', 'sp_ijdbc_columns(?,?,?,?)', 'select * from  #tmp_columns', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('IMPORTEDKEYS', 1, 'create table #tmp_fkeys ( PKTABLE_CAT varchar (32) null, PKTABLE_SCHEM varchar (32) null, PKTABLE_NAME varchar(64) null , PKCOLUMN_NAME varchar(32) null , FKTABLE_CAT varchar(32) null, FKTABLE_SCHEM varchar(32) null, FKTABLE_NAME varchar(32) null , FKCOLUMN_NAME varchar(32) null , KEY_SEQ smallint null , UPDATE_RULE smallint null , DELETE_RULE smallint null , FK_NAME varchar(32) null, PK_NAME varchar(32) null, DEFERRABILITY int null ) ', 'sp_ijdbc_importkey(?,?,?)', 'select * from #tmp_fkeys', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('EXPORTEDKEYS', 1, 'create table #tmp_fkeys ( PKTABLE_CAT varchar (32) null, PKTABLE_SCHEM varchar (32) null, PKTABLE_NAME varchar(64) null , PKCOLUMN_NAME varchar(32) null , FKTABLE_CAT varchar(32) null, FKTABLE_SCHEM varchar(32) null, FKTABLE_NAME varchar(32) null , FKCOLUMN_NAME varchar(32) null , KEY_SEQ smallint null , UPDATE_RULE smallint null , DELETE_RULE smallint null , FK_NAME varchar(32) null, PK_NAME varchar(32) null, DEFERRABILITY int null
) ', 'sp_ijdbc_exportkey(?,?,?)', 'select * from #tmp_fkeys', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('PRIMARYKEYS', 1, 'create table #tmp_primarykey ( TABLE_CAT varchar(32) null, TABLE_SCHEM     varchar(32) null, TABLE_NAME      varchar(32) null,   COLUMN_NAME     varchar(32) null,   KEY_SEQ         smallint null, PK_NAME     varchar(30) null) ', 'sp_ijdbc_primarykey(?,?,?)', 'select * from #tmp_primarykey', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('PRODUCTNAME', 2, null, 'select ''Adaptive Server Enterprise''', null, 1, 3, 0, -1) 

insert spt_ijdbc_mda values ('PRODUCTNAME', 6, null, 'Adaptive Server Enterprise', null, 4, 7, 0, -1) 
insert spt_ijdbc_mda values ('ISREADONLY', 2, null,'select 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('ISREADONLY', 4, null, '0', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('ALLPROCSCALLABLE', 2, null, 'select 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('ALLPROCSCALLABLE', 4, null, '0', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('ALLTABLESSELECTABLE', 2, null, 'select 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('ALLTABLESSELECTABLE', 4, null, '0', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('COLUMNALIASING', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('COLUMNALIASING', 4, null, '1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('IDENTIFIERQUOTE', 2, null, 'select ''"''', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('IDENTIFIERQUOTE', 6, null, '"', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('ALTERTABLESUPPORT', 2, null, 'select 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('ALTERTABLESUPPORT', 4, null, '1, 1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('CONNECTCONFIG', 2, null, 'set quoted_identifier on set textsize 2147483647', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('CONVERTSUPPORT', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CONVERTSUPPORT', 4, null, '1', null, 4, 7, 0, -1)

insert spt_ijdbc_mda values ('CONVERTMAP', 1, 'create table #tmp_convert_datatype (CONVERT_TYPE smallint null)', 'sp_ijdbc_convert_datatype(?,?)', 'select * from #tmp_convert_datatype', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('LIKEESCAPECLAUSE', 2, null, 'select 1', null,  1, 3, 0, -1)
insert spt_ijdbc_mda values ('LIKEESCAPECLAUSE', 4, null, '1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('MULTIPLERESULTSETS', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('MULTIPLERESULTSETS', 4, null, '1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('MULTIPLETRANSACTIONS', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('MULTIPLETRANSACTIONS', 4, null, '1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('NONNULLABLECOLUMNS', 2, null, 'select 1', null, 1, 3, 0, -1) 
insert spt_ijdbc_mda values ('NONNULLABLECOLUMNS', 4, null, '1', null, 4, 7, 0, -1) 
insert spt_ijdbc_mda values ('POSITIONEDDELETE', 2, null, 'select 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('POSITIONEDDELETE', 4, null, '0', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('POSITIONEDUPDATE', 2, null, 'select 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('POSITIONEDUPDATE', 4, null, '0', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('STOREDPROCEDURES', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('STOREDPROCEDURES', 4, null, '1', null, 4, 7, 0, -1)

insert spt_ijdbc_mda values ('PROCEDURES', 1, 'create table #tmp_stored_procedures ( PROCEDURE_CAT varchar(32) null, PROCEDURE_SCHEM varchar(32) null, PROCEDURE_NAME varchar(32) null, num_input_params int null, num_output_params int null, num_result_sets int null, REMARKS varchar(254) null, PROCEDURE_TYPE int null)', 'sp_ijdbc_stored_procedures(?,?,?)','select * from #tmp_stored_procedures',  1, 7, 0, -1)

insert spt_ijdbc_mda values ('SELECTFORUPDATE', 2, null, 'select 0', null, 1, 3, 0, -1) 

insert spt_ijdbc_mda values ('SELECTFORUPDATE', 4, null, '0', null, 4, 7, 0, -1) 
insert spt_ijdbc_mda values ('CURSORTRANSACTIONS', 2, null, 'select 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CURSORTRANSACTIONS', 4, null, '1, 1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('STATEMENTTRANSACTIONS', 2, null, 'select 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('STATEMENTTRANSACTIONS', 4, null, '1, 1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('TRANSACTIONSUPPORT', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('TRANSACTIONSUPPORT', 4, null, '1', null, 4, 7, 0, -1)
/* 
 *Set this to 1 if 'exec <dbname>..<storedProcName>' is allowed
 */
insert spt_ijdbc_mda values ('PREPEND_DB_NAME', 2, null, 'select 1', null, 1, 3, 0, -1) 
insert spt_ijdbc_mda values ('PREPEND_DB_NAME', 5, null, '1', null, 4, 7, 0, -1) 

-- note - transaction levels here match Connection.TRANSACTION
-- insert spt_ijdbc_mda values ('TRANSACTIONLEVELS', 1, 'sp_ijdbc_getisolationlevels',1 ,7, 0, -1) 
insert spt_ijdbc_mda values ('TRANSACTIONLEVELS', 2, null, 'select 8, 2, 1', null, 1, 7,0, -1)

insert spt_ijdbc_mda values ('TRANSACTIONLEVELDEFAULT', 2, null, 'select 2', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('TRANSACTIONLEVELDEFAULT', 5, null, '2', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_ISOLATION', 2, null, 'set transaction isolation level ', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('GET_ISOLATION', 2, null, 'select @@isolation', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_ROWCOUNT', 2, null, 'set rowcount ?', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('GET_AUTOCOMMIT', 2, null, 'select @@tranchained', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_AUTOCOMMIT_ON', 2, null, 'set CHAINED off', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_AUTOCOMMIT_OFF', 2, null, 'set CHAINED on', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('USERNAME', 2, null, 'select user_name()', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_READONLY_TRUE', 3, null, '', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_READONLY_FALSE', 3, null, '', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SET_CATALOG', 2, null, 'use ?', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('GET_CATALOG', 2, null, 'select db_name()', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('NULLSORTING', 2, null, 'select 0, 1, 0, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('NULLSORTING', 4, null, '0, 1, 0, 0', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('PRODUCTVERSION', 2, null, 'select @@version', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('FILEUSAGE', 2, null, 'select 0, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('FILEUSAGE', 4, null, '0, 0', null, 4, 7, 0, -1)
if ('a'='A')  	/* Case insensitive */
    begin
        insert spt_ijdbc_mda values ('IDENTIFIERCASES', 2, null, 'select 0, 0, 0, 1, 1, 0, 0, 1', null, 1, 3, 0, -1)
        insert spt_ijdbc_mda values ('IDENTIFIERCASES', 4, null, '0, 0, 0, 1, 1, 0, 0, 1', null, 4, 7, 0, -1)

    end
else 		/* case sensitive */
    begin
        insert spt_ijdbc_mda values ('IDENTIFIERCASES', 2, null, 'select 1, 0, 0, 0, 1, 0, 0, 0', null, 1, 3, 0, -1)
        insert spt_ijdbc_mda values ('IDENTIFIERCASES', 4,null,  '1, 0, 0, 0, 1, 0, 0, 0', null, 4, 7, 0, -1)
    end

insert spt_ijdbc_mda values ('SQLKEYWORDS', 2, null, 'select name from master.dbo.spt_values where type = ''W'' and ansi_w != 1', null, 1, 7, 0, -1)

insert spt_ijdbc_mda values ('NUMERICFUNCTIONLIST', 2, null, 'select ''abs,acos,asin,atan,atan2,ceiling,cos,cot,degrees,exp,floor,log,log10,pi,power,radians,rand,round,sign,sin,sqrt,tan''', null, 1, 4, 0, -1)
insert spt_ijdbc_mda values ('NUMERICFUNCTIONLIST', 7, null, 'abs,acos,asin,atan,atan2,ceiling,cos,cot,degrees,exp,floor,log,log10,pi,power,radians,rand,round,sign,sin,sqrt,tan', null, 5, 7, 0, -1)
insert spt_ijdbc_mda values ('STRINGFUNCTIONLIST', 2, null, 'select ''ascii,char,concat,difference,insert,length,lcase,ltrim,repeat,right,rtrim,soundex,space,substring,ucase''', null, 1, 4, 0, -1)
insert spt_ijdbc_mda values ('STRINGFUNCTIONLIST', 7, null, 'ascii,char,concat,difference,insert,length,lcase,ltrim,repeat,right,rtrim,soundex,space,substring,ucase', null, 5, 7, 0, -1)
insert spt_ijdbc_mda values ('SYSTEMFUNCTIONLIST', 2, null, 'select ''database,ifnull,user,convert''', null, 1, 4, 0, -1)
insert spt_ijdbc_mda values ('SYSTEMFUNCTIONLIST', 7, null, 'database,ifnull,user,convert', null, 5, 7, 0, -1)
insert spt_ijdbc_mda values ('TIMEDATEFUNCTIONLIST', 2, null, 'select ''curdate,curtime,dayname,dayofmonth,dayofweek,dayofyear,hour,minute,month,monthname,now,quarter,second,timestampadd,timestampdiff,week,year''', null, 1,4, 0, -1)
insert spt_ijdbc_mda values ('TIMEDATEFUNCTIONLIST', 7, null, 'curdate,curtime,dayname,dayofmonth,dayofweek,dayofyear,hour,minute,month,monthname,now,quarter,second,timestampadd,timestampdiff,week,year', null, 5, 7, 0, -1)  
insert spt_ijdbc_mda values ('NULLPLUSNONNULL', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('NULLPLUSNONNULL', 4, null, '1', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('EXTRANAMECHARS', 2, null, 'select ''@#$''', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('EXTRANAMECHARS', 6,null,  '@#$', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('MAXBINARYLITERALLENGTH', 2, null, 'select 255', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('MAXBINARYLITERALLENGTH', 5, null, '255', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('MAXCHARLITERALLENGTH', 2, null, 'select 255', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('MAXCHARLITERALLENGTH', 5, null, '255', null, 4, 7, 0, -1)
go
insert spt_ijdbc_mda values ('SCHEMAS', 1,'create table #tmp_getschemas (TABLE_SCHEM varchar(30) null) ', 'sp_ijdbc_getschemas',' select * from #tmp_getschemas', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('COLUMNPRIVILEGES', 1, 'create table #tmp_getcolumnprivileges ( TABLE_CAT varchar(32) null, TABLE_SCHEM varchar(32) null, TABLE_NAME varchar(32) null, COLUMN_NAME varchar(32) null, GRANTOR varchar(32) null, GRANTEE varchar(32) null, PRIVILEGE varchar(128) null, IS_GRANTABLE char(3) null)', 'sp_ijdbc_getcolumnprivileges( ?,?,?,?)', 'select * from #tmp_getcolumnprivileges',  1, 7, 0, -1)

insert spt_ijdbc_mda values ('TABLEPRIVILEGES', 1, 'create table #tmp_gettableprivileges ( TABLE_CAT varchar(32) null, TABLE_SCHEM varchar(32) null, TABLE_NAME varchar(32) null, GRANTOR varchar(32) null, GRANTEE varchar(32) null, PRIVILEGE varchar(128) null, IS_GRANTABLE char(3) null) ', 'sp_ijdbc_gettableprivileges(?,?,?)', ' select * from  #tmp_gettableprivileges', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('ROWIDENTIFIERS', 1, 'create table #tmp_getbestrowidentifier ( SCOPE smallint null, COLUMN_NAME varchar(32) null, DATA_TYPE smallint null, TYPE_NAME varchar(32) null , COLUMN_SIZE int null, BUFFER_LENGTH varchar(255) null,  DECIMAL_DIGITS smallint null, PSEUDO_COLUMN smallint null) ', 'sp_ijdbc_getbestrowidentifier(?,?,?,?,?)', 'select * from #tmp_getbestrowidentifier', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('VERSIONCOLUMNS', 1, ' create table #tmp_getversioncolumns (SCOPE smallint null, COLUMN_NAME varchar(32) null, DATA_TYPE int null, TYPE_NAME varchar(8) null, COLUMN_SIZE int null, BUFFER_LENGTH smallint null, DECIMAL_DIGITS smallint null, PSEUDO_COLUMN smallint null) ', 'sp_ijdbc_getversioncolumns(?,?,?)',' select * from #tmp_getversioncolumns', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('KEYCROSSREFERENCE', 1, 'create table #tmp_fkeys ( PKTABLE_CAT varchar (32) null, PKTABLE_SCHEM varchar (32) null, PKTABLE_NAME varchar(64) null , PKCOLUMN_NAME varchar(32) null , FKTABLE_CAT varchar(32) null, FKTABLE_SCHEM varchar(32) null, FKTABLE_NAME varchar(32) null , FKCOLUMN_NAME varchar(32) null , KEY_SEQ smallint null , UPDATE_RULE smallint null , DELETE_RULE smallint null , FK_NAME varchar(32) null, PK_NAME varchar(32) null, DEFERRABILITY int null) ', 'sp_ijdbc_getcrossreferences(?,?,?,?,?,?)', 'select * from #tmp_fkeys', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('INDEXINFO', 1, 'create table #tmp_getindexinfo ( TABLE_CAT  varchar (32) null, TABLE_SCHEM varchar (32) null, TABLE_NAME varchar (32) null, NON_UNIQUE varchar (5) null, INDEX_QUALIFIER varchar (32) null, INDEX_NAME varchar (32) null, TYPE smallint null, ORDINAL_POSITION smallint null, COLUMN_NAME varchar (32) null, ASC_OR_DESC varchar (1) null, CARDINALITY int null, PAGES int null, FILTER_CONDITION varchar (32) null) ', 'sp_ijdbc_getindexinfo(?,?,?,?,?)', 'select * from #tmp_getindexinfo', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('PROCEDURECOLUMNS', 1, 'create table #tmp_getprocedurecolumns (PROCEDURE_CAT varchar(32) null,PROCEDURE_SCHEM varchar(32) null,PROCEDURE_NAME varchar(32) not null,COLUMN_NAME varchar(32) not null,COLUMN_TYPE smallint not null,DATA_TYPE smallint not null,TYPE_NAME varchar(32) not null,PRECISION int not null,LENGTH int not null,SCALE smallint not null,RADIX smallint not null, NULLABLE smallint not null,REMARKS varchar(255) null) ', 'sp_ijdbc_getprocedurecolumns(?,?,?,?)', 'select * from #tmp_getprocedurecolumns', 1, 7, 0, -1)

insert spt_ijdbc_mda values ('CATALOGS', 1, 'create table #tmp_getcatalogs ( TABLE_CAT varchar(30) null)', 'sp_ijdbc_getcatalogs','select * from #tmp_getcatalogs', 1, 7, 0, -1)
insert spt_ijdbc_mda values ('TABLETYPES', 2, null, 'select TABLE_TYPE from master.dbo.spt_ijdbc_table_types', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('SEARCHSTRING', 2, null, 'select ''\''', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('SEARCHSTRING', 6, null, '\', null, 4, 7, 0, -1)
/*
supportsIntegrityEnhancementFacility: true
*/
insert spt_ijdbc_mda values ('INTEGRITYENHANCEMENT', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('INTEGRITYENHANCEMENT', 4, null, '1', null, 4, 7, 0, -1)

/* 
supportsOuterJoins: true
supportsFullOuterJoins: false
supportsLimitedOuterJoins: true
supports the syntax of the body of an oj escape without further
processing: false for Version < 12
*/
insert spt_ijdbc_mda values ('OUTERJOINS', 2, null, 'select 1, 0, 1, 0', null, 1, 3, 0, 11950)
insert spt_ijdbc_mda values ('OUTERJOINS', 4, null, '1, 0, 1, 0', null, 4, 7, 0, 11950)
insert spt_ijdbc_mda values ('OUTERJOINS', 2, null, 'select 1, 0, 1, 1', null, 1, 3, 11950, -1)
insert spt_ijdbc_mda values ('OUTERJOINS', 4, null, '1, 0, 1, 1', null, 4, 7, 11950, -1)
go

/* 
isCatalogAtStart: true
*/
insert spt_ijdbc_mda values ('CATALOGATSTART', 2, null, 'select 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CATALOGATSTART', 4, null, '1', null, 4, 7, 0, -1)

/* 
same with catalog
*/
insert spt_ijdbc_mda values ('CATALOGSUPPORT', 2, null, 'select 1, 1, 1, 1, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CATALOGSUPPORT', 4, null, '1, 1, 1, 1, 0', null, 4, 7, 0, -1)

/* 
supportsSubqueriesInComparisons: true
supportsSubqueriesInExists: true
supportsSubqueriesInIns: true
supportsSubqueriesInQuantifieds: true
supportsCorrelatedSubqueries: true
*/
insert spt_ijdbc_mda values ('SUBQUERIES', 2, null, 'select 1, 1, 1, 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('SUBQUERIES', 4, null, '1, 1, 1, 1, 1', null, 4, 7, 0, -1)

/*
supportsTableCorrelationNames: true
supportsDifferentTableCorrelationNames: false
*/
insert spt_ijdbc_mda values ('CORRELATIONNAMES', 2, null, 'select 1, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CORRELATIONNAMES', 4, null, '1, 0', null, 4, 7, 0, -1)

/*
supportsExpressionsInOrderBy: true
supportsOrderByUnrelated: true
*/
insert spt_ijdbc_mda values ('ORDERBYSUPPORT', 2, null, 'select 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('ORDERBYSUPPORT', 4, null, '1, 1', null, 4, 7, 0, -1)

/* 
supportsGroupBy: true
supportsGroupByUnrelated: true
supportsGroupByBeyondSelect: true
*/
insert spt_ijdbc_mda values ('GROUPBYSUPPORT', 2, null, 'select 1, 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('GROUPBYSUPPORT', 4, null, '1, 1, 1',null,  4, 7, 0, -1)

/* 
supportsMinimumSQLGrammar: true
supportsCoreSQLGrammar: false
supportsExtendedSQLGrammar: false
*/
insert spt_ijdbc_mda values ('SQLGRAMMAR', 2, null, 'select 1, 0, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('SQLGRAMMAR', 4, null, '1, 0, 0', null, 4, 7, 0, -1)

/* 
supportsANSI92EntryLevelSQL: true
supportsANSI92IntermediateSQL: false
supportsANSI92FullSQL: false
*/
insert spt_ijdbc_mda values ('ANSI92LEVEL', 2, null, 'select 1, 0, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('ANSI92LEVEL', 4, null, '1, 0, 0', null, 4, 7, 0, -1)
go

/* 
SQL Server's terms for 'schema', 'procedure' and 'catalog' 
and how to separate them
*/
insert spt_ijdbc_mda values ('SCHEMATERM', 2, null, 'select ''owner''', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('SCHEMATERM', 6,null,  'owner',null,  4, 7, 0, -1)
insert spt_ijdbc_mda values ('PROCEDURETERM', 2, null, 'select ''stored procedure''',null,  1, 3, 0, -1)
insert spt_ijdbc_mda values ('PROCEDURETERM', 6, null, 'stored procedure', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('CATALOGTERM', 2, null, 'select ''database''', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CATALOGTERM', 6, null, 'database', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('CATALOGSEPARATOR', 2, null, 'select ''.''', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('CATALOGSEPARATOR', 6, null, '.', null, 4, 7, 0, -1)

/* 
supportsSchemasInDataManipulation: true
supportsSchemasInProcedureCalls: true
supportsSchemasInTableDefinitions: true
supportsSchemasInIndexDefinitions: true
supportsSchemasInPrivilegeDefinitions: false
*/
insert spt_ijdbc_mda values ('SCHEMASUPPORT', 2, null, 'select 1, 1, 1, 1, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('SCHEMASUPPORT', 4, null, '1, 1, 1, 1, 0', null, 4, 7, 0, -1)

/* 
supportsUnion: true
supportsUnionAll: true
*/
insert spt_ijdbc_mda values ('UNIONSUPPORT', 2, null, 'select 1, 1', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('UNIONSUPPORT', 4, null, '1, 1', null, 4, 7, 0, -1)

/* 
supportsDataDefinitionAndDataManipulationTransactions: true
supportsDataManipulationTransactionsOnly: false
dataDefinitionCausesTransactionCommit: false
dataDefinitionIgnoredInTransactions: false
*/
insert spt_ijdbc_mda values ('TRANSACTIONDATADEFINFO', 2, null, 'select 1, 0, 0, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('TRANSACTIONDATADEFINFO', 4, null, '1, 0, 0, 0', null, 4, 7, 0, -1)

/*
max column name length, max columns in group by,
max columns in index, max columns in order by,
max columns in select, max columns in table
XXX max columns in index is only 15 for B1
server.  Will that be a separate script?  Can we
detect whether this is B1 server?
XXX max columns in select is unlimited, so I'm
returning 0 -- the spec I'm looking at
doesn't actually say what to do in such a case
*/
insert spt_ijdbc_mda values ('COLUMNINFO', 2, null, 'select 30, 16, 16, 16, 0, 250', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('COLUMNINFO', 5, null, '30, 16, 16, 16, 0, 250', null, 4, 7, 0, -1)
insert spt_ijdbc_mda values ('MAXCONNECTIONS', 2, null, 'select @@max_connections', null, 1, 7, 0, -1)
insert spt_ijdbc_mda values ('MAXINDEXLENGTH', 2, null, 'select 255', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('MAXINDEXLENGTH', 5, null, '255', null, 4, 7, 0, -1)
/*
max cursor name length, max user name length,
max schema name length, max procedure name length,
max catalog name length
*/
insert spt_ijdbc_mda values ('MAXNAMELENGTHS', 2, null, 'select 30, 30, 30, 30, 30', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('MAXNAMELENGTHS', 5,null,  '30, 30, 30, 30, 30', null, 4, 7, 0, -1)
/*
** max bytes in a row is 1962, 0 is for 'no, that doesn't include blobs'
** ROWINFO cannot be converted into a LITERAL type since it contains 
** different types for each column:  int, boolean
*/
insert spt_ijdbc_mda values ('ROWINFO', 2, null, 'select 1962, 0', null, 1, 7, 0, -1)
/*
max length of a statement, max number of open statements
both are unlimited
*/
insert spt_ijdbc_mda values ('STATEMENTINFO', 2,null,  'select 0, 0', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('STATEMENTINFO', 5, null, '0, 0', null, 4, 7, 0, -1)
/*
max table name length, max tables in a select
*/
insert spt_ijdbc_mda values ('TABLEINFO', 2, null, 'select 30, 256', null, 1, 3, 0, -1)
insert spt_ijdbc_mda values ('TABLEINFO', 5, null, '30, 256', null, 4, 7, 0, -1)
go
/*
RSMDA.getColumnTypeName
*/
insert spt_ijdbc_mda values ('COLUMNTYPENAME', 1, 'create table #tmp_sql_type_name (name varchar(32) null ) ', 'sp_ijdbc_sql_type_name?,?)', 'select * from #tmp_sql_type_name', 1, 7, 0, -1)
go
/*
Get the Data source specific DEFAULT CHARACTER SET
*/
insert spt_ijdbc_mda values ('DEFAULT_CHARSET', 1, 'create  table  #tmp_default_charset (DEFAULT_CHARSET varchar(30) null)', 'sp_ijdbc_default_charset', 'select * from  #tmp_default_charset', 1, 7, 0, -1)
go
/*
ownUpdatesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('OWNUPDATESAREVISIBLE', 4, null, '1, 0, 0', null, 6, 7, 0, -1)
go
/*
ownDeletesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('OWNDELETESAREVISIBLE', 4,null,  '1, 0, 0', null, 6, 7, 0, -1)
go
/*
ownInsertsAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('OWNINSERTSAREVISIBLE', 4,null,  '0, 0, 0', null, 6, 7, 0, -1)
go
/*
othersUpdatesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('OTHERSUPDATESAREVISIBLE', 4, null, '1, 0, 0', null, 6, 7, 0, -1)
go
/*
othersDeletesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('OTHERSDELETESAREVISIBLE', 4, null, '1, 0, 0', null, 6, 7, 0, -1)
go
/*
othersInsertsAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('OTHERSINSERTSAREVISIBLE', 4, null, '1, 0, 0', null, 6, 7, 0, -1)
go
/*
updatesAreDetected (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('UPDATESAREDETECTED', 4, null, '0, 0, 0', null, 6, 7, 0, -1)
go
/*
deletesAreDetected (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('DELETESAREDETECTED', 4, null, '0, 0, 0', null, 6, 7, 0, -1)
go
/*
insertsAreDetected (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('INSERTSAREDETECTED', 4, null, '0, 0, 0', null, 6, 7, 0, -1)
go
/*
supportsBatchUpdates: true (JDBC 2.0)
*/
insert spt_ijdbc_mda values ('SUPPORTSBATCHUPDATES', 4, null, '1', null, 6, 7, 0, -1)
go
/*
execBatchUpdatesInLoop: false 
*/
insert spt_ijdbc_mda values ('EXECBATCHUPDATESINLOOP', 4, null, '0', null, 6, 7, 0, -1)
go
/*
supportsResultSetType (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: true
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('SUPPORTSRESULTSETTYPE', 4, null, '1, 1, 0', null, 6, 7, 0, -1)
go
/*
supportsResultSetConcurrency(CONCUR_READ_ONLY) (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: true
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('READONLYCONCURRENCY', 4, null, '1, 1, 0', null, 6, 7, 0, -1)
go
/*
supportsResultSetConcurrency(CONCUR_UPDATABLE) (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_ijdbc_mda values ('UPDATABLECONCURRENCY', 4, null, '1, 0, 0', null, 6, 7, 0, -1)
go
/*
getUDTs (JDBC 2.0)
*/  
insert spt_ijdbc_mda values ('UDTS', 1, null, 'sp_ijdbc_getudts(?,?,?,?)', null, 6, 7, 0, -1)
go
/*
isCaseSensitive
*/
insert spt_ijdbc_mda values ('ISCASESENSITIVE', 2, null, 'if exists (select 1 where ''A'' = ''a'') select 0 else select 1', null, 6, 7, 0, -1)
go

/*
 JTA support for JDBC 2.0 extensions

 XACOORDINATORTYPE returns the type of the distributed transaction
 coordinator.  It is up to jConnect to manufacture an XAResource object
 that can interact with that type of coordinator.

 This is temporary.  When ASE 12.0 implements CR 203610 we will use
 that accessor.
*/
insert spt_ijdbc_mda values ('XACOORDINATORTYPE', 1,'create  table #tmp_getxacoordinator ( TxnStyle int null, RequiredRole varchar(30) null, Status int null) ',  'sp_ijdbc_getxacoordinator', 'select * from  #tmp_getxacoordinator', 6, 7, 0, -1)

go

commit
go
dump tran master with truncate_only 
go

/*
**  End of spt_ijdbc_mda
*/



/*
**  spt_ijdbc_conversion
*/


/** SECTION BEGIN: CLEANUP **/
use master
go

/*
** create table with conversion information
*/
if exists (select * from sysobjects
	where name = 'spt_ijdbc_conversion')
begin
    drop table spt_ijdbc_conversion
end
go
/** SECTION END: CLEANUP **/

create table spt_ijdbc_conversion (datatype int, conversion char(20))
go

grant select on spt_ijdbc_conversion to public
go

/*Values based on the table info from the SQL Server Ref Man Chapter 4*/
/*bit*/
insert into spt_ijdbc_conversion values(0,'11111110111111110001')
/*integers+numerics*/
insert into spt_ijdbc_conversion values(1,'11111100011111110000')
insert into spt_ijdbc_conversion values(2,'11111100011111110000')
insert into spt_ijdbc_conversion values(9,'11111100011111110000')
insert into spt_ijdbc_conversion values(10,'11111100011111110000')
insert into spt_ijdbc_conversion values(11,'11111100011111110000')
insert into spt_ijdbc_conversion values(12,'11111100011111110000')
insert into spt_ijdbc_conversion values(13,'11111100011111110000')
insert into spt_ijdbc_conversion values(14,'11111100011111110000')
insert into spt_ijdbc_conversion values(15,'11111100011111110000')
/*Binaries*/
insert into spt_ijdbc_conversion values(5,'11111110111111111111')
insert into spt_ijdbc_conversion values(4,'11111110111111111111')
insert into spt_ijdbc_conversion values(3,'11111110111111111111')
/*Characters*/
insert into spt_ijdbc_conversion values(6,'00011110100000001111')
insert into spt_ijdbc_conversion values(8,'00011110100000001111')
insert into spt_ijdbc_conversion values(19,'00011110100000001111')
/*Dates*/
insert into spt_ijdbc_conversion values(16,'00000010000000001110')
insert into spt_ijdbc_conversion values(17,'00000010000000001110')
insert into spt_ijdbc_conversion values(18,'00000010000000001110')
/*NULL*/
insert into spt_ijdbc_conversion values(7,'00000000000000000000')
go
commit
go
dump tran master with truncate_only 
go

/*
**  End of spt_ijdbc_conversion
*/



/*
**  ijdbc_function_escapes
*/


/* 
** This script creates a table which is used by jdbcCONNECT to
** obtain information on this specific server types implementation
** of the various static functions for which JDBC provides escape
** sequences.
**
** Each row has two columns.  Escape_name is the name of the
** static function escape.  Map_string is a string showing how the
** function call should be sent to the server.  %i is a placeholder
** for the i'th argument to the escape.  This numbering is used
** to support skipping arguments.  Reordering of arguments is NOT
** supported.  Thus, a map string of 'foo(%2)' is ok (skips first
** argument); 'foo(%2, %1)' is not ok, at least until the driver
** changes to support this.
**
** Don't include rows for unsupported functions.
**
** Three escapes, convert, timestampadd, and timestampdiff, have
** one argument which takes special constant values.  These constants
** may also need to be mapped.  Therefore, include one row for each
** possible constant value, using the concatenation of the function name
** and the constant value as the escape_name column.  E.g.: 
** convertsql_binary, convertsql_bit, convertsql_char, etc.
** DO count the constant in figuring argument numbers.  Thus,
** timestampadd(sql_tsi_second, ts, ts) gets the map string
** 'dateadd(ss, %2, %3)')
**
** Use lower case for the escape name.  Use whatever case you
** need to for the map string.
**
*/

/** SECTION BEGIN: CLEANUP **/
use master
go

if exists (select * from sysobjects
    where name = 'ijdbc_function_escapes')
    begin
        drop table ijdbc_function_escapes
    end
go
/** SECTION END: CLEANUP **/

create table ijdbc_function_escapes (escape_name varchar(40),
    map_string varchar(40))
go

grant select on ijdbc_function_escapes to public
go

/* don't bother inserting rows for unsupported functions
** insert ijdbc_function_escapes values ('mod', null)
** insert ijdbc_function_escapes values ('truncate', null)
** insert ijdbc_function_escapes values ('left', null)
** insert ijdbc_function_escapes values ('locate', null)
** insert ijdbc_function_escapes values ('replace', null)
** insert ijdbc_function_escapes values (timestampdiffsql_tsi_frac_second, null)
** insert ijdbc_function_escapes values (timestampaddsql_tsi_frac_second, null)
** insert ijdbc_function_escapes values ('convertsql_bigint', null)
*/
insert ijdbc_function_escapes values ('abs', 'abs(%1)')
go
insert ijdbc_function_escapes values ('acos', 'acos(%1)')
go
insert ijdbc_function_escapes values ('asin', 'asin(%1)')
go
insert ijdbc_function_escapes values ('atan', 'atan(%1)')
go
insert ijdbc_function_escapes values ('atan2', 'atn2(%1, %2)')
go
insert ijdbc_function_escapes values ('ceiling', 'ceiling(%1)')
go
insert ijdbc_function_escapes values ('cos', 'cos(%1)')
go
insert ijdbc_function_escapes values ('cot', 'cot(%1)')
go
insert ijdbc_function_escapes values ('degrees', 'degrees(%1)')
go
insert ijdbc_function_escapes values ('exp', 'exp(%1)')
go
insert ijdbc_function_escapes values ('floor', 'floor(%1)')
go
insert ijdbc_function_escapes values ('log', 'log(%1)')
go
insert ijdbc_function_escapes values ('log10', 'log10(%1)')
go
insert ijdbc_function_escapes values ('pi', 'pi()')
go
insert ijdbc_function_escapes values ('power', 'power(%1, %2)')
go
insert ijdbc_function_escapes values ('radians', 'radians(%1)')
go
insert ijdbc_function_escapes values ('rand', 'rand(%1)')
go
insert ijdbc_function_escapes values ('round', 'round(%1, %2)')
go
insert ijdbc_function_escapes values ('sign', 'sign(%1)')
go
insert ijdbc_function_escapes values ('sin', 'sin(%1)')
go
insert ijdbc_function_escapes values ('sqrt', 'sqrt(%1)')
go
insert ijdbc_function_escapes values ('tan', 'tan(%1)')
go
insert ijdbc_function_escapes values ('ascii', 'ascii(%1)')
go
insert ijdbc_function_escapes values ('char', 'char(%1)')
go
insert ijdbc_function_escapes values ('concat', '%1 + %2')
go
insert ijdbc_function_escapes values ('difference', 'difference(%1, %2)')
go
insert ijdbc_function_escapes values ('insert', 'stuff(%1, %2, %3, %4)')
go
insert ijdbc_function_escapes values ('length', 'char_length(%1)')
go
insert ijdbc_function_escapes values ('lcase', 'lower(%1)')
go
insert ijdbc_function_escapes values ('ltrim', 'ltrim(%1)')
go
insert ijdbc_function_escapes values ('repeat', 'replicate(%1, %2)')
go
insert ijdbc_function_escapes values ('right', 'right(%1, %2)')
go
insert ijdbc_function_escapes values ('rtrim', 'rtrim(%1)')
go
insert ijdbc_function_escapes values ('soundex', 'soundex(%1)')
go
insert ijdbc_function_escapes values ('space', 'space(%1)')
go
insert ijdbc_function_escapes values ('substring', 'substring(%1, %2, %3)')
go
insert ijdbc_function_escapes values ('ucase', 'upper(%1)')
go
insert ijdbc_function_escapes values ('curdate', 'getdate()')
go
insert ijdbc_function_escapes values ('curtime', 'getdate()')
go
insert ijdbc_function_escapes values ('dayname', 'datename(dw, %1)')
go
insert ijdbc_function_escapes values ('dayofmonth', 
    'datepart(dd, %1)')
go
insert ijdbc_function_escapes values ('dayofweek', 
    'datepart(dw, %1)')
go
insert ijdbc_function_escapes values ('dayofyear', 
    'datepart(dy, %1)')
go
insert ijdbc_function_escapes values ('hour', 'datepart(hh, %1)')
go
insert ijdbc_function_escapes values ('minute', 'datepart(mi, %1)')
go
insert ijdbc_function_escapes values ('month', 'datepart(mm, %1)')
go
insert ijdbc_function_escapes values ('monthname',    
    'datename(mm, %1)')
go
insert ijdbc_function_escapes values ('now', 'getdate()')
go
insert ijdbc_function_escapes values ('quarter', 'datepart(qq, %1)')
go
insert ijdbc_function_escapes values ('second', 'datepart(ss, %1)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_second',
	'dateadd(ss, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_minute',
	'dateadd(mi, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_hour',
	'dateadd(hh, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_day',
	'dateadd(dd, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_week',
	'dateadd(wk, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_month',
	'dateadd(mm, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_quarter',
	'dateadd(qq, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampaddsql_tsi_year',
	'dateadd(yy, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_second',
	'datediff(ss, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_minute',
	'datediff(mi, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_hour',
	'datediff(hh, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_day',
	'datediff(dd, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_week',
	'datediff(wk, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_month',
	'datediff(mm, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_quarter',
	'datediff(qq, %2, %3)')
go
insert ijdbc_function_escapes values ('timestampdiffsql_tsi_year',
	'datediff(yy, %2, %3)')
go
insert ijdbc_function_escapes values ('week', 'datepart(wk, %1)')
go
insert ijdbc_function_escapes values ('year', 'datepart(yy, %1)')
go
insert ijdbc_function_escapes values ('database', 'db_name()')
go
insert ijdbc_function_escapes values ('ifnull', 'isnull(%1, %2)')
go
insert ijdbc_function_escapes values ('user', 'user_name()')
go
insert ijdbc_function_escapes values ('convertsql_binary',
	'convert(varbinary(255), %1)')
go
insert ijdbc_function_escapes values ('convertsql_bit', 
    'convert(bit, %1)')
go
insert ijdbc_function_escapes values ('convertsql_char',
	'convert(varchar(255), %1)')
go
insert ijdbc_function_escapes values ('convertsql_date',
	'convert(datetime, %1)')
go
insert ijdbc_function_escapes values ('convertsql_decimal',
	'convert(decimal(36, 18), %1)')
go
insert ijdbc_function_escapes values ('convertsql_double',
	'convert(float, %1)')
go
insert ijdbc_function_escapes values ('convertsql_float',
	'convert(float, %1)')
go
insert ijdbc_function_escapes values ('convertsql_integer',
	'convert(int, %1)')
go
insert ijdbc_function_escapes values ('convertsql_longvarbinary',
	'convert(varbinary(255), %1)')
go
insert ijdbc_function_escapes values ('convertsql_longvarchar',
	'convert(varchar(255), %1)')
go
insert ijdbc_function_escapes values ('convertsql_real',
	'convert(real, %1)')
go
insert ijdbc_function_escapes values ('convertsql_smallint',
	'convert(smallint, %1)')
go
insert ijdbc_function_escapes values ('convertsql_time',
	'convert(datetime, %1)')
go
insert ijdbc_function_escapes values ('convertsql_timestamp',
	'convert(datetime, %1)')
go
insert ijdbc_function_escapes values ('convertsql_tinyint',
	'convert(tinyint, %1)')
go
insert ijdbc_function_escapes values ('convertsql_varbinary',
	'convert(varbinary(255), %1)')
go
insert ijdbc_function_escapes values ('convertsql_varchar',
	'convert(varchar(255), %1)')
go

/*
**  End of ijdbc_function_escapes
*/
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_procxmode')
begin
	drop procedure sp_procxmode
end
go
print "Installing sp_procxmode"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
*/

create procedure sp_procxmode
@procname varchar(767) = null,
@execmode varchar(30) = null
as

declare @uid int
declare @oid int
declare @msg varchar(250)	/* message text */
declare @dbname varchar(255)
declare @owner varchar(30)
declare @objname varchar(257)
declare @objid int
declare @alltranmask int
declare @retcode int
declare @cmd varchar(255)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* 
** If either parameter is null we will be joining with a temporary table
** to convert transaction mode numbers (0, 16, 32, 256) to strings 
** ("Unchained", "Chained", "Any Mode", "Dynamic Ownership Chain").
** The "Dynamic Ownership Chain" is not an exclusive mode. It exists 
** in conjunction with one of the other three.
*/
if ((@procname is null) or (@execmode is null))
begin
	create table #execmode (intval integer, charval varchar(30))
	insert into #execmode values(0,  'Unchained')
	insert into #execmode values(16, 'Chained')
	insert into #execmode values(32, 'Any Mode')
	insert into #execmode values(256,'Dynamic Ownership Chain')

	select @alltranmask = 16 + 32
end

/* 
** If the first parameter is null, we're to report the transaction-modes
** of every stored procedure in the current database.
*/
if (@procname is null)
begin
	select 'procedure name' = o.name, 'user name' = user_name(o.uid),
		'transaction mode' = t.charval
	from sysobjects o, #execmode t
	where	((o.type = 'P') or (o.type = 'XP')) and
 		(((o.sysstat2 & t.intval ) != 0) or
		 ((t.intval = 0) and (o.sysstat2 & @alltranmask) = 0))
	order by o.name

	return(0)
end

/* 
** If only the second parameter is null, we will report the
** transaction-mode of the specified procedure.
*/
if ((@procname is not null) and (@execmode is null))
begin
	/* 
	** Check if proc name is prefixed with the dbname. The proc sp_namecrack
	** cannot be used, because sp_procxmode is created before and it
	** would cause a dependency failure at creation time.
	*/
	if @procname like "%.%.%.%"
	begin
        	select @procname = substring(@procname, charindex(".", @procname) + 1, 125)
	end

	if @procname like "%.%.%"
	begin
	        select @dbname = substring(@procname, 1, charindex(".", @procname) - 1)
        	select @procname = substring(@procname, charindex(".", @procname) + 1, 125)
	end

	if @procname like "%.%"
	begin
        	select @owner = substring(@procname, 1, charindex(".", @procname) - 1)
        	select @procname = substring(@procname, charindex(".", @procname) + 1, 125)
	end

	select @objname = @procname

	/*
	** If a database qualifies, it has to be this database.
	** Execute the procedure in the target database.
	*/
	if ((@dbname is not null) and (@dbname != db_name()))
	begin
		select @cmd = @dbname + '.dbo.sp_procxmode'
		select @procname = @owner + '.' + @objname
		exec @retcode = @cmd @procname
		return (@retcode)
	end

	select @objid = object_id(@procname)
	if (@objid is not null)
	begin
		if not exists(select 1 from sysobjects
			where id = @objid 
			and type in ('P', 'XP'))
		begin
			select @objid = null
		end
	end

	if (@objid is null)
	begin
		/*
		** Force an error message, since we haven't
		** installed sp_getmessage yet.
		*/
		dbcc update_tmode(@procname, 'anymode')
		return (1)
	end

 
	select 'procedure name' = o.name, 'user name' = user_name(o.uid),
		'transaction mode' = t.charval
	from sysobjects o, #execmode t
	where	(@objid = o.id) and
		((o.type = 'P') or (o.type = 'XP')) and
 		(((o.sysstat2 & t.intval ) != 0) or
		 ((t.intval = 0) and (o.sysstat2 & @alltranmask) = 0))

	return(0)
end

/* 
** If neither parameter is null, we're to set the transaction-mode
** of the specified procedure to the specified value.
*/
if ((@procname is not null) and (@execmode is not null))
begin
	/* Start the transaction to log the execution of this procedure.
	**
	** IMPORTANT: The name "rs_logexec is significant and is used by 
	**            Replication Server
	*/
	begin transaction rs_logexec

	/*
	** Update transaction-mode in both sysobjects and DES.
	*/
	dbcc update_tmode(@procname, @execmode)

	/* If dbcc update_tmode returned an error, return
	** an error now.
	*/
	if (@@error != 0)
	begin
		rollback transaction
		return(1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, 'sp_procxmode', @dbname
		rollback transaction
		return(1)
	end
		
	commit transaction

end
go

exec sp_procxmode 'sp_procxmode', 'anymode'
go

grant execute on sp_procxmode to public
go

-- Generate sp_procxmode on sp_drop_object as it was skipped earlier
-- when that sproc was first created. (sp_procxmode did not
-- exist at that time.)
-- You want to first check whether sp_drop_object exists in this db, to 
-- avoid calling sp_procxmode on a non-existent object.

if exists (select 1 from sysdatabases where name = 'sybsystemprocs')
	use sybsystemprocs
go

if exists (select 1 from sysobjects where name = 'sp_drop_object')
	exec sp_procxmode 'sp_drop_object', 'anymode'
go

use master
go

exec sp_procxmode 'sp_procxmode', 'rep_current'
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_validlang')
begin
	drop procedure sp_validlang
end
go
print "Installing sp_validlang"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */
create procedure sp_validlang
@name	varchar(255)
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Check to see if this language is in Syslanguages. */
if exists (select *
		from master.dbo.syslanguages
		where name = @name)
begin
	return 0
end
return 1
go
exec sp_procxmode 'sp_validlang', 'anymode'
go
grant execute on sp_validlang to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_getmessage')
begin
	drop procedure sp_getmessage
end
go
print "Installing sp_getmessage"
go


/* generic/sproc/getmessage	14.2	4/25/91 */

/* Messages from sysmessages
** 17200, "Message number must be greater than or equal to 17000."
** 17201, "'%1!' is not an official language name from Syslanguages."
** 17202, "Message number %1! does not exist in the %2! language."
*/

create procedure sp_getmessage
@message_num int,
@result varchar(1024) output,
@language varchar(30) = NULL
as

	declare @lang_id smallint 
	declare @msg varchar(1024)
	declare @returncode smallint

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* 
	** Use default language if none specified, 
	** and initialize result 
	*/
	select @lang_id = @@langid, @result = NULL

	/* Only retrieve external errors */
	if @message_num < 17000
	BEGIN
 		/* 17200   "Message number must be greater than or equal to 17000." */
		 select @msg = description from master.dbo.sysmessages
				    where error = 17200
		 print @msg
		 return (1)
	END

	/*
	** Check that language is valid.
	*/
	if @language is not NULL
	BEGIN
	    execute @returncode = sp_validlang @language
	    if @returncode != 0
	    begin
		    /* Us_english is always valid */
		    if @language != "us_english"
		    BEGIN
			    /* 
			    ** 17201, "'%1!' is not an official language
			    **	name from Syslanguages."
			    */
			    select @msg = description from master.dbo.sysmessages
						where error = 17201
						and langid = @@langid

			    /* Get english if the current language is missing */
			    if @msg is null
				select @msg = description from master.dbo.sysmessages
						where error = 17201
						and langid is NULL

			    print @msg, @language
			    return @returncode
		    END

		    /* set to us_english */
		    select @lang_id = NULL
	    end

	    else
	    select @lang_id = langid from master.dbo.syslanguages
			where @language = name

	END

	/* The langid is assigned 0 since it gets its value from @@langid. */
	/* For us_english, we have to insert it as NULL and not 0, this is */
	/* to maintain compatibility with the current conventions          */
	if @lang_id = 0 
	begin 
		select @lang_id = NULL        
	end   

	/* Get message from the proper place */
	/* System messages */
	if @message_num < 20000
	BEGIN
		select @result = description from master.dbo.sysmessages
			   where  langid = @lang_id 
			     and   error = @message_num 

		/* Get english if the current language is missing */
		if @result is null
			select @result = description from master.dbo.sysmessages
                                        where error = @message_num
                                        and (langid is NULL or langid =0)
	END
	else
	/* User messages */
	BEGIN
		/* There is no proper alternate language for user messages */
		select @result = description from sysusermessages
			   where  langid = @lang_id 
			     and   error = @message_num 

		/* this is in here for compatibility with older revs which */
		/* by mistake used to add langid as 0 in sysusermessages   */
		if @result is null and @lang_id is NULL
			select @result = description from sysusermessages
					where (langid = 0 or langid is NULL)
					and error = @message_num

	END

	/* Warn the user if the message can't be found */
	if @result is null
	begin
		/* 17202, "Message number %1! does not exist in the %2! language." */
		select @msg = description from master.dbo.sysmessages
			where error = 17202
			and langid = @@langid

		if @language is null
			select @language = @@language

		if @msg is null
			select @msg = "Message number %1! does not exist in the %2! language."

		print @msg, @message_num, @language

		return (1)
	end

return (0)
go
exec sp_procxmode 'sp_getmessage', 'anymode'
go
grant execute on sp_getmessage to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_getsize')
begin
	drop procedure sp_aux_getsize
end
go
print "Installing sp_aux_getsize"
go

/* This stored procedure is for parsing a size string of the form:
**		 "%f[pPkKmMgG]
** and return the value in equivalent "k" units if @format_str is NULL.
** If a format string is specified then another conversion to the required
** format is done. @output_str has the string equivalent of the return value.
** If a format string is specified then @ret_size value will be set to 0.
** For example sp_aux_getsize "1024K",@ret_size, "M" will put 1 in @ret_size.
**
**	Messages for sp_aux_getsize
** 
** 18146, "Syntax error encountered. Sizes must be of the form int[KMGP].
**         For example, a size of 5 megabytes may be specified as '5M'."
**
** 18149, "Invalid size of %1! encountered. Sizes must be greater than zero."
*/
create procedure sp_aux_getsize
@size_str		varchar(30),
@ret_size		int output,
@input_size		int = NULL,
@output_str		varchar(30) = NULL output
as

declare 
	@unit_loc		int,
	@multiplier		int,
	@one_char		char(1),
	@digits			varchar(30),
	@units			varchar(30),
	@float_size		float,
	@count			int,
	@found_invalid_char	int,
	@num_decimal		int,
	@digit_str_len		int

select @unit_loc = patindex("%[kKmMgGpP]%", @size_str)

if @unit_loc != 0
begin
	/*
	** Separate the unit specifier from the digits.
	*/
	select @digits = substring(@size_str, 1, @unit_loc - 1)
	select @units = lower(substring(@size_str, @unit_loc, 30))

	/*
	** Remove any blanks that may have been between the digits 
	** and the unit specifier (for example, '2 M').
	*/
	select @digits = rtrim(@digits)

	/* 
	** Make sure the unit specifier is valid.  Acceptable values
	** are [pPkKmMgG]; however; we will allow the user to specify 
	** [kKmMgG]b. For example, 8Mb will be allowed.
	*/
	if ((datalength(@units) > 2) 
	 or ((datalength(@units) > 1) and (substring(@units, 2, 1) != 'b'))
	 or ((datalength(@units) > 1) and (substring(@units, 1, 1) = 'p'))) 
	begin
		/* 18146, "Syntax error encountered. Sizes must be
		** of the form int[KMGP]. For example, a size of 5 
		** megabytes may be specified as '5M'."
		*/
		raiserror 18146
		select @ret_size = 0
		return 0
	end

	select @units = substring(@units, 1, 1)
end
else
begin
	select @digits = substring(@size_str, 1, char_length(@size_str))
	select @units = "k"
end

/*
** Ensure that @digits contains a valid floating-point 
** number.
*/
if (@digits is NULL)
begin
	/*
	** 18146, "Syntax error encountered. Sizes must be of the form
	**        int[KMGP]. For example, a size of 5 megabytes may be
	**        specified as '5M'."
	*/
	raiserror 18146
	select @ret_size = 0
	return 0
end

select @found_invalid_char = patindex("%[^0-9.]%", @digits)
select @num_decimal = 0

if (@found_invalid_char = 0)
begin
	/*
	** Shake out errors like '.2.0M'
	*/
	select @count = 1
	select @digit_str_len = char_length(@digits)

	while (@count <= @digit_str_len)
	begin
		select @one_char = substring(@digits, @count, 1)
		if (@one_char = ".")
		begin
			select @num_decimal = @num_decimal + 1
		end
		select @count = @count + 1
	end
end

if ((@found_invalid_char != 0) or (@num_decimal > 1))
begin
	/* 
	 ** 18146, "Syntax error encountered. Sizes must be of the form
	 **        int[KMGP]. For example, a size of 5 megabytes may be
	 **        specified as '5M'."
	 */
	 raiserror 18146
	 select @ret_size = 0
	 return 0
end

if @input_size is NULL
begin
	select @float_size = convert(float, @digits)

	if @float_size < 0
	begin
		select @size_str = rtrim(@size_str)
		/*
		** 18149, "Invalid size of %1! encountered. Sizes must be
		** greater than zero."
		*/
		raiserror 18149, @size_str
		return 0
	end

	if (@units = "p")
		select @float_size = @float_size * @@maxpagesize / 1024
	else if (@units = "m")
		select @float_size = @float_size * 1024 
	else if (@units = "g")
		select @float_size = @float_size * 1024 * 1024
end
else
begin
	select @float_size = @input_size
end
	
if @input_size is not NULL
begin
	/* Here the input size is assumed to be in K units */
	if (@units = "p")
		select @float_size = @float_size / (@@maxpagesize / 1024)
	else if (@units = "m")
		select @float_size = @float_size / 1024 
	else if (@units = "g")
		select @float_size = @float_size /(1024 * 1024) 
end

/*
**  Now round config size to the nearest integer value since
**  we'll be inserting this into sysconfigures as the integer
**  representation of the number of kilobytes for this size of this
**  cache.  But if a format string is given as an input, round it off
**  to the 4 digit precision after a decimal point.
*/
if @input_size is not NULL
begin
	select @ret_size = 0
	select @output_str = ltrim(str(round(@float_size, 4),15,4)) + @units
end
else
begin
	select @ret_size = convert(int, round(@float_size, 0))
end
return 1
go
exec sp_procxmode 'sp_aux_getsize', 'anymode'
go
grant execute on sp_aux_getsize to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_namecrack')
begin
	drop procedure sp_namecrack
end
go
print "Installing sp_namecrack"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */

create procedure sp_namecrack
@name	varchar(1023),
@site	varchar(255) = null output,
@db	varchar(255) = null output,
@owner	varchar(255) = null output,
@object	varchar(255) = null output
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @site = null, @db = null, @owner = null, @object = null

/*
**  Is there a site name?
*/
if @name like "%.%.%.%"
begin
	select @site = substring(@name, 1, charindex(".", @name) - 1)
	select @name = substring(@name, charindex(".", @name) + 1, 1025)
end

/*
**  Is there a database name?
*/
if @name like "%.%.%"
begin
	select @db = substring(@name, 1, charindex(".", @name) - 1)
	select @name = substring(@name, charindex(".", @name) + 1, 1025)
end

/*
**  Is there a owner?
*/
if @name like "%.%"
begin
	select @owner = substring(@name, 1, charindex(".", @name) - 1)
	select @name = substring(@name, charindex(".", @name) + 1, 1025)
end

select @object = @name

return (0)
go
exec sp_procxmode 'sp_namecrack', 'anymode'
go
grant execute on sp_namecrack to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_autoformat')
begin
	drop procedure sp_autoformat
end
go
print "Installing sp_autoformat"
go

/*
** Generated by spgenmsgs.pl on Fri Jul 25 17:36:44 2003 
*/
/*
** raiserror Messages for autoformat [Total 5]
**
** 17870, "Table '%1!' does not exist in database '%2!'. %3!"
** 18088, "The target database does not exist."
** 18588, "Column '%1!' does not exist in table '%2!'."
** 19206, "%1!: Execute immediate SQL failed. SQL statement is: %2!"
** 19237, "No columns were found in syscolumns in database '%1!' for table '%2!'."
*/
/*
** sp_getmessage Messages for autoformat [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
** **************************************************************************
** sp_autoformat
**
** Generic stored procedure to select data from any table and auto-format
** column's that are of [var]char (string) type (except text) so that these
** column's appear only wide as the maximum-sized data in the table being
** selected from.
**
** We also provide for a way to ONLY select a subset of the columns in the
** table. This list can be passed via the @selectlist argument, and should
** be a comma-separated list like what would be used by the user if they
** were doing a normal SELECT from this table. This list should ONLY contain
** the raw column names, and no further expressions around it.
**
** The output will be generated in the order that the columns are requested
** via this @selectlist argument.
**
** Restrictions:
** =============
**
**  . Does not fully support use of quoted identfiers for table and
**    column names.
**
**  . The @selectlist is expected to be comma-separated list.
**
**  . This proc does *not* validate that the columns in the WHERE clause,
**    ORDER BY provided by the user actually exist in the table being
**    selected from. These are just tacked on to the final SELECT statement.
**    If there are errors in these arguments, you will just get a run-time
**    error from execute immediate.
**
**  . The length of the generated SQL statement is max of 2048 bytes. For
**    tables with large # of columns, this might overflow. (Provision can
**    be made for the caller to supply a SQL buffer in the future.)
**
**  . There is some support for multi-byte character types but the
**    actual reporting of the data is untested.
**
** Parameters:
**	@fulltabname	- Full table name, possibly 2-, 3-part
**	@selectlist	- SELECT list of columns to output.
**	@whereclause	- Any WHERE predicates on table.
**	@orderby	- Any ORDER BY clause for output.
**	@fmtspecifier	- Format specifier to display output, say in XML.
**			  (Future extension. Currently only for: 'for xml')
**	@trace		- Tracing levels.
**
** NOTE(s):
** =========
**
**  - If the @selectlist is provided, then only these columns will be
**    projected out. If not, columns are projected out in colid order,
**    just like a 'select *' output.
**
** - @selectlist should be formatted as:
**
**	[ <Column's AS-Name label> ][ ]*=[ ]*<column name>
**
**  	. The <Column's AS-Name label> is optional.
**  	. There can be white spaces around the '=' separator.
**
** - This procedure creates a temporary table to store the column information
**   for the table being processed. The table is small, but causes space
**   requirements on tempdb. Column names of this table has a bit cryptic 
**   names - this is to avoid potential conflict with column names of a table
**   to process.
**
** - If the table being reported on is large-ish, and there are multiple
**   'char'-type columns, then the processing could be slightly slow as we
**   make as many passes over the input table as there are char-type columns
**   to determine each column's max-length.
**
** Examples:
** =========
**
	sp_autoformat systypes

	sp_autoformat syscolumns, 'id, colid, name'

	sp_autoformat syscolumns, "TableID = id, 'Column ID'=colid, name"
			, "where id = 3"
** Trace-levels:
** ==============
**	0	- Default; no tracing.
**	1	- High-level tracing of major phases.
**	2	- Detailed tracing for each phase.
**	3	- Dump select-list, as-list at end of each iteration.
**	4	- Dump contents of #temp table as it is processed.
**
**  Trace messages are intentionally left in-line as they are meant only
**  for debugging and internal uses.
**
** Returns:
**	0	- If all processing went ok.
**	1	- For usage errors/internal errors.
**	<n>	- The @@error value that was received when an error occured.
**		  This could be the return value from execute immediate.
**		  Client can trap this and do further processing based on
**		  the error number.
{
*/
create procedure sp_autoformat(
			  @fulltabname	varchar(767)
			, @selectlist	varchar(8192)	= NULL
			, @whereclause	varchar(4096)	= NULL
			, @orderby	varchar(4096)	= NULL
			, @fmtspecifier	varchar(32)	= NULL
			, @trace	int		= 0
) as
begin
	declare @whoami		varchar(255)
	      , @whoami_sp	varchar(258)
	      , @currdbname	varchar(30)
	      , @sitename	varchar(30)	-- unused.
	      , @dbname		varchar(30)
	      , @dbid		int		-- @dbname's dbid.
	      , @owner		varchar(30)
	      , @tablename	varchar(255)
	      , @lcl_tablename	varchar(767)
	      , @colname	varchar(510)
	      , @asname		varchar(275)	-- Could be longer than
	      					-- column name
	      , @asname_valid	int
	      , @sqlstr		varchar(8000)
	      , @dot_loc	int		-- location of '.' in names
	      , @comma_loc	int		-- location of ',' in lists
	      , @equal_loc	int		-- location of '=' in name.
	      , @objid		int
	      , @maxlength	int		-- really in # of chars.
	      , @autoformat	tinyint
	      , @sel_colnum	int		-- column number
	      , @as_colnum	int		-- as-list column number
	      , @retval		int
	      , @mbyte_char_str	varchar(30)
	      , @mbyte		int		-- whether column is multi-byte
	      , @sellist_given	tinyint		-- Boolean
	      , @colid		int		-- colid

	      , @this_col_spec_len	int
	      , @trace_highlevel	int
	      , @trace_detailed		int
	      , @trace_dumplists	int
	      , @trace_temptable	int
	      , @setrowcount		int
	      , @type			int
	      , @collength		int

	select	  @setrowcount = @@setrowcount	

	select	  @whoami = object_name(@@procid, db_id('sybsystemprocs'))
		, @currdbname	= db_name()

		-- Get rid of any leading spaces in input arguments.
		, @fulltabname	= ltrim(@fulltabname)
		, @whereclause	= ltrim(@whereclause)
		, @orderby	= ltrim(@orderby)

		-- Initially assume that it is a one-part name.
		--
	select	  @dbname = NULL
		, @owner = user_name()		-- current user.
		, @tablename = @fulltabname
		, @objid = object_id(@fulltabname)
		, @sellist_given = 0

		, @trace_highlevel	= 1
		, @trace_detailed	= 2
		, @trace_dumplists	= 3
		, @trace_temptable	= 4

	if (@trace >= @trace_highlevel)
	begin
		print "%1!: (Nesting Level: %2!) fulltabname: '%3!'"
			, @whoami , @@nestlevel , @fulltabname
	end

	/*
	** If we are under a user defined xact, disallow this since we may
	** we create tables via select-into and that is not allowed in a
	** multi-statement xact.
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_autoformat"
		select @retval = 1
		goto error_exit
	end

	set transaction isolation level 1    
	set chained off

	-- Extract out the 1st part of a 3-part or 2-part name
	if (charindex(".",@fulltabname) > 0)
	begin
		exec sp_namecrack @fulltabname
			, @sitename output
			, @dbname output
			, @owner output
			, @tablename output
	end
	else
	begin
		select @tablename = @fulltabname,
		@sitename = null, @dbname = null, @owner = null
	end

	-- Now that we have the basename for the table, do special processing
	-- to see if it is a #temp table. And manage the db-context for the
	-- temp table. User -might- be asking for a #temp table that is not
	-- the currently-assigned tempdb. If so, let the passed-in dbname be.
	-- Otherwise, set the dbname to be the user's currently assigned temp
	-- dbname.
	--
	if  ((@dbname is NULL) and (substring(@tablename, 1, 1) = "#") )
	begin
		select @dbname = db_name(@@tempdbid)
	end

	-- By now if @dbname is NULL, use current db to search for table.
	--
	if (@dbname IS NULL)
		select @dbname = db_name()

	-- ******************************************************************
	-- Error checking for invalid dbname, object name etc.
	--
	select @dbid = db_id(@dbname)
	if (@dbid IS NULL)
	begin
		raiserror 18088
		select @retval = 1
		goto error_exit
	end

	-- select @objid = object_id(@dbname + "." + @owner + "." + @tablename)
	select @lcl_tablename = @dbname + "." + @owner + "." + @tablename
	select @objid = object_id(@lcl_tablename)
	if (@objid IS NULL)
	begin
		-- Table does not exist in database. The last arg is NULL,
		-- as we don't need to further describe the action of what
		-- failed.
		--
		raiserror 17870, @fulltabname, @dbname, NULL
		select @retval = 1
		goto error_exit
	end

	if (@trace >= @trace_highlevel)
	begin
		print "%1!: (Nesting Level: %2!) %3! dbname: '%4!' owner: '%5!' tablename: '%6!' Objid: %7!"
			, @whoami , @@nestlevel
			, @currdbname, @dbname, @owner, @tablename
			, @objid
	end

	-- ******************************************************************
	-- Create a #temp table that will be used to further process the
	-- column list for the table being selected from.
	-- All we are doing here is to create a template table using      
	-- datatypes from syscolumns, systypes. Use the source tables from
	-- master to avoid deadlocking on syscolumns in tempdb.           
	--
	select    c.colid		as '_clid#af' 	-- colid
		, c.name		as '_clname#af' -- column name
		, t.usertype		as '_usrtype#af'-- usrtype
		, t.type		as '_type#af'	-- system type
		, t.name		as '_typnm#af'	-- type name
		, c.length		as '_colen#af'	-- length
		, convert(int not null, 0) as '_maxlen#af' -- max data length
		, convert(tinyint, 0) 	as '_auto#af'	-- autoformat bit
		, convert(tinyint, 0)	as '_slc#af'	-- appears in the select list
		, convert(int, 0)	as '_sorder#af' -- position in the select list
		, convert(varchar(50), c.name)  as '_asname#af' 
		, convert(tinyint, 0)	as '_mbyte#af'
	into	#colinfo_af lock allpages
	from master..syscolumns c, master..systypes t
	where 1 = 0

	set rowcount 0

	-- Insert column's datatype info and other book-keeping information
	-- for all columns in the table into the above #temp table.
	--
	if (@dbname != 'tempdb')
	begin
		select @sqlstr = 
		  "INSERT #colinfo_af"
		+ "(_clid#af,_clname#af,_usrtype#af,_type#af,_typnm#af,_colen#af"
		+ ",_maxlen#af,_auto#af,_slc#af,_sorder#af"
		+ ",_asname#af,_mbyte#af" + ")"

		-- Initially all columns are considered unselected,
		-- Initial load of the data is in colid order for
		-- the SELECT. This allows the @selectlist to be NULL
		-- and we still get the right results.
		-- And initial selectorder is 0 as we have not
		-- processed the select list, yet.
		--
		+  " SELECT c.colid,c.name,t.usertype,t.type,t.name"
			+ ",case when c.length < 80 then 80 else c.length end"
			+ ",0"		-- maxlength
			+ ",0"		-- autoformat
			+ ",1"		-- selected
			+ ",c.colid"		-- selectorder
			+ ",c.name"	-- asname
			+ ",0"		-- mbyte (multi-byte char column)

		+ " FROM " + @dbname + ".dbo.syscolumns c,"
			   + @dbname + ".dbo.systypes t"
		+ " WHERE c.id=" + convert(varchar, @objid)
		+    " AND c.usertype=t.usertype"

		select @whoami_sp = @whoami + '(1)'

		exec (@sqlstr)
		select @retval = @@error
		if (@retval != 0)
		begin
			raiserror 19206, @whoami_sp, @sqlstr
			goto error_exit
		end

	end
	else
	begin
		INSERT #colinfo_af	
		(_clid#af, _clname#af, _usrtype#af, _type#af, _typnm#af,
		_colen#af, _maxlen#af, _auto#af, _slc#af, _sorder#af,
		_asname#af, _mbyte#af)
		SELECT c.colid,c.name,t.usertype,t.type,t.name
		,case when c.length < 80 then 80 else c.length end
		,0          -- maxlength
		,0          -- autoformat
		,1          -- selected, assume by default all columns
		,c.colid    -- selectorder 
		,c.name     -- asname
		,0          -- mbyte (multi-byte char column)
		FROM tempdb.dbo.syscolumns c, tempdb.dbo.systypes t
		WHERE c.id= @objid AND c.usertype=t.usertype

	end

	-- *************************************************************
	-- Initially we assume that all columns in the table are being
	-- selected.
	--
	select @sel_colnum = count(*) from #colinfo_af

	-- If table's columns were not found in the syscolumns of the
	-- db specified (or chosen by this script), then there is an
	-- error somewhere. Flag that and bail.
	--
	if (@sel_colnum = 0)
	begin
		raiserror 19237 , @dbname, @fulltabname
		select @retval = 0
		goto error_exit
	end

	if (@trace >= @trace_temptable)
	begin
		exec sp_autoformat #colinfo_af, @trace = @trace
		
		select * from #colinfo_af

		print ""
		if (@trace >= @trace_highlevel)
		begin
			print "%1!: (Nesting Level: %2!) %3! dbname: '%4!' owner: '%5!' tablename: '%6!' Objid: %7!"
				, @whoami , @@nestlevel
				, @currdbname, @dbname, @owner, @tablename
				, @objid
		end
	end

	/*
	** *************************************************************
	** Parse the @selectlist, if any, and update the #temp table to
	** record the order that the user has requested in which the
	** columns should appear in the final output.
	*/
	if (@selectlist is NOT NULL)
	begin	-- {

		-- Mark all columns as not being selected as we have
		-- user-specified SELECT list.
		--
		update #colinfo_af
		set   _slc#af = 0		-- all columns are not selected
		    , _sorder#af = 0		-- no colid order

		if (@@error != 0)
		begin
			select @retval = @@error
			goto error_exit
		end

		if (@trace >= @trace_highlevel)
		begin
			print "Processing select list: %1!", @selectlist
		end
			-- Remember that user provided a select-list,
			-- which will soon be parsed away to become NULL.
		select    @sellist_given = 1

			-- Reset the select-list column #; will be recomputed.
			, @sel_colnum = 0

		while (@selectlist is NOT NULL)
		begin
			if (@trace >= @trace_dumplists)
			begin
				print "  Processing 'SELECT' list: %1!"
					, @selectlist
			end

			select @comma_loc = charindex(',', @selectlist)

			-- Extract out the current column.
			--
			select @colname = case @comma_loc
					    when 0 then @selectlist
					    else substring(@selectlist, 1,
							(@comma_loc - 1))
					  end

			-- Remember length of this entire pattern, with
			-- possibly embedded '=', as we need that length
			-- to move past this column specifier.
			--
			select @this_col_spec_len = datalength(@colname)

			select @sel_colnum = @sel_colnum + 1

			-- Parse the column specifier which can be one of:
			--
			--	select id
			--	select 'This ID' = id
			--
			-- (Column's AS-name is optional.)
			--
			select @equal_loc = charindex('=', @colname)

			if (@equal_loc != 0)
			begin
				-- L.h.s of '=' is label, AS-name
				select @asname = substring(@colname, 1,
							(@equal_loc - 1))

				-- R.h.s of '=' is column name.
				select @colname = substring(@colname,
							(@equal_loc + 1),
						(@this_col_spec_len
						 - datalength(@asname)
						 - 1) )

				select @asname = rtrim(ltrim(@asname))
					, @colname = rtrim(ltrim(@colname))
			end
			else
			begin
				select @colname = rtrim(ltrim(@colname))
				select @asname = @colname
			end

			select @asname_valid = valid_name(@asname)
			if (@trace >= @trace_detailed)
			begin
				print "    %1! Column: '%2!', AS-name: '%3!' valid ID: %4!"
					, @sel_colnum, @colname, @asname
					, @asname_valid
			end

			 -- Filter out duplicate columns in select-list
			 -- If column exists but selected = 1, then it
			 -- has been seen already. Raise an error.
			 --
			if ((select count(*) from #colinfo_af
			     where _clname#af = @colname
			       and _slc#af = 1) != 0)
			begin
				/*
				** This is a possibly temporary restriction,
				** so no raiserror is being done. This error
				** might go away in the future.
				*/
				print "Column '%1!' specified multiple times in the SELECT list. This is currently unsupported."
					, @colname
				select @retval = 1
				goto error_exit
			end

			-- Record the column's order # in the #temp table.
			-- And store its AS-name for the output.
			--
			update #colinfo_af
			set 	  _sorder#af = @sel_colnum
				, _slc#af = 1
				, _asname#af = @asname
			where _clname#af = @colname

			-- User is expected to be honest and provide a
			-- select-list that is exactly contained in the
			-- table's column-list. If we did not update
			-- exactly one row, it is an error. (0 rows
			-- updated means column was not found in the list
			-- of columns. More than one row updated means that
			-- the same column appeared twice in the select list.)
			--
			if (@@rowcount != 1)
			begin
				raiserror 18588, @colname, @fulltabname
				if (@trace >= @trace_temptable)
				begin
					
					select * from #colinfo_af
					order by _clid#af
					
				end
				select @retval = 1
				goto error_exit
			end

			if (@@error != 0)
			begin
				select @retval = @@error
				goto error_exit
			end

			-- Move past the previous column specifier (which
			-- possibly includes an embedded '=') and (any)
			-- ','-separator
			--
			select @selectlist =
				case @comma_loc
				  when 0 then NULL
				  else substring(@selectlist, (@comma_loc + 1),
					  (datalength(@selectlist)
					  	- @this_col_spec_len
						- 1)
					)
				end

			-- If the separator was the last item, and there is
			-- no more data after that (i.e. 'id, name,') flag
			-- that condition and raise an error. We should keep
			-- the behaviour consistent with that of
			-- 'id, name, '; where there are trailing spaces
			-- after the last comma.
			--
			if ((@comma_loc != 0) and (@selectlist IS NULL))
			begin
				raiserror 18588, @selectlist, @fulltabname
				select @retval = 1
				goto error_exit
			end
		end

	end	-- }	if (@selectlist is NOT NULL)

	if (@trace >= @trace_temptable)
	begin
		select * from #colinfo_af
	end

	/*
	** *************************************************************
	** Process the #temp table looking for columns that need auto-
	** -formatting.
	**
	**  . Scan each row of the #temp table.
	**  . Identify columns of [var]char, uni[var]char, and sysname
	**    types. (See below for complete list of types that need 
	**    auto-formatting.)
	**  . Update the #temp table w/max lengths for each column which
	**    is of this type.
	**  . Set a bit in table tagging this column, to avoid re-work.
	*/
	if (@trace >= @trace_highlevel)
	begin
		print "Processing #temp table looking for columns needing auto-formatting."
	end

	-- List of usertype values for char-type data that are multi-byte:
	-- 24 -- nchar
	-- 25 -- nvarchar
	-- 34 -- unichar
	-- 35 -- univarchar
	select @mbyte_char_str = "24, 25, 34, 35"


	/*
	** Note about the datatypes being handled here:
	**  . [var]binary is being skipped. We dont' want to deal with
	**    truncation of trailing 0s business right now.
	**  . TEXT (image) is being skipped as it is too much processing.
	*/
	declare curcolumns cursor for
	select _clname#af, _type#af, _colen#af, _clid#af
	from #colinfo_af
	where _type#af in (    38	-- intn, bigint null
			,  39	-- varchar, [long]sysname, nvarchar
			,  47	-- char, nchar
			,  48	-- tinyint
			,  49	-- date
			,  50	-- bit
			,  51	-- time
			,  52	-- smallint
			,  55	-- decimal
			,  56	-- int
			,  58	-- smalldatetime
			,  59	-- real
			,  60	-- money
			,  61	-- datetime
			,  62	-- float
			,  63	-- numeric
			,  65	-- usmallint
			,  66	-- uint
			,  67	-- ubigint
			,  68	-- uintn
			, 106	-- decimaln
			, 108	-- numericn
			, 109	-- floatn
			, 110	-- moneyn
			, 111	-- datetimn
			, 122	-- smallmoney	
			, 123	-- daten
			, 135	-- unichar
			, 147	-- timen
			, 155	-- univarchar
			, 187	-- bigdatetimen
			, 188 	-- bigtimen   
			, 189   -- bigdatetime
			, 190   -- bigtime
			, 191	-- bigint
	)
	and _sorder#af > 0

	/*
	** Reuse existing table instead of creating a new one.
	** Later a self-join may be done as well as two tables join.
	** Those duplicate rows will have columns: colname, maxlength
	** set and colid = -1.
	*/
	select @sqlstr = "INSERT #colinfo_af(_clid#af,_clname#af,_usrtype#af,
			_type#af,_typnm#af,_colen#af,_auto#af,_slc#af,_sorder#af,_asname#af,_mbyte#af,_maxlen#af)
		SELECT -1,_clname#af,0,0,'',0,0,0,0,'',0 , "
	open curcolumns

	fetch curcolumns into @colname, @type, @collength, @colid

	while (@@sqlstatus = 0)
	begin	-- {

		if (@trace >= @trace_detailed)
		begin
			print "    Column '%1!'", @colname
		end

		-- Some background: the first isnull() caters
		-- for a case where we have 0 rows at all,
		-- so the minimum length is 1. The second
		-- isnull() enforces a minimum length of 4
		-- when NULL values occur in the column, to
		-- accomodate 'NULL'. The convert() to varchar
		-- is used to determine the length of
		-- non-varchar data.
		--
		--  if(int1==int2 and int1,int2 > 0)
		-- 	=>  sign(int1/int2) * sign (int2/int1) = 1

		select @sqlstr = @sqlstr +
		"isnull(max(isnull(char_length("
		+ "convert(varchar("
		+  convert(varchar,@collength) + "),"
		+ @colname  + ")"  + "),4)),1)"
		+ " *sign(_clid#af/" + convert(varchar(4),@colid) +
		")*sign (" + convert(varchar(4),@colid) + "/_clid#af) +"	

		fetch curcolumns into @colname, @type, @collength,@colid


	end	-- }	while (@@sqlstatus = 0)

	close curcolumns

	deallocate cursor curcolumns

	select @whoami_sp = @whoami + '(2)'

	-- finalize the INSERT for EI call
	select  @sqlstr = @sqlstr + "0" + " FROM #colinfo_af," 
			+ @fulltabname + " " + @whereclause

	if (@trace >= @trace_dumplists)
	begin
		select @sqlstr
	end

	exec(@sqlstr)

	select @retval = @@error
	if (@retval != 0)
	begin
		raiserror 19206, @whoami_sp, @sqlstr
		goto error_exit
	end

	/*
	** temp table has duplicate set of rows now. fix maxlength values
	** and get rid of duplicate part of the table.
	*/
	update #colinfo_af
	set _maxlen#af = c2._maxlen#af,
	_auto#af = 1,
	_mbyte#af = sign(charindex(#colinfo_af._usrtype#af,@mbyte_char_str))
	from #colinfo_af , #colinfo_af c2
	where #colinfo_af._clname#af = c2._clname#af
	and c2._maxlen#af > 0		-- rows inserted by EI
	and #colinfo_af._maxlen#af = 0	-- initial set or rows

	delete #colinfo_af where _clid#af < 0

	-- Numeric values need to be right-justified. At this point, we have
	-- determined the maximum length for each column based on the value contents,
	-- but that will still lead to incorrect formatting when the column name 
	-- is longer than this maximum length. Therefore, set the max. length of
	-- the formatted column to the column name length if the latter is larger.
	update #colinfo_af
	set _maxlen#af = char_length(_asname#af)
	where _maxlen#af < char_length(_asname#af)

	if (@trace >= @trace_temptable)
	begin
		select * from #colinfo_af
	end

	/*
	** ****************************************************************
	** Go back and process the #temp table, extracting out each column
	** and generate a SQL statement to account for the max-lengths of
	** columns that need auto-formatting. If the user had given us a
	** SELECT list, then only pick those columns. Otherwise, pick all
	** columns (select *).
	*/
	select 	  @sqlstr = "SELECT"
		, @sel_colnum = 1

	declare curcolumns cursor for
	select _clname#af, _maxlen#af, _auto#af, _asname#af, _mbyte#af, _type#af
		, _colen#af
	from #colinfo_af
	where _slc#af = 1
	order by _sorder#af

	open curcolumns

	fetch curcolumns into     @colname, @maxlength, @autoformat
				, @asname , @mbyte, @type, @collength

	while (@@sqlstatus = 0)
	begin
		select @sqlstr = @sqlstr
				+ case @sel_colnum when 1 then "" else ", " end

		select @sel_colnum = @sel_colnum + 1

		if (@autoformat = 1)
		begin
			select @sqlstr = @sqlstr
				+ @asname + '=' +
				case when @type in (39,   -- char, nchar                          
						    47,   -- varchar, [long]sysname, nvarchar     
						    135,  -- unichar                              
						    155)  -- univarchar                           
				then
					-- Expect to handle all potentially long, character
					-- datatypes here
					"SUBSTRING(convert(varchar("+convert(varchar,@collength)+"),"  
						+ @colname
						+ "),1,"
						+ case @mbyte
							 when 0
							 then convert(varchar, @maxlength)
							 else convert(nvarchar, @maxlength)
						  end
						+ ")"
	  			else 
					-- We need to right-adjust the integer datatypes; since this
					-- will not display NULL values as 'NULL' anymore due to the 
					-- string concatenation, we need to explicitly stick in 'NULL'.
					-- Note that 80 characters is enough for all integer datatypes.
					"right(space(80)+isnull(convert(varchar(80),"					  
						+ @colname
						+ "),'NULL')," + convert(varchar, @maxlength) + ")"
				end
		end
		else
		begin
			-- Only generate an AS-name clause when the AS-name
			-- is known to be different than the column name.
			--
			select @sqlstr = @sqlstr
					+ case @asname
					    when @colname then NULL
					    else @asname + '='
					  end
					+ @colname
		end

		fetch curcolumns into     @colname, @maxlength, @autoformat
					, @asname , @mbyte, @type, @collength
	end

	close curcolumns

	deallocate cursor curcolumns

	-- Append the FROM list for the select from the table.
	--
	select @sqlstr =  @sqlstr 

			-- Go back to using the full table name as the
			-- user passed to us. #temp tables were processed
			-- earlier to generate the name that the user
			-- should have been using.
			--
			+ " FROM " + @fulltabname
			+ " " + @whereclause
			+ " " + @orderby
			+ " " + @fmtspecifier

	select @whoami_sp = @whoami + '(3)'
	if (@trace = 0)
	begin
		set rowcount @setrowcount
	end

	exec (@sqlstr)
	select @retval = @@error
	if (@retval != 0)
	begin
		raiserror 19206, @whoami_sp, @sqlstr
		goto error_exit
	end

	return 0

error_exit:
	return @retval
	
end
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_autoformat', 'anymode'
go
grant execute on sp_autoformat to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_remotesql')
begin
	drop procedure sp_remotesql
end
go
print "Installing sp_remotesql"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
*/
create procedure sp_remotesql
	@server varchar(255),	/* name of remote server */
	@query varchar(255)	/* statement to be executed on remote server */
/*
** The caller may supply up to 250 additional arguments of type
** char or varchar.  These will be concatenated to the end of the
** query buffer initialized by the @query arg.  This query buffer
** is passed directly to server '@server', where it is executed.
** Any and all results are passed directly back to Omni's client.
*/
as
	if @@error > 0
		return @@error
go
exec sp_procxmode 'sp_remotesql', 'anymode'
go
grant execute on sp_remotesql to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_check_remote_tempdb')
begin
	drop procedure sp_check_remote_tempdb
end
go
print "Installing sp_check_remote_tempdb"
go

/*
** Messages for sp_check_remote_tempdb
**
** 19818, "Local temporary database '%1!' is skipped for this operation. The
**         database is accessible from the owner instance '%2!' only."
** 19820, "The database '%1!' is only accessible from the owner instance 
**	   '%2!'. Please execute the procedure on that instance.
*/

/*
** Description
**      It checks if the database is a local tempdb owned by a remote
**	instance and print msg depending on the action requested. 
**
** Parameters
**      @dbid	- Database id
**	@action - 'skip' or 'reject'. Depending on the value it
**		  will raise a skip or reject warning. Any other
**		  value will avoid printing any message.
** Returns
**      1       - Database is local tempdb owned by remote instance. 
**      0       - Otherwise
*/
create procedure sp_check_remote_tempdb 
@dbid int, 
@action sysname = NULL
as
begin
	declare @instanceid int, 
		@instancename sysname,
		@dbname varchar(255),
		@error int,
		@msg varchar(1024)

	if (@@clustermode = 'shared disk cluster')
	begin
   		select @instanceid = isnull(db_instanceid(@dbid), 0)
   		if (@instanceid > 0 and @instanceid != @@instanceid)
   		begin
			if (@action = 'skip' )
				select @error = 19818
			else if (@action = 'reject')
				select @error = 19820
			else
				select @error = 0

			if (@error != 0)
			begin
				select @dbname = db_name(@dbid)
				select @instancename = 
					instance_name(@instanceid)

        			exec sp_getmessage @error, @msg output
				print " "
        			print @msg, @dbname, @instancename
			end

			return 1
   		end
	end

	return 0
end 
go
exec sp_procxmode 'sp_check_remote_tempdb', 'anymode'
go
grant execute on sp_check_remote_tempdb to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_configure')
begin
	drop procedure sp_configure
end
go
print "Installing sp_configure"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/configure */

/*
** Messages for "sp_configure"          17410
**      Must use "langid" when referencing spt_values
**
** 17260, "Can't run %1! from within a transaction." 
** 17410, "Configuration option doesn't exist."
** 17411, "Configuration option is not unique."
** 17413, "The value of the 'number of devices' must not be less than the number of active devices '%1!'
** 17414, "You can't set the default language to a language ID that is not defined in Syslanguages."
** 17415, "Configuration option value is not legal."
** 17418, "'%1!' is an invalid file command. The valid commands are 'verify', 'read', 'write', and 'restore'."
** 17419, "Configuration option changed. The SQL Server need not be rebooted since the option is dynamic.
** 18123, "Configuration option changed. The SQL Server must be rebooted before the change in effect since the option is static."
** 18124, "No matching configuration options.  Here is a listing of groups:"
** 18125, "Must provide the parameter 'filename'."
** 18133, "The character set, '%1!', is invalid since it is not defined in Syscharsets."
** 18134, "The sortorder, '%1!', is invalid since it is not defined in Syscharsets."
** 18397, "Changing the value of '%1!' does not increase the amount of 
**        memory Adaptive Server uses.
**
** 18549, "Invalid third argument supplied: '%1!'. Valid choices are
**	   'with truncate' or 'default'."
**
** 18915, "An additional %1! K bytes of memory is available for 
** 	  reconfiguration. This is the difference between 'max memory' 
**	  and 'total logical memory'."
**
** 18916, "Changing the value of '%1!' to '%2!' increases the amount of
** 	  memory ASE uses by %3! K."
**
** 18917, "Changing the value of '%1!' to '%2!' reduces the amount of
** 	  memory ASE uses by %3! K. The reduced memory may be reused
**	  when this configure value changes, but will not be released
**	  until ASE restarts."
**
** 18932, "Resulting configuration value and memory use have not changed 
**	  from previous values: new configuration value %1!, previous %2!."
**
** 19106, "Cannot change the value of configuration parameter 'global cache 
**	  partition number' when the server is in recovery."
** 
** 19107, "Cannot change the value of configuration parameter 'max concurrently 
**	  recovered dbs' because the server is still in recovery setup."
**
** 19108, "Cannot change the configuration parameter 'max concurrently
**	   recovered dbs' to %1 when the server is in recovery. The only value 
**	   allowed is 1.
**
** 19109, "Cannot change the value of configuration parameter 'global async
**	  prefetch limit' when the server is in recovery."
**
** 19416, "Provider class '%1!' is not a recognized messaging provider class."
**
** 19519, "Cannot run sp_configure for server '%1!' since you are not
**	  connecting to it." 
**
** 19520, "Cannot configure '%1!' for an instance, since it is a strictly 
**	  cluster-wide option." 
**
** 19521, "Cannot configure '%1!' to cluster-wide since all active instances 
**	  have instance-specific setting on this option."
**
** 19570, "Cannot drop the instance-specific configuration for configuration
**	  parameter '%1!' since the configuration setting does not exist."
**
** 19574, "An instance name needs to be provided. "
**
** 19654, "Warning: In Shared Disk Cluster, all instances share the same 
**	  configuration file. Please run sp_configure to read the configuration 
**        file for all other instances to keep the configuration consistent."
** 19816, "You cannot set configuration values from inside a local temporary
**	  database."
** 19874, "Cannot configure '%1!' to cluster-wide since it is an 
**	  instance-specific-only option."
** 19953, "Cannot change the value of configuration parameter 'config file 
**	  version' because it is server generated."
**
** 19961, "WARNING: Compatibility mode will not be used when 'abstract plan dump/load/replace' is on."
** 19962, "WARNING: Compatibility mode may not be used when statement cache and literal autoparam are enabled."
** 19966, "WARNING: Enabling compatibility mode will not affect the query plans already stored in the procedure cache."
** 19967, "WARNING: The configuration option 'statement cache size' is configured with value '%1!'. Enabling compatibility mode will not affect the query plans already stored in the statement cache."
*/

create procedure sp_configure
@configname varchar(255) = NULL,	/* configure option name */
@configvalue int = NULL,		/* configure value */
@configvalue2 varchar(255) = NULL,	/* config file command/charset info */
@configvalue3 varchar(255) = NULL	/* physical name of file */
as

declare @confignum int			/* number of option to be configured */
declare @configcount int		/* number of options like @configname */
declare @whichone	int		/* using english or default lang ? */
declare @cmd		smallint	/* configuration file command */
declare @status int			/* return status for misc calls */
declare @children int			/* number of children in a group */
declare @parent int			/* config number of parent group */
declare @msg varchar(1024)		/* temp buffer for messages */
declare @sysconfig smallint		/* contents of sysconfigures.config */
declare @sysname varchar(255)		/* contents of sysconfigures.comment */
declare @sysparent smallint		/* contents of sysconfigures.parent */
declare @sysstatus int			/* contents of sysconfigures.status */
declare @value int 			/* default charset/sort order id */
declare @user_displaylevel int		/* user display level */
declare @numdevices int			/* number of active devices */
declare @sorder_chset_id int            /* current sortorder or character set id */
declare @use_wildcard tinyint           /* use wildcard to search option name or not */
declare @match_count int                /* number of option found by name match */
declare @cmpstate     	int         	/* Local NODE state in companionship */
declare @additional_free_memory	 int    /* Additional Free memory */
declare @logical_memory	 int            /* total logical memory before 
					   change*/
declare @lmemconfignum int		/* confignum for 'total logical memory' */
declare @additional_memory	 int    /* increase in logical memory due 
					   to change*/
declare	@oldcfgvalue		int	/* 
					** previous config value for parameter
					** with integer type.
					*/
declare @oldcfgvalue_char	varchar(255)
					/*
					** previous config value for parameter
					** with character type.
					*/
declare @defvalue	varchar(255)	/* default config value */
declare @fullconfigname varchar(255) 	/* configure option name */
declare @bvalue     	int         	/* base value after unit 
					   converting */
declare @unit		varchar(20)
declare @nocase         tinyint         /* case-sensitive sort order flag */
declare @rec_state	varchar(30)	/* the server recovery state */
declare @new_class	smallint	/* for valid messaging provider
					** class
					*/
declare @is_equal       int             /*
					** flag to check whether configuration
					** value and run value are same or not.
					*/ 
declare @configcount2	int		/* number of options for an instance. */
declare @configcount3	int		/* number of options for an instance. */
declare @match_count2	int  		/* number of option found by name and
					** instance match.
					*/
declare @instanceid	tinyint		/* instance id */
declare @use_cluster	int		/* if cluster-wide value is used. */
declare @remote_instance_name	varchar(255)
					/* remote instance name */
declare @remote_instance_id	tinyint
					/* remote instance id */
declare @retstat	int
declare @sqlbuf		varchar(255)

declare @non_default_options int  	/* this option is set when nondefault
					   settings  are to be displayed */
declare @tmp_rtms_value  int           /* to store the value of 'enable real time messaging'*/
declare @all_rtms_provider_set int 	/* to store bit map while all rtms provider enabled*/
declare @cfg_rtms_provider_mask int 	/* to check if the required rtms provider enabled */	
declare @cfg_rtms_all_mask     int   	/* to check if all options of rtms enabled */ 					
declare @optlevel_def	varchar(20)	/* default value for optlevel */
declare @optlevel_run	varchar(20)	/* run value for optlevel */
declare @optlevel_curr	varchar(20)	/* current value for optlevel */

declare @config_value_to_check int	/* value of config option to be 
					** checked with compatibility mode.
					*/

select @whichone = 0
select @status = 0
select @cmd = 1
select @value = NULL
select @user_displaylevel = NULL
select @sorder_chset_id = 0
select @is_equal = 0
select @use_wildcard = 1
select @config_value_to_check = NULL
select @use_cluster = 0
select @instanceid = NULL

/*
** Check if the default sort order is case-insensitive.
*/
if ("A" = "a")
        select @nocase = 1
else
        select @nocase = 0

/*
**  Disallow running sp_configure within a transaction since it might make
**  recovery impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
		raiserror 17260, "sp_configure"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1
set nocount on

/*
** Prepare values for'optimizer level'.
*/
select * into #optlevel 
from master.dbo.spt_values where type = 'OL'
and name like 'ase%'

select @optlevel_def = name
from master.dbo.syscurconfigs , #optlevel
where config = 507
and number = convert(int,defvalue)

select @optlevel_run = name
from master.dbo.syscurconfigs , #optlevel
where config = 507
and number = convert(int,value2)

select @optlevel_curr = name
from master.dbo.syscurconfigs , #optlevel
where config = 507
and number = convert(int,value)

/*
**      If the "default sortorder" is case insensitive dictionary sort order,
** the procedure will just print out all the options and their values
** without grouping if no option name is given.
*/
if (@nocase = 1 and @configname is NULL)
begin
	/* Display all config parameters for specified instance. */
	if @configvalue3 is not NULL
	begin

		begin 
			select "Parameter Name" = convert(char(30), name), 
			       "Default" = CASE WHEN b.config = 507 THEN @optlevel_def
			       ELSE convert(char(11), 
				 space(11-char_length(
				 convert(varchar(11), defvalue))) + 
				 convert(varchar(11), defvalue))
				 END,
			       "Memory Used" = convert(char(11), 
				 space(11-char_length( 
				 convert(varchar(11), c.comment))) + 
				 convert(varchar(11), c.comment)), 
			       "Config Value" = CASE WHEN b.config = 507 THEN @optlevel_curr
			       ELSE convert(char(12), 
				 space(12-char_length( 
				 isnull(b.value2, 
				 convert(char(32), b.value)))) + 
				 isnull(b.value2, convert(char(32), b.value)))
				 END,
			       "Run Value" = CASE WHEN b.config = 507 THEN @optlevel_run
			       ELSE convert(char(12), 
				 space(12-char_length(isnull(c.value2, 
				 convert(char(32), c.value)))) + 
				 isnull(c.value2, convert(char(32), c.value)))
				 END,
			       "Unit" = convert(char(20), c.unit),

				"Type" = convert(char(20), c.type)

			from master.dbo.sysconfigures b, 
			     master.dbo.syscurconfigs c 
			where 

			b.config *= c.config 
			and b.config != 19 
			and parent != 19 

			
			return (0) 
		end 
	end



	return (0)
end




/* check whether nondefault settings are to be displyed.*/
if (@configname is not NULL)
begin

	if "display nondefault settings" like "%" + @configname + "%"
	begin
		declare @countno int
	
		/*check if configuration option is unique*/
		
		select @countno = count(*)
		from master.dbo.sysconfigures
		where name like "%" + @configname + "%"
		  and parent != 19


		/*
		** if configuration option is not unique, display the duplicates
		** and return
		*/	
		if @countno > 0
		begin
				
			select name
			into #temptab		
			from master.dbo.sysconfigures a
			where name like "%" + @configname + "%"
	   	      	      and parent != 19
			
			insert into #temptab values 
			("display nondefault settings")
				
			raiserror 17411
			print ""
			print "Choose option from the following"
			print ""
			exec sp_autoformat #temptab
			return(1)
		end		
		/*
		** if configuration option is unique set non_default_options=1, 
		** and make configname=NULL so that next block is bypassed
		*/	
		else
		begin	
			select @non_default_options = 1
			select @configname = NULL	
		end

	end
end
	
/* Validate the configname if it not NULL */
if @configname is not NULL
begin
	/* Check the duplicate rows for cluster-wide settings. */ 
	select @configcount = count(*) 
		from master.dbo.sysconfigures 
			where name like "%" + @configname + "%" 
			and parent != 19


        /*
        **      If configure option is not unique and case-insensitive
        ** dictionary sort order is used, check if unique option found
        ** by exact name match, if so, then disable wildcard match
        ** for searching option name.
        */
        if ((@configcount > 1 

		)
		and @nocase = 1)
 

        begin
                /* check if unique option found by exact name match */
                select @match_count = count(*)
                        from master.dbo.sysconfigures
                                where name = @configname
                                and parent != 19

		
                if (@match_count = 1

		) 
                begin
                        select @use_wildcard = 0  /* don't use wildcard */

			if @match_count = 1
			begin
                        	select @configcount = @match_count
			end


                end
        end

	/*
	** If more than one option like @configname,
	** show the duplicates and return.
	*/
	if @configcount > 1

	begin
		/*
		** 17411, "Configuration option is not unique."
		*/
		raiserror 17411
		print ""

               select "Parameter Name" = convert(char(30), name),
                        "Default" = CASE WHEN a.config = 507 THEN @optlevel_def
				ELSE convert(char(11), space(11-char_length(
                                    convert(varchar(11), defvalue)))+
                                    convert(varchar(11), defvalue))
				END,
                        "Memory Used" = convert(char(11), space(11-char_length(
                                        convert(varchar(11), b.comment)))+
                                        convert(varchar(11), b.comment)),
                        "Config Value" = CASE WHEN a.config = 507 THEN @optlevel_curr
				ELSE convert(char(12), space(12-char_length(
                          isnull(a.value2, convert(char(32), a.value)))) +
                          isnull(a.value2, convert(char(32), a.value)))
				END,
                        "Run Value" = CASE WHEN a.config = 507 THEN @optlevel_run
				ELSE convert(char(12), space(12-char_length(
                          isnull(b.value2, convert(char(32), b.value)))) +
                          isnull(b.value2, convert(char(32), b.value)))
				END,
			"Unit" = convert(char(20), b.unit),

			"Type" = convert(char(10), b.type)
			

		from master.dbo.sysconfigures a,
			master.dbo.syscurconfigs b
		where 

			    a.config *= b.config
			and name like "%" + @configname + "%"
			and parent != 19
			and a.config != 19

		order by name

		/*
		**  If @configname like '%memory%' print message. 
		**  18915, "An additional %1! K bytes of memory is available 
		**  for reconfiguration. This is the difference between 
		**  'max memory' and 'total logical memory'."
		**
		*/
		if (lower(@configname) like '%memory%')
		begin
			select 	@additional_free_memory = 
					(max(b.value) - min(b.value)) * 2 
			from 	master.dbo.sysconfigures a,
				master.dbo.syscurconfigs b
			where 	a.name in ('max memory', 
					   'total logical memory')

			and	a.config = b.config


			exec sp_getmessage 18915, @msg output
			print @msg,@additional_free_memory
		end	
		return (1)
	end
	
	/*
	** if it is a valid option and the @configvalue is not NULL,
	** set the option
	*/
	if (@configcount != 0) and (@configvalue is not NULL)
	begin
		/* set @confignum */
		select	@confignum = config,
			@sysstatus = status,
			@fullconfigname = name
			from master.dbo.sysconfigures
				where name like "%" + @configname + "%"
				and parent != 19
				and config != 19

		/* Disallow running sp_configure on "config file version". */ 
		if (@confignum = 504) 
		begin 
			/* 
			** 19953, "Cannot change the value of configuration 
			** parameter 'config file version' because it 
			** is server generated." 
			*/ 
			raiserror 19953 
			return (1) 
		end



		/*
		** Later, we will want to test whether the config value is
		** actually changing.  Obtain the current and default values
		** for this config so we can ignore requests that result in
		** no change.  Here, if the parameter datatype is (var)char,
		** @oldcfgvalue will be 0; if it's an int, @oldcfgvalue_char
		** will be NULL.
		*/
		select	@oldcfgvalue = b.value,
			@oldcfgvalue_char = b.value2,
			@defvalue = c.defvalue
			from master.dbo.sysconfigures b,
			     master.dbo.syscurconfigs c
				where b.config = @confignum

		  		and b.config *= c.config


		/* 
		** The @oldcfgvalue could be NULL if this is the 
		** first time configuration of an instance value.  
		** If this is the case, get the @oldcfgvalue from 
		** the cluster-wide settings.  
		*/ 
		if @oldcfgvalue is NULL 
		begin 
			select @oldcfgvalue = b.value,
			       @oldcfgvalue_char = b.value2,
			       @defvalue = c.defvalue
				from master.dbo.sysconfigures b, 
			     	     master.dbo.syscurconfigs c 
					where b.config = @confignum 

					and b.config *= c.config 

		end


 		if (@configvalue2 = "default")
		begin
			select @value = 1
			if @oldcfgvalue_char is null
				select @configvalue = convert(int, @defvalue)
		end
		else
			select @value = 0

		/*
		**  If the option name is "configuration file",
		**  take action, then return.
		*/
		if @confignum = 114
		begin
			/*
			** if the file command is not one of the valid
			** commands, complain and then quit.
			*/
			if @configvalue2 not in ("read", "write", "restore",
						 "verify")
			begin
				/*
				** print the message to show the valid
				** file command
				*/
				raiserror 17418, @configvalue2
				return(1)
			end

			/*
			** if filename is NULL
			*/
			if (@configvalue3 is NULL)
			begin
				/* 18125, "Must provide the parameter 'filename'." */
				raiserror 18125
				return(1)
			end

			/*
			** Must have sa_role to run these commands 
			*/
       			if (proc_role("sa_role") < 1)
			begin
				return(1)
			end

			select @cmd = case
			   when (@configvalue2 = "verify") then 2
			   when (@configvalue2 = "read"  ) then 3
			   when (@configvalue2 = "write" ) then 4
			   else 5	-- "restore"
			end


			select @status = config_admin(@cmd,0,0,0,NULL,
						@configvalue3)

			if (@status = 1)
			begin
        			return(0)
			end

			return (1)
		end

		if @confignum = 123
		begin
			/* get current default charset id */
			select @value = value from
				master.dbo.sysconfigures
				where config = 131
		
			select @sorder_chset_id = @value
			if @configvalue2 is not NULL
			begin
				/*
				** Get default charset id from name and
				** validate the charset id.
				*/
				select @value = id
					from master..syscharsets
					where name = @configvalue2 
					and type between 1000 and 1999

				if @value is null
				begin
					/* 18133, "The character set, '%1!', is invalid since it 
					** is not defined in Syscharsets."
					*/
					raiserror 18133, @configvalue2
					return (1)
				end
			end
		end

		else
		if @confignum = 131
		begin
			/* get current default sortord id */
			select @value = value from
				master.dbo.sysconfigures
				where config = 123

			select @sorder_chset_id = @value
			if @configvalue2 is not NULL
			begin
				/*
				** Get default sortorder id from name and
				** validate the sortord id.
				*/
				select @value = id
					from master..syscharsets
					where name = @configvalue2
					and type between 2000 and 2999

				if @value is null
				begin
					/* 18134, "The sortorder, '%1!', is invalid since it 
					** is not defined in Syscharsets."
					*/
					raiserror 18134, @configvalue2
					return (1)
				end
			end
		end

		/*
		** If an attempt to enable a disk mirroring is made, and
		** if this happens to be a server with HA services turned
		** on, we disallow. Currently we do not support ASE HA
		** services along with sybase mirroring.
		*/
		if (@confignum = 140 and @configvalue = 0)
		begin
			select @cmpstate = @@cmpstate
			if @cmpstate >= 0
			begin
				/* 18816 Mirroring not allowed in ASE HA */
				raiserror 18816
				return(1)
			end
		end
		
		/*
		** If an attempt to disable disk mirroring is being made,
		** ensure that there are no devices that are currently
		** being mirrored.
		*/
		else
		if (@confignum = 140 and @configvalue = 1)
		begin
			if (select count(*) from master.dbo.sysdevices
				where status & 512 = 512) > 0
			begin

			  /* 18750, Unable to disable disk mirroring
			  ** because some devices are currently
			  ** mirrored. Use 'disk unmirror' to
			  ** unmirror these devices and then
			  ** re-run this sp_configure command.
			  */

			  raiserror 18570
			  return (1)
			end
		end

		/* 
		**  If this is the number of current audit table we want
		**  to make sure that if "with truncate" option is not 
		**  provided new table is empty other wise fail.
		*/
		else
		if @confignum = 260
		begin
			if @configvalue2 is not NULL
			begin
				if (@configvalue2 not in ("with truncate", 
								"default"))
				begin
					/*
					** 18549, "Invalid third argument
					**         supplied: '%1!'. Valid
					**	   choices are 'with truncate'
					**	   or 'default'."
					*/
					raiserror 18549, @configvalue2
					return(1)
				end
			end
			else
			begin
				select @value = 2
			end
		end

		/*
		** global cache partition number
		*/
		else
		if  @confignum = 337
		and @configvalue is not NULL
		begin
			select @rec_state = @@recovery_state
			if (@rec_state not like "NOT_IN_RECOVERY%")
			begin
				raiserror 19106
				return(1)
			end

			/*
			** Partition number must be a power of 2
			** between 1 and 128.
			*/
			if (@configvalue not between 1 and 128)
			or (@configvalue & (@configvalue - 1) != 0)
			begin
				raiserror 18611
				return(1)
			end
		end

		/*
		** If this is to change the number of maximum concurrently
		** recovered dbs, check to make sure that the server is
		** not currently in the tuning process. We don't allow
		** change to this config parameter if the server is in
		** tuning process.
		** If the server is still in recovery process, the only value
		** that the config parameter may be changed to is 1, which is
		** to change back to do serial recovery.
		*/
		else
		if @confignum = 415
		begin
			select @rec_state = @@recovery_state
			if (@rec_state like "RECOVERY_TUNING%")
			begin
				raiserror 19107
				return (1)
			end
			else if (@rec_state not like "NOT_IN_RECOVERY%" and
				 @configvalue != 1)
			begin
				raiserror 19108, @configvalue
				return (1)
			end

		end

		/*
		** If the config parameter is "global async prefetch limit",
		** do not allow this change if server is in recovery process.
		*/
		else
		if @confignum = 303
		begin
			select @rec_state = @@recovery_state
			if (@rec_state not like "NOT_IN_RECOVERY%")
			begin
				raiserror 19109
				return(1)
			end
		end

		/*
		** If configure parameter is "enable real time messaging",
		** check @configvalue2
		**
		**	- null means enable for all supported messaging
		**	  on that platform.
		**	- 'TIB_JMS' means enable/disable for TIBJMS only.
		**	- 'IBM_MQ' means enable/disable for IBM MQ only.
		**	- 'EAS_JMS' means enable/disable for EASJMS only.
		**  	- 'SONICMQ_JMS' means enable for SONICMQ_JMS only.
		**
		** @configvalue will be changed to a bit mask.
		*/
		if (@value != 3) and (@confignum = 429)
		begin
			if (@configvalue2 is not null)
			begin
				/* Get the class number */
				select @new_class = number
					from master.dbo.spt_values
					where lower(name) = lower(@configvalue2)
					      and type = 'X'

				/* Unrecognized provider class */
				if @@rowcount = 0
				begin
					raiserror 19416, @configvalue2
					return(1)
				end
				
				/* Not a supported provider class */
				if (@new_class != 12) and (@new_class != 13)
				    and (@new_class != 14) and (@new_class != 15)
				begin
					raiserror 19416, @configvalue2
					return(1)
				end
			end			
			
			/* Get the rtms provider mask */
			select @cfg_rtms_all_mask = number
				from master.dbo.spt_values
				where lower(name) = 'all providers'
					and type = 'RT'

			select @all_rtms_provider_set = sum(number)
				from master.dbo.spt_values
                                where type = 'RT'
					and low = 1
			select @all_rtms_provider_set = @all_rtms_provider_set 
							+ @cfg_rtms_all_mask

			if (@configvalue2 is not null)
			begin
				select @cfg_rtms_provider_mask = number
					from master.dbo.spt_values
					where lower(name) = lower(@configvalue2)
					and type = 'RT'
					and low = 1
				/* Not a supported RTMS provider */
				if (@cfg_rtms_provider_mask is null)
				begin
					raiserror 19416, @configvalue2
                                        return(1)
				end
			end
			else if (@configvalue != 0)
			begin
				select @cfg_rtms_provider_mask = @cfg_rtms_all_mask
			end
			else 
			begin
				select @cfg_rtms_provider_mask = @all_rtms_provider_set
			end
		end
	
		/*
		** Raise warning messages if abstract plan 
		** dump/load/replace, literal autoparam or
		** statement cache are already on when 
		** compatibility mode is being enabled.
		*/
		if (@confignum = 502 and @configvalue = 1)
		begin
			/* Raise warning message 19966 */
			exec sp_getmessage 19966, @msg output
			print @msg 
		
			/*
			** Raise warning message 19961 if abstract 
			** plan dump/load/replace is already on. 
			*/
			if exists (select * 
				   from  master.dbo.sysconfigures
				   where config in (383, 384, 385)
				   	 and value = 1)
			begin
                                exec sp_getmessage 19961, @msg output
                                print @msg 
			end
	
			/*
			** Raise warning message 19967 if  
			** statement cache is already on. 
			*/
			select @config_value_to_check = value 
			from  master.dbo.sysconfigures
			where config = 414 

			if (@config_value_to_check is not NULL 
			    and @config_value_to_check != 0)
			begin
                                exec sp_getmessage 19967, @msg output
                                print @msg, @config_value_to_check

				/*
				** Raise warning message 19962 if  
				** literal autoparam is already on. 
				*/
				if exists (select * 
					   from  master.dbo.sysconfigures
					   where config = 462 
					   	 and value = 1) 
				begin
                                	exec sp_getmessage 19962, @msg output
                                	print @msg 
				end
			end

			/*
			** Raise warning message if the value of  
			** histogram tuning factor is not 1, the   
			** default value in ASE 12.5. 
			*/
			select @config_value_to_check = value 
			from  master.dbo.sysconfigures
			where config = 433 

			if (@config_value_to_check is not NULL 
			    and @config_value_to_check != 1)
			begin
				exec sp_getmessage 19965, @msg output
        			print @msg,  @config_value_to_check 
			end

		end

		/*
		** Raise warning messages if compatibility mode 
		** is already on when abstract plan dump/load/replace
		** or literal autoparam is being enabled.
		*/
		if exists (select * 
			   from  master.dbo.sysconfigures
			   where config = 502 and value = 1) 
		begin
			/*
			** Check if abstract plan dump/load/replace
			** is being enabled.
			*/
			if ((@confignum = 383 or 
		     	     @confignum = 384 or 
		     	     @confignum = 385) and 
		    	     @configvalue = 1)
			begin
                                exec sp_getmessage 19961, @msg output
                                print @msg 
			end
		
			/*
			** Check if literal autoparam is being enabled.
			** Note that literal autoparam itself is not
			** a problem but the combination of both
			** statement cache and literal autoparam will
			** have some effect. 
			*/
			if (@confignum = 462 and @configvalue = 1) 
			begin
				/* if statement cache is also on */
				if exists (select * 
					   from  master.dbo.sysconfigures
					   where config = 414 
					   	 and value != 0)
				begin
                               		exec sp_getmessage 19962, @msg output
                                	print @msg 
				end
			end

			/*
			** Check if statement cache is being enabled 
			** because we may have literal autoparam 
			** enabled already. In that case, we need to 
			** raise warning message for literal autoparam
			** as above too. 
			*/
			if (@confignum = 414 and @configvalue != 0) 
			begin
				/* if literal autoparam is already on */
				if exists (select * 
					   from  master.dbo.sysconfigures
					   where config = 462
					   	 and value = 1 ) 
				begin
                                	exec sp_getmessage 19962, @msg output
                                	print @msg 
				end
			end
		end

		/* get @logical_memory */
		select 	@lmemconfignum = config
		from 	master.dbo.sysconfigures
		where 	name = 'total logical memory'


		select 	@logical_memory = value 
		from 	master.dbo.syscurconfigs
		where 	config = @lmemconfignum


		select	@unit = unit
		from	master.dbo.syscurconfigs
		where	config = @confignum	


		/* optimizer level */
		if (@confignum = 507)
		begin
			select @configvalue = number from master.dbo.spt_values
			where type = 'OL' and name = @configvalue2
		end
		/*
		** If configure value is 0, looking for the value
		** in configvalue2. As "default character set id" and
		** "default sortorder_id" can be changed together, if
		** @configvalue is 0 in this case, we will get syntax
		** error. So for such parameters where @unit is "id", 
		** we will not check value of configvalue2.
		*/
		if (@configvalue = 0
		and @configvalue2 is not NULL
		and @confignum != 507
		and @configvalue2 not in("default", "read", "write", "restore",
					"verify", "with truncate"

					)
		and @unit not in ("name", "not applicable", "switch")
		and (@unit != "id" or @confignum in (124, 168)))
		begin
			/* convert "pPkKmMgG" to equivalent "k" units */
			exec @status = sp_aux_getsize @configvalue2, @bvalue output

			if @status = 0
			begin
				/* Invalid syntax */
				return(1)
			end

			/* sp_aux_getsize returns value in K unit. */
			/*
			** If we are updating max memory, do the conversion
			** to 2k-pages ourselves
			*/
			if @confignum = 396
			begin
				select @configvalue = @bvalue / 2
			end
			else
			begin
				select @bvalue = @bvalue * 1024

				/* 
				** normalize it according to its unit and put
				** back to @configvalue. 
				*/
				select @configvalue = config_admin(20, 
					@confignum, @bvalue, 0, NULL, NULL)

			end
		end

                /*
                **  If this is the number of default language, we want
                **  to make sure that the new value is a valid language
                **  ID in Syslanguages.
                */
                if @confignum = 124
                begin
                        if not exists (select *
                                from master.dbo.syslanguages
                                        where langid = @configvalue)
                        begin
                                /* 0 is default language, us_english */
                                if @configvalue != 0
                                begin
                                        /* 17414, "You can't set the default 
					** language to a language ID that is
					** not defined in Syslanguages."
                                        */
                                        raiserror 17414
                                        return (1)
                                end
                        end
                end


		/*
		** If this is the number of devices configuration
		** parameter, we want to make sure that it's not being
		** set to lower than the number of devices in sysdevices.
		*/
		if @confignum = 116
		begin
			/*
			** Get the number of devices.
			*/
			select @numdevices = count(*)
			from master.dbo.sysdevices
			where status & 2 = 2

			if (@configvalue < @numdevices)
			begin
				/* 17413, "The value of the 'number of 
				** devices' must not be less than the number
				** of active devices '%1!'
				*/
				raiserror 17413, @numdevices
				return (1)
			end
		end

		/*
		** Before changing the config value, if this parameter
		** is "number of open databases", make sure it cannot
		** be reduced during recovery.
		*/
		if @confignum = 105
		begin
			select @rec_state = @@recovery_state
			if ((@rec_state not like "NOT_IN_RECOVERY%") and
				(@configvalue < @oldcfgvalue))
			begin
				raiserror 19114
				return(1)
			end
		end

		/*
		** Now we're done checking for @configvalue2 = "default", so
		** we can modify it.  If this is a char param and @configvalue2
		** is "default", reset it to be the actual default.
		*/
		if  @configvalue2 = "default"
		and @oldcfgvalue_char is not null
		begin
			select @configvalue2 = @defvalue
		end

		/*
                ** Check for parameter with integer and character datatype
                ** that if the new and old values for the configuration 
                ** parameter are same, then the value of configuration 
                ** parameter will not be changed. 
                */
		if ((@oldcfgvalue_char is NULL AND @configvalue = @oldcfgvalue)
		 OR (@oldcfgvalue_char is not NULL AND @configvalue2 = @oldcfgvalue_char))
		begin			
			/*
			** Now the old and new values for the first parameter
			** are same. But as "default sortorder id" and "default
			** character set id" both can be changed in sp_configure
			** together, check if the first parameter in sp_configure
			** is one of these and if the new and old values for the
			** second parameter are same, then value of both the
			** parameters should not be changed. The condition
			** mentioned below will always be true for other
			** configuration parameters or if only one configuration
			** parameter is given in sp_configure.
			*/
			
			if (@confignum not in (123, 131)) OR 
			   (@value = @sorder_chset_id)
			begin
				/* Set the @is_equal flag to true */
				select @is_equal = 1

			end
				
		end



		/*
		**If for 'enable real time messaging',  
		**We need to check the bitmap
		*/
		if (@value != 3) and (@confignum = 429)
		begin
			if (@oldcfgvalue = @cfg_rtms_all_mask)
				select @tmp_rtms_value = @all_rtms_provider_set
			else 
				select @tmp_rtms_value = @oldcfgvalue
			
			select @tmp_rtms_value = @tmp_rtms_value & @cfg_rtms_provider_mask
			/*
			** If @configvalue != 0, it means to enable RTDS. 
			** Set it as 1 
			*/
			if (@configvalue != 0) and (@configvalue != 1)
				select @configvalue = 1
			
			if (@configvalue != 0) and (@tmp_rtms_value !=0)
				select @is_equal = 1
			else if (@configvalue = 0) and (@tmp_rtms_value = 0)
				select @is_equal = 1
			else 
				select @is_equal = 0

			if (@is_equal = 1)
				select @configvalue = @oldcfgvalue			
		end
		
		
		
		
		/* 
		** If the new and old values are not the same, call
		** config_admin() to set the new value.  Otherwise just
		** set @status = 1 (success).
		*/
		select @status = case
               	   when (@is_equal = 1) then 1
		   else config_admin(@cmd, @confignum, 
					@configvalue, @value,

					NULL,

				@configvalue2) end
		/* if successful */
		if (@status = 1)
		begin
			if (@confignum = 507)
			begin
				select @optlevel_curr = @configvalue2,
					@optlevel_run = @configvalue2
			end
				
			/* Display the new value */
               		select "Parameter Name" = convert(char(30), name),
                        "Default" = CASE WHEN b.config = 507 THEN @optlevel_def
				ELSE convert(char(11), space(11-char_length(
                                    convert(varchar(11), defvalue)))+
                                    convert(varchar(11), defvalue))
				END,
                        "Memory Used" = convert(char(11), space(11-char_length(
                                        convert(varchar(11), c.comment)))+
                                        convert(varchar(11), c.comment)),
                        "Config Value" = CASE WHEN b.config = 507 THEN @optlevel_curr
				ELSE convert(char(12), space(12-char_length(
                          isnull(b.value2, convert(char(32), b.value)))) +
                          isnull(b.value2, convert(char(32), b.value)))
				END,
                        "Run Value" = CASE WHEN b.config = 507 THEN @optlevel_run
				ELSE convert(char(12), space(12-char_length(
                          isnull(c.value2, convert(char(32), c.value)))) +
                          isnull(c.value2, convert(char(32), c.value)))
				END,
			"Unit" = convert(char(20), c.unit),
			"Type" = convert(char(20), c.type)

			from master.dbo.sysconfigures b,
				master.dbo.syscurconfigs c
			where 
				b.config = @confignum and

				b.config *= c.config 


			/*
                        ** If the configuration value and run value are equal
                        ** then display a message that there will not be any
                        ** change in configuration parameter and exit.
                        */

                        if (@is_equal = 1)
                        begin
				if (@confignum = 507)
				begin
					select @configvalue2 = @optlevel_curr,
				   	   @oldcfgvalue_char = @optlevel_curr
				end
                                /*
                                ** 18932, Resulting configuration value
                                ** and memory use have not changed from
                                ** previous values: new configuration
                                ** value %1!, previous configuration %2!
                                */
                                exec sp_getmessage 18932, @msg output
				/* for integer datatype. */
                                if (@oldcfgvalue_char is NULL)
                                begin
                                        print @msg,  @configvalue, @oldcfgvalue
                                end
                                else
                                begin
                                /* for character datatype. */
                                        print @msg,  @configvalue2, @oldcfgvalue_char
                                end
                                return(0)
                        end

			/*
			** print reboot message if this option is not
			** dynamic.
			*/
			if ((@sysstatus & 8) = 8)
			begin
				exec sp_getmessage 17419, @msg output
				print @msg
			end
			else
			begin
				exec sp_getmessage 18123, @msg output
				print @msg
			end
			/*
			** Lets us calculate @additional_memory i.e. the 
			** increase in 'total logical memory'
			*/
			select 	@additional_memory = 
					(value - @logical_memory) * 2 
			from 	master.dbo.syscurconfigs
			where 	config = @lmemconfignum


			/*
			** print additional memory message 
			*/
			if (@additional_memory > 0)
			begin
				/*
				** 18916, Changing the value of '%1!' to '%2!' 
				** increases the amount of memory ASE uses 
				** by %3! K.
				*/
				if (@unit != "name")
				begin
					exec sp_getmessage 18916, @msg output
					print @msg,  @fullconfigname,
					      @configvalue, @additional_memory
				end
				else
				begin
					/* 
					** For configure options with name
					** as their units, they use 
					** configvalue2 (type of varchar)
					** to specify the intended value
					** insteading of configvalue (type
					** of int).
					*/
					exec sp_getmessage 18916, @msg output
					print @msg,  @fullconfigname,
					      @configvalue2, @additional_memory
				end
			end
			else if (@additional_memory < 0)
			begin
				/*
				** 18917, Changing the value of '%1!' to '%2!' 
				** reduces the amount of memory ASE uses 
				** by %3! K. The reduced memory may be
				** reused when this configure value changes,
				** but will not be released until ASE restarts.
				*/
				select @additional_memory = @additional_memory * -1 
				if (@unit != "name")
				begin
					exec sp_getmessage 18917, @msg output
					print @msg,  @fullconfigname, 
					      @configvalue, @additional_memory
				end
				else
				begin
					exec sp_getmessage 18917, @msg output
					print @msg,  @fullconfigname, 
					      @configvalue2, @additional_memory
				end
			end
			else
			begin
				/*
				** 18397, Changing the value of '%1!'
				** does not increase the amount of 
				** memory Adaptive Server uses.
				*/
				exec sp_getmessage 18397, @msg output
				print @msg,  @fullconfigname
			end

			return(0)
		end
		else
			return(1)
	end

end

/*
** @configcount=0 implies @configname is not valid
** @configname=NULL implies displaying all the parameters except for
** the parameters with the config number equal to 19 or the parent equal
** to 19 since those parameters are displayed by sp_cacheconfig.
*/
if (@configcount = 0)
begin
	/* 18124, "No matching configuration options.  
	** Here is a listing of groups:" 
	*/
	raiserror 18124
	select distinct convert(char(50), name)
		from master.dbo.sysconfigures
		where config < 100
		and parent != 19
		and config != 19
		order by name
	return(1)
end
else if (@configname is NULL and @non_default_options is NULL)
begin

	select @configname = "Config"

end

/*
** retrieve the display level from sysattributes
*/
select @user_displaylevel = int_value from master.dbo.sysattributes where
	class = 4 AND
	attribute = 0 AND
	object_type = 'L' AND
	object = suser_id()

/*
** set the default display level to 10 if it is not defined in sysattributes
*/
if (@user_displaylevel is NULL)
	select @user_displaylevel = 10

/*  
** If non_default_options is set, display only nondefault settings depending 
** on current display level and return
*/	
if(@non_default_options = 1)
begin 
	/* Display all config parameters for specified instance. */
	if @configvalue3 is not NULL
	begin
		if @configvalue3 != @@instancename
		begin
			raiserror 19519, @configvalue3
			return (1)
		end
		else
		begin
			select  Parameter_Name = convert(char(30), name), 
				Default_Value = convert(varchar(11), defvalue), 
				Memory_Used = convert(varchar(11), c.comment), 
				Config_Value = isnull(b.value2, 
						      convert(char(32), b.value)),
				Run_Value  = isnull(c.value2, 
						    convert(char(32), c.value)), 
				Unit = convert(char(20), c.unit), 
				Type_ = convert(char(10), c.type)

			into #temptable1 
			from master.dbo.sysconfigures b, 
			     master.dbo.syscurconfigs c 
			where 
			      
				b.config = c.config
			      and (c.defvalue != isnull(b.value2, 
						  convert(char(32), b.value)) 
			        or c.defvalue != isnull(c.value2, 
						  convert(char(32), c.value))) 
			      and c.config != 114 
					/* Exclude option 'configuration file' */
			      and c.type != "read-only" 
			      and display_level <= @user_displaylevel

			exec sp_autoformat #temptable1,
				@selectlist = "'Parameter Name' = Parameter_Name,
				'Default'= Default_Value,'Memory Used' = Memory_Used,
				'Config Value '= Config_Value,'Run Value'= Run_Value,
				
				'Unit' = Unit,'Type'= Type_",

				@orderby = "order by Parameter_Name"
			return (0)
		end
	end

	if @@system_view = "instance"
	begin
		/*
		** Display the information of the config parameter
		** for the current instance as well as the cluster-wide
		** one.
		*/
        	select  Parameter_Name = convert(char(30), name),
			Default_Value = convert(varchar(11), defvalue),
			Memory_Used = convert(varchar(11), c.comment),
			Config_Value = isnull(b.value2, convert(char(32), b.value)),
			Run_Value  = isnull(c.value2, convert(char(32), c.value)),
			Unit = convert(char(20), c.unit),
			Type_ = convert(char(10), c.type)

		into #temptable3
		from master.dbo.sysconfigures b,
	     	     master.dbo.syscurconfigs c
		where   

			b.config = c.config
			and (c.defvalue != isnull(b.value2, convert(char(32), b.value)) 
		    	  or c.defvalue != isnull(c.value2, convert(char(32), c.value)))	  
			and c.config != 114 
					/* Exclude option 'configuration file' */ 
			and c.type != "read-only"
			and display_level <= @user_displaylevel 

		exec sp_autoformat #temptable3, 
			@selectlist = "'Parameter Name' = Parameter_Name, 
			'Default'= Default_Value,'Memory Used' = Memory_Used, 
			'Config Value '= Config_Value,'Run Value'= Run_Value, 

			'Unit' = Unit,'Type'= Type_", 

			@orderby = "order by Parameter_Name"
	end
	else
	begin
		/* 
		** When system_view is set to 'cluster', we need to
		** display the config info across all instances. This
		** includes two part: one is the cluster-wide config
		** setting whose instanceid is NULL; the other
		** part is the info for each instance who has a valid
		** instanceid.
		*/
		select distinct
			Parameter_Name = convert(char(30), name), 
			Default_Value = convert(varchar(11), defvalue), 
			Memory_Used = convert(varchar(11), c.comment), 
			Config_Value = isnull(b.value2, convert(char(32), b.value)), 
			Run_Value  = isnull(c.value2, convert(char(32), c.value)), 
			Unit = convert(char(20), c.unit), 
			Type_ = convert(char(10), c.type)
						
		into #temptable 
		from master.dbo.sysconfigures b, master.dbo.syscurconfigs c 
		where 
			
			b.config = c.config 
			and (c.defvalue != isnull(b.value2, 
						  convert(char(32), b.value)) 
			  or c.defvalue != isnull(c.value2, 
						  convert(char(32), c.value))) 
			and c.config != 114 
					/* Exclude option 'configuration file' */ 
			and c.type != "read-only" 
			and display_level <= @user_displaylevel


		
		exec sp_autoformat #temptable, 
			@selectlist = "'Parameter Name' = Parameter_Name,
			'Default'= Default_Value,'Memory Used' = Memory_Used,
			'Config Value '= Config_Value,'Run Value'= Run_Value,

			'Unit' = Unit,'Type'=Type_",
		
			@orderby = "order by Parameter_Name"
	end
	return (0)

end 	    	
	
/*
**      If @use_wildcard = 0 and the default sortorder is case-insensitive
** dictionary sort order, use exact match: name = @configname to get row,
** otherwise use wildcard match: name like "%" + @configname + "%".
*/
 
if (@use_wildcard = 0 and @nocase = 1)
begin
        select  @confignum = config,
                @parent = config,
                @sysname = name,
                @sysstatus = status
        from master.dbo.sysconfigures
                where name = @configname
                and config != 19
end
else
begin
	select	@confignum = config, 
		@parent = config,
		@sysname = name,
		@sysstatus = status
	from master.dbo.sysconfigures
		where name like "%" + @configname + "%"
		and config != 19
end

select	@children = count(*)
	from master.dbo.sysconfigures
	where parent =  @confignum

if @children = 0
begin
	/* @@nestlevel is problem area if a sproc calls sp_configure */
	/* could pass in another param when recursing */
	if @@nestlevel > 1
	begin
		/* reached a leaf, notify parent */
		return(1)
	end
	else
	begin

		begin
			/* Display the information of the config parameter 
			** for the current server as well as the cluster-wide
			** one. Instanceid is NULL meaning this is the 
			** cluster-wide configuration.
			*/ 
			select "Parameter Name" = convert(char(30), name),
                        "Default" = CASE WHEN b.config = 507 THEN @optlevel_def
				ELSE convert(char(11), space(11-char_length(
                                    convert(varchar(11), defvalue)))+
                                    convert(varchar(11), defvalue))
				END,
                        "Memory Used" = convert(char(11), space(11-char_length(
                                        convert(varchar(11), c.comment)))+
                                        convert(varchar(11), c.comment)),
                        "Config Value" = CASE WHEN b.config = 507 THEN @optlevel_curr
				ELSE convert(char(12), space(12-char_length(
                          isnull(b.value2, convert(char(32), b.value)))) +
                          isnull(b.value2, convert(char(32), b.value)))
				END,
                        "Run Value" = CASE WHEN b.config = 507 THEN @optlevel_run
				ELSE convert(char(12), space(12-char_length(
                          isnull(c.value2, convert(char(32), c.value)))) +
                          isnull(c.value2, convert(char(32), c.value)))
				END,
			"Unit" = convert(char(20), c.unit),
			"Type" = convert(char(20), c.type)

			from master.dbo.sysconfigures b,
			     master.dbo.syscurconfigs c
			where 

				b.config *= c.config
				and name like "%" + @configname + "%"
				and b.config != 19
				and parent != 19
		end

	end

	return (0)
end
else
begin
	select @msg = "Group: " + @sysname
	print ""
	print @msg
	print ""

	/* this poor guy has kids, so recurse to leaves */
	declare config_curs cursor for 
		select config, name, parent 
		from master.dbo.sysconfigures 
		where parent = @parent
		order by name
		
	open config_curs

	fetch config_curs into @sysconfig, @sysname, @sysparent

	while (@@sqlstatus = 0)
	begin

		execute @status = sp_configure @sysname

		if (@status = 1)
		begin
			/*
			** this guy has leaves as kids,
			** so print out the leaves with
			** display level <= @user_displaylevel
			** Note: If a config parameter has more than one
			** parent, the extra parents are stored in
			** 'sysattribures'.
			*/
			create table #configure_temp (config int)

			insert into #configure_temp
				select distinct a.config
					from master.dbo.sysconfigures a,
					master.dbo.syscurconfigs b
					where
			  	   	   display_level <= @user_displaylevel
				   	   and parent = @parent
					   and a.config != 19
					   and a.config = b.config

		  		    union
				    select distinct config
					from master.dbo.syscurconfigs,
					master.dbo.sysattributes
					where
			  	   	   display_level <= @user_displaylevel
					   and class = 4
					   and attribute = 1
					   and object_type = 'CP'
				   	   and int_value = @parent
					   and object = config
					   and config != 19


			if exists (select * from #configure_temp)
			begin

				/*
				** If system_view is 'instance', display
				** the config info for the current instance
				** as well as the cluster-wide one.
				*/

			 	begin
			    		select 
					"Parameter Name" = convert(char(30), name),
					"Default" = CASE WHEN b.config = 507
						THEN @optlevel_def
						ELSE convert(char(11), 
						space(11-char_length(
						convert(varchar(11), defvalue))) +
						convert(varchar(11), defvalue))
						END,
					"Memory Used" = 
						convert(char(11), 
						space(11-char_length(
						convert(varchar(11), c.comment))) +
						convert(varchar(11), c.comment)),
					"Config Value" = CASE WHEN b.config = 507 
						THEN @optlevel_curr
						ELSE convert(char(12),
						space(12-char_length(
		 	 			isnull(b.value2, 
						convert(char(32), b.value)))) +
		 	 			isnull(b.value2, 
						convert(char(32), b.value)))
						END,
					 "Run Value" = CASE WHEN b.config = 507
					 	THEN @optlevel_run
						ELSE convert(char(12), 
						space(12-char_length(
			 			isnull(c.value2, 
						convert(char(32), c.value)))) +
			 			isnull(c.value2, 
						convert(char(32), c.value)))
						END,
			  		"Unit" = convert(char(20), c.unit),
			  		"Type" = convert(char(20), c.type)

			   		from master.dbo.sysconfigures b,
					     master.dbo.syscurconfigs c
			   		where b.config in
						(select config 
						 from #configure_temp)
					and b.config = c.config

			   		order by name
				end

			end

			drop table #configure_temp

			close config_curs
			deallocate cursor config_curs

			return(0)
		end
		else
		begin
			/*
			** this lucky guy has grandkids, so, continue
			*/
			fetch config_curs into 
				@sysconfig, @sysname, @sysparent

		end
	end

	close config_curs
	deallocate cursor config_curs

	return(0)
end

go
exec sp_procxmode 'sp_configure', 'anymode'
go
grant execute on sp_configure to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dboption')
begin
	drop procedure sp_dboption
end
go
print "Installing sp_dboption"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/a_values */

/*
** Messages for "sp_dboption"           17420
**      Use "langid" when looking at spt_values ???
**
** 17260, "Can't run %1! from within a transaction." 
** 17420, "Settable database options."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17423, "Usage: sp_dboption [dbname, optname, {true | false}]"
** 17424, "Database option doesn't exist or can't be set by user."
** 17425, "Run sp_dboption with no parameters to see options."
** 17426, "Database option is not unique."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 17430, "Run the CHECKPOINT command in the database that was changed."
** 17431, "true"
** 17432, "false"
** 17433, "Database option '%1!' turned ON for database '%2!'."
** 17434, "Database option '%1!' turned OFF for database '%2!'."
** 17289, "Set your curwrite to the hurdle of current database."
** 17436, "You cannot set the '%1!' option for a temporary database"
** 17439, "You cannot turn on ''%1!' for '%2!' because it is an HA server 
** 	that has been configured with the proxy_db option."
** 18974, "Warning: Attempting to change database options for a 
** 	   temporary database. Database options must be kept consistent
** 	   across all temporary databases."
** 19015, "The 'async log service' option is only valid for configurations 
**	   with more than 4 engines online."
** 19112, "Running CHECKPOINT on database '%1!' for option '%2!' to take effect."
** 19113, "CHECKPOINT command failed. Run the CHECKPOINT command in database '%1!' for the 
**         change to take effect."
** 19424, "Cannot run '%1!' on an archive database."
** 19884, "You cannot set the '%1!' option to '%2!' for a temporary database."
** 19518, "Warning: Attempting to change database options for a local
**         temporary database. Database options must be kept consistent
**         across all local temporary databases."
** 19886, "Please execute DUMP DATABASE before executing DUMP TRANSACTION."
** 19892, "DUMP TRANSACTION is not allowed when '%1!' is ON. Use DUMP DATABASE 
	or DUMP TRANSACTION ... WITH TRUNCATE_ONLY or WITH NO_LOG instead."
** 19987, "You cannot set the '%1!' option for temporary databases or for 
	   databases with durability %2!"
*/

create procedure sp_dboption
@dbname varchar(30) = NULL,		/* database name to change */
@optname varchar(20) = NULL,		/* option name to turn on/off */
@optvalue varchar(10) = NULL,		/* true or false */
@dockpt	tinyint	= 1			/* 
					** 0 indicates don't run checkpoint 
					** else run checkpoint automatically
					*/
as

declare @dbid int			/* dbid of the database */
declare @dbuid int			/* id of the owner of the database */
declare @statvalue int,			/* number of option */
	@stattype char(2),		/* status field flag */
	@statopt smallint,		/* option mask, part 1 */
	@stat2opt smallint,		/* option mask, part 2 */
	@stat3opt int			/* option mask, part 3 */
declare @optcount int			/* number of options like @optname */
declare @success_msg varchar(1024)	/* success status message */
declare @msg varchar(1024)
declare @sptlang	int
declare @true		varchar(10)
declare @false		varchar(10)
declare @whichone	int		/* which language? */
declare	@optmsgnum	int		/* identify one msgnum to compare */
declare	@msgcnt		int		/* count distinct dups */
declare @tempdb_mask	int		/* all tempdb status bits */
declare @local_tempdb_mask int		/* all local tempdb status bits */
declare @isatempdb	int		/* changing options on a temp. db ? */
declare @ismixedlog	int		/* does database have mixed log,data */ 
declare @engines	int		/* Get the number of engines */
declare @isarchivedb	int		/* Is this an archive database? */
declare @DMPX_NOTOK_NONLOGGED_WRITES	int /* Same definition as in dmpld.h */
declare @DMPX_NOTOK_TRUNCATED_ONLY	int /* Same definition as in dmpld.h */
declare @durability	varchar(30)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0, @isatempdb = 0, @isarchivedb = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end


/*
**  If no @dbname given, just list the possible dboptions.
**  Only certain status bits may be set or cleared.  
**	   settable                	    not settable
**      ------------------------------  --------------------------
**	allow select into/bulkcopy (4)	don't recover (32)
**	read only (1024)		not recovered (256)
**	dbo use only (2048)		dbname has changed (16384)
**	single user (4096)
**	truncate log on checkpoint (8)
**	no checkpoint on recovery (16)
**	allow null (8192)
**	ddl in tran (512)
**      ALL SETTABLE OPTIONS (15900)
**	abort xact on log full (1, type='D2')
**	no space accounting (2, type='D2')
**	auto identity(4, type='D2')
**	identity in nonunique index(8, type='D2')
**	auto identity unique index(64, type='D2')
**	async log service	  (1024 type='D3')
**	delayed commit   	  (2048 type='D3')
**      scratch database (16777216 type='D3')
*/

/*
** Look for the "settable options" mask in spt_values
*/
select @statopt = number
from master.dbo.spt_values
where type = "D"
  and name = "ALL SETTABLE OPTIONS"

select @stat2opt = number
from master.dbo.spt_values
where type = "D2"
  and name = "ALL SETTABLE OPTIONS"


select @stat3opt = number
from master.dbo.spt_values
where type = "D3"
   and name = "ALL SETTABLE OPTIONS"

/*
** If we can't find the option masks, guess at them
*/
if @statopt is null
	select @statopt  = 4 | 8 | 16 | 512 | 1024 | 2048 | 4096 | 8192
if @stat2opt is null
	select @stat2opt = 1 | 2 | 4 | 8 | 64
if @stat3opt is null
	select @stat3opt = 1024 | 2048 | 16777216

if @dbname is null
begin
	exec sp_getmessage 17420, @msg output
	print @msg

	if @sptlang = 0
	    select database_options = name
		from master.dbo.spt_values
		where ((type = "D"
			and number & @statopt = number
			and number & @statopt != @statopt)
		    or (type = "D2"
			and number & @stat2opt = number
			and number & @stat2opt != @stat2opt)
		    or (type = "D3"
			and number & @stat3opt = number
			and name != "ALL SETTABLE OPTIONS"))
		order by name
	else
	    select database_options = name, convert(char(22), description)
		from master.dbo.spt_values, master.dbo.sysmessages
		where ((type = "D"
			and number & @statopt = number
			and number & @statopt != @statopt)
		    or (type = "D2"
			and number & @stat2opt = number
			and number & @stat2opt != @stat2opt)
		    or (type = "D3"
			and number & @stat3opt = number
			and name != "ALL SETTABLE OPTIONS"))
		  and msgnum = error
		  and langid = @sptlang
		order by name
	return (0)
end

/*
**  Verify the database name and get the @dbid and @dbuid
*/
select @dbid = dbid, @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so and list the databases.
*/
if @dbid is NULL
begin
	raiserror 17421
	return (1)
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if ((suser_id() != @dbuid) and (proc_role("sa_role") < 1))
	return(1)

/*
**  You can not change any of the options in master.  If the user tries to
**  do so tell them they can't.
*/
if @dbid = 1
begin
	raiserror 17422
	return (1)
end

/*
** Determine if we are changing options for a temporary database.
*/
select @tempdb_mask =  number
	from master.dbo.spt_values
	where   type = "D3" and name = "TEMPDB STATUS MASK"

if (@dbid = 2) or exists (select * from master.dbo.sysdatabases
	     	            where dbid = @dbid
	     	            and (status3 & @tempdb_mask) != 0)
begin
	select @isatempdb = 1
end
else
if exists (select * from master.dbo.sysdatabases
                            where dbid = @dbid
                            and (status3 & 4194304) = 4194304)
begin
	select @isarchivedb = 1
end

select @durability = db_attr(@dbid, "durability")

/*
** If attempting to change the options for a temporary database, the user
** should be warned that database options across all temporary databases
** should be kept consistent.
*/
select @local_tempdb_mask = 0

if (@@clustermode != "shared disk cluster" and @isatempdb = 1)
begin
	exec sp_getmessage 18974, @msg output
	print @msg
end
else if (@@clustermode = "shared disk cluster")
begin
	select @local_tempdb_mask = number
		from master.dbo.spt_values
		where   type = "D3" and name = "LOCAL TEMPDB STATUS MASK"

	if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid
			and (status3 & @local_tempdb_mask) != 0)
	begin
		/*
		** In SDC, #table appears only in local tempdbs, global tempdb
		** is mostly like the regular databases, dboptions doesn't
		** need to be same among global tempdbs.
		**
		** 19518, "Warning: Attempting to change database options for a
		**	   local temporary database. Database options must be
		**	   kept consistent across all local temporary 
		**	   databases."
		*/
		exec sp_getmessage 19518, @msg output
		print @msg
	end
end

/*
**  Check remaining parameters.
*/
exec sp_getmessage 17431, @true out
exec sp_getmessage 17432, @false out
if @optname is NULL or lower(@optvalue) not in 
	("true", "false", @true, @false) or @optvalue is null
begin
	raiserror 17423
	return (1)
end

/*
**  Use @optname and try to find the right option.
**  If there isn't just one, print appropriate diagnostics and return.
*/
select @optcount = count(*)
   from master.dbo.spt_values
	where name like "%" + @optname + "%"
	  and ((type = "D"
		and number & @statopt = number)
	    or (type = "D2"
		and number & @stat2opt = number)
	    or (type = "D3"
		and number & @stat3opt = number))
/*
**  If more than one option like @optname, make sure they are not the same
**  option ("trunc" and "trunc.", for example)
*/
if @optcount > 1
begin
	select  @optmsgnum = msgnum
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))

	select @msgcnt = count(msgnum)
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
	          and msgnum != @optmsgnum

	/* 
	** msgcnt of 0 indicates we really have just 1 unique dboption, 
	** probably due to alternate spelling.
	*/
	if (@msgcnt = 0) 
		select @optcount = 1
end
/*
** If no option, and alternate language is set, use other language
*/
if @optcount = 0 and @sptlang != 0
begin
    select @optcount = count(*)
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
		  and msgnum = error
		  and langid = @sptlang
    select @whichone = 1
    /*
    **  If more than one option like @optname, make sure they are not the same
    **  option ("trunc" and "trunc.", for example)
    */
    if @optcount > 1
    begin
	select  @optmsgnum = msgnum
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
		  and msgnum = error
		  and langid = @sptlang

	select @msgcnt = count(msgnum)
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
		  and msgnum = error
		  and langid = @sptlang
	          and msgnum != @optmsgnum

	/* 
	** msgcnt of 0 indicates we really have just 1 unique dboption, 
	** probably due to alternate spelling.
	*/
	if (@msgcnt = 0) 
		select @optcount = 1
    end
end

/*
**  If no option, show the user what the options are.
*/
if @optcount = 0
begin
	raiserror 17424

	exec sp_getmessage 17425, @msg output
	print @msg
	return (1)
end

/*
**  If more than one option like @optname, show the duplicates and return.
*/
if @optcount > 1
begin
	raiserror 17426

	if @sptlang = 0
	    select duplicate_options = name
		from master.dbo.spt_values
			where name like "%" + @optname + "%"
			  and ((type = "D"
				and number & @statopt = number)
			    or (type = "D2"
				and number & @stat2opt = number)
	    	    	    or (type = "D3"
		        	and number & @stat3opt = number))
	else
	    select duplicate_options = name, convert(char(22), description)
		from master.dbo.spt_values, master.dbo.sysmessages
			where (name like "%" + @optname + "%"
				or description like "%" + @optname + "%")
			  and ((type = "D"
				and number & @statopt = number)
			    or (type = "D2"
				and number & @stat2opt = number)
	    	    	    or (type = "D3"
		        	and number & @stat3opt = number))
			  and msgnum = error
			  and langid = @sptlang

	return (1)
end


if db_name() != "master"
begin
	raiserror 17428
	return (1)
end

/*
** User cannot set a temporary  database in single user mode or as a scratch 
** database.
*/
select @statvalue = number
   from master.dbo.spt_values
	where name like "%" + @optname + "%"
	  and ((type = "D"
		and number & @statopt = number)
	    or (type = "D2"
		and number & @stat2opt = number)
	    or (type = "D3"
		and number & @stat3opt = number))
 
if (@isatempdb = 1) and ((@statvalue & (4096 | 16777216)) != 0)
begin
	raiserror 17436, @optname
	return (1)
end

/* disallow turning off the 'select into' option for a temporary database. */
if 	(@isatempdb = 1) 
    and (@statvalue = 4) 
    and (lower(@optvalue) in ('false', @false))
begin
	raiserror 19884, @optname, @false
	return (1)
end
/* 
** Only the 'single user option' may be changed in an archive database.
*/
if (@isarchivedb = 1) and (@statvalue != 4096)
begin
	raiserror 19424, "sp_dboption"
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_dboption"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
**  Get the number which is the bit value to set
*/
if @whichone = 0
       	  select @statvalue = number, @stattype = type, @success_msg = name
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
		    or (type = "D3"
			and number & @stat3opt = number))
else
    select @statvalue = number, @stattype = type, @success_msg = name
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
			and ((type = "D"
			      and number & @statopt = number)
			  or (type = "D2"
			      and number & @stat2opt = number)
		    	  or (type = "D3"
				and number & @stat3opt = number))
			and msgnum = error
			and langid = @sptlang

/*
** We do not allow 'sybsecurity' to be set to 'single user' since,
** if auditing is enabled and we try to set 'sybsecurity' database to
** 'single user' then, the audit process is killed because audit process
** tries to do 'usedb' and it fails (look at utils/auditing.c).
*/
if (@dbname = "sybsecurity") and (@statvalue = 4096)
begin
	/*
	** 17435, "The 'single user' option is not valid for the
	** 'sybsecurity' database.
	*/
	raiserror 17435
	return (1)
end
 
/*
** We do not allow Async logging services on system  databases. 
*/

if (@statvalue = 1024) and (@stattype = "D3") 
begin
	/* 
	** Not valid for master, model and systemp tempdb, user define tempdbs and
	** the sybsecurity database
	*/
	if (@dbname in ("master","model", "sybsystemdb", "sybsystemprocs", "sybsecurity", "dbccdb", "dbccalt", "sybsyntax"))
		OR (@isatempdb = 1)
	begin
		/*
		** 18984, The 'async log service' option is not valid 
		** for system databases 
		*/
		raiserror 18984
		return(1)
	end

	/* We don't allow this option for databases with mixed log and data */
	select @ismixedlog = status2 & 32768 
		from master.dbo.sysdatabases
			where dbid = @dbid

	if(@ismixedlog = 32768)
	begin
		/*
		** 18986, The 'async log service' option is only valid for 
		** configurations with more than 4 engines online.
		*/
		raiserror 18986
		return(1)
	end

	select @engines = count(engine)
		from master.dbo.sysengines
		where status != "offline"

	if (@engines < 4)
	begin
		raiserror 19015
		return(1)
	end
end

/*
** For IMDB/RDDB databases disallow 'delayed commit' and 'async log service'.
*/
if   ((@durability in ('at_shutdown', 'no_recovery'))
  and (@statvalue in (1024, 2048))
  and (@stattype = "D3")
 )
begin
       select @durability = upper(@durability)
       raiserror 19987,  @optname, @durability
       return (1)
end
	
/*
**  Now update sysdatabases.
*/
if lower(@optvalue) in ("true", @true)
begin
	/* 
	** If this is the option to set 'abort tran on log full' to 
	** true for sybsecurit database, then don't allow.
	*/
	if (db_name(@dbid) = "sybsecurity" 
		and @stattype = "D2" and @statvalue = 1)
	begin
		/*
		** AUDIT_CHANGE: New error message needs to be reserved and
		** the print statement needs to be removed.
		*/
		print "You cannot set 'abort tran on log full' to true for sybsecurity database."
		return (1)
	end

	/*
	** Disallow DDL IN TRAN 
	**	if proxydb option is set (@@crthaproxy = 1)
	**	if this server is a HA server (@@cmpstate >= 0)
	**	if database is not a tempdb
	*/
	if ((@statvalue = 512) and (@@crthaproxy = 1) and
		(@@cmpstate >= 0) and (@isatempdb = 0))
	begin
		/*
		** Cannot set DDL_IN_TRAN option for HA servers
		** configured with proxy_db option.
		*/
		exec sp_getmessage 17439, @msg output
		print @msg, @success_msg, @dbname
		return (1)
	end

	if (@stattype = "D")
		update master.dbo.sysdatabases
			set status = status | @statvalue
				where dbid = @dbid
	else if( @stattype = "D2")
		update master.dbo.sysdatabases
			set status2 = status2 | @statvalue
				where dbid = @dbid
	else
		update master.dbo.sysdatabases
			set status3 = status3 | @statvalue
				where dbid = @dbid
	exec sp_getmessage 17433, @msg output
	print @msg, @success_msg, @dbname
end

/*
**  We want to turn it off.
*/
else
begin

	if (@stattype = "D")
		update master.dbo.sysdatabases
			set status = status & ~@statvalue
				where dbid = @dbid
	else if (@stattype = "D2")
		update master.dbo.sysdatabases
			set status2 = status2 & ~@statvalue
				where dbid = @dbid
	else
		update master.dbo.sysdatabases
			set status3 = status3 & ~@statvalue
				where dbid = @dbid
	exec sp_getmessage 17434, @msg output
	print @msg, @success_msg, @dbname
end

if (@dockpt != 0)
begin
	exec sp_getmessage 19112, @msg output
	print @msg, @dbname, @success_msg

	/*
	**  Run the CHECKPOINT command on the database that was changed. If
	**  that fails advise the user to run the CHECKPOINT command in the database 
	**  that was changed.
	*/
	checkpoint @dbname

	if (@@error != 0)
	begin
		exec sp_getmessage 19113, @msg output
		print @msg, @dbname
	end
end
else
begin
	exec sp_getmessage 17430, @msg output
	print @msg
end

return (0)
go
exec sp_procxmode 'sp_dboption', 'anymode'
go
grant execute on sp_dboption to public
go
dump tran master with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropdevice')
begin
	drop procedure sp_dropdevice
end
go
print "Installing sp_dropdevice"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/dropdevice */

/*
** Messages for "sp_dropdevice"         17482
**
** 17260, "Can't run %1! from within a transaction." 
** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices." 
** 17482, "Device is being used by a database. You can't drop it."
** 17483, "Device dropped."
*/

create procedure sp_dropdevice
@logicalname	varchar(255)		/* logical name of the device */

as
declare @msg varchar(1024)
declare @len1 int, @len2 int
declare @status int
declare @status2 int
declare @factor int
declare @adbclass int

select @adbclass = 28

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_dropdevice"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
**  Check and make sure that the device actually exists.
*/
if not exists (select * 
		from master.dbo.sysdevices
			where name = @logicalname)
begin
	/*
	** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices." 
	*/
	raiserror 17471
	return (1)
end

/*
**  Check and make sure that no database is using the device.
**  If so, print out who is using it and exit.
*/
if exists (select *
	from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname)
begin
	/*
	** 17482, "Device is being used by a database. You can't drop it."
	*/
	raiserror 17482
   
	select @factor = @@maxpagesize / @@pagesize 

	select @len1 = max(datalength(a.name)),
	       @len2 = max(datalength(c.name))
	from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname

	if (@len1 > 23 or @len2 > 21)
	    select database_name = a.name,
		device = c.name,
		size = convert(varchar(25), (size / 512) * @factor) + " MB"
	    from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname
	    order by a.name, c.name, size
	else
	    select database_name = convert(char(23), a.name),
		device = convert(char(21), c.name),
		size = convert(varchar(25), (size / 512) * @factor) + " MB"
	    from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname
	    order by a.name, c.name, size

	return (1)
end
else if exists (select 1
        from master..sysattributes a
        where a.class=@adbclass
        and a.object_type = 'D'
        and a.attribute = 1
        and a.object_cinfo = @logicalname)
begin
        /*
        ** 17482, "Device is being used by a database. You can't drop it."
        */
        raiserror 17482

        select convert(char(30), name), convert(char(40), char_value)
        from master.dbo.sysdatabases a, master.dbo.sysattributes b
        where b.class = @adbclass
        and b.object_type = 'D'
        and b.attribute = 1
        and b.object_cinfo = @logicalname
        and b.object = a.dbid

        return (1)
end

/*
**  Everything's ok so drop the device.
*/
select @status = status from master.dbo.sysdevices
	where name = @logicalname
	
select @status2 = status2 from master.dbo.sysdevices
	where name = @logicalname
/*
** If database device or cache device (status2 & 8), close it and remove it 
** from the sysdevices table using "disk release" command.  If dump device,
** remove it from sysdevices table.
**/
if (((@status & 6) != 0) or ((@status2 & 8) != 0))
	disk release name = @logicalname
else
	delete master.dbo.sysdevices 
		where name = @logicalname
if (@@error != 0)
	return (1)

/*
** 17483, "Device dropped."
*/
exec sp_getmessage 17483, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_dropdevice', 'anymode'
go
grant execute on sp_dropdevice to public
go
dump tran master with truncate_only
go
/* Sccsid = "@(#) generic/sproc/src/server_install 84.1 6/23/93" */
/*	4.8	1.1	06/14/90	sproc/src/server_sun */
/*
**  This file contains the necessary modifications to be made for
**  various DataServer host machines.
**  It sets the DataServer host environment to be linux.
**  spt_values.low is the number of bytes in a DataServer page.
*/
use master
go

delete spt_values
	where type = "E" and number > 0
go
/* data page size for linux */
insert into spt_values (name, number, type, low)
	values ("linux", 1, "E", @@maxpagesize)

/* Value to set and clear the high bit for int datatypes for linux. */
insert into spt_values (name, number, type, low)
	values ("int high bit", 2, "E", 0x00000080)

/* Value which gives the byte position of the high byte for int datatypes for linux. */
insert into spt_values (name, number, type, low)
	values ("int high byte", 3, "E", 4)
go

/*
** Make minimum allowable memory setting equal to value which
** would allow for successful operation of the server on a linux.
*/
update spt_values
	set low = 3850
		from spt_values
	where number = 104 
		and type = "C"
go

/*
** Value indicates the support of direct i/o on this port
*/

insert into spt_values (name, number, type, low)
        values ("directio", 0, "io", 1)

/* command to fix up freeoff on page 24 in all databases */
dbcc dbrepair (master, fixsysindex)

go

dump transaction master to diskdump with truncate_only
go
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_loaddbupgrade')
begin
	drop procedure sp_loaddbupgrade
end
go
print "Installing sp_loaddbupgrade"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_loaddbupgrade 
@databasename varchar(30), 
@devname varchar(30)
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

dbcc traceon(3402)

/* The recovery which is part of load database will perform the upgrade */
load database @databasename from @devname

dbcc traceoff(3402)

return (0)
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_prtsybsysmsgs')
begin
	drop procedure sp_prtsybsysmsgs
end
go
print "Installing sp_prtsybsysmsgs"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/* 
** This procedure is needed to extract messages for the batch that creates
** the sybsystemprocs database. When return parameters are used in an execute
** statement that is a part of a SQL batch, the return values are printed 
** with a heading before subsequent statements in the batch are executed.
** These headings could be confusing to a user that is looking at the results
** of the batch. Hence we print the message in a stored procedure
*/

create procedure sp_prtsybsysmsgs 
@i int, @size int = NULL, @size2 int = NULL
as

declare @msg varchar(1024)

exec sp_getmessage @i, @msg out
print @msg, @size, @size2
go
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for crtsybsystemprocs	18060
** 18060, "The database sybsystemprocs needs to be atleast %1!MB in size. 
** It is currently at %2!MB."
** 18061, "Installing system stored procedures in the sybsystemprocs database."
** 18062, "Database sybsystemprocs of size %1!MB is being created on the 
** default device." 
** 18063, "Done creating database sybsystemprocs on the default device."
** 18064, "Cannot create database sybsystemprocs of size %1!MB on the default 
** device because there is not enough space. Please create this database 
** elsewhere and rerun the installmaster script."
** 19527, "The '%1!' database cannot be created. Terminating the installation."
** 19528, "The '%1!' database does not exist. Terminating the installation."
** 19529, "Cannot open database '%1!'. Check the availability of this database 
** and retry the installation."
*/

declare @crdb_cmd	varchar(200)	-- create proc db if needed
declare @procdb_name	varchar(30)	-- proc db's standard name
declare @procdb_min_mb	int		-- proc db's standard size
declare @procdb_mb	int		-- how big proc db presently is
declare @crdb_use_mb	int		-- size to use in "create database"
declare @lpages_per_mb	int		-- logical pages per megabyte
declare @mb_per_au	int		-- megabytes per alloc unit

select @procdb_name = "sybsystemprocs"
select @lpages_per_mb = (1024 * 1024) / @@maxpagesize

/*
** Refer to include/server.h for the server's current sybsystemprocs
** minimum and recommended sizes. Keep the number in this file consistent
** with that recommended. It is presently not based on page size or pointer
** size.
*/

select @procdb_min_mb = 152	/* taken from include/server.h */

/*
** Check if the procedure database exists.  If not, create it at its
** minimum permitted size via "exec immediate"; otherwise ensure that
** it is big enough for our needs.
*/
if not exists (select * from master.dbo.sysdatabases where name=@procdb_name)
begin
	/*
	** No database yet.  Create one.  However, let us make sure to use
	** a size that we CAN create, so that page size issues don't cause
	** us to create a database that will fail the minimum size test.
	*/
	select @mb_per_au = (256 / @lpages_per_mb)
	if (@mb_per_au <= 1)
		select @crdb_use_mb = @procdb_min_mb
	else
		select @crdb_use_mb = @mb_per_au *
			((@procdb_min_mb + @mb_per_au - 1) / @mb_per_au)

	/*
	** 18062, "Database sybsystemprocs of size %1!MB is being created on 
	** the default device"
	*/	
	exec sp_prtsybsysmsgs 18062, @crdb_use_mb

	select @crdb_cmd = "create database " + @procdb_name +
		" on default=" + convert(varchar(10), @crdb_use_mb)

	exec (@crdb_cmd)

	-- If the create command failed, an error was printed and return.
	if (@@error != 0)
	begin
		/*
		** 19527, "The '%1!' database cannot be created. Terminating the installation."
		*/
		raiserror 19527, "sybsystemprocs"
		return
	end

	-- Ensure that what we created was the size we asked for.
	select @procdb_mb = isnull(sum(size), 0) / @lpages_per_mb
	from master.dbo.sysusages where dbid=db_id(@procdb_name)
	if (@procdb_mb < @procdb_min_mb)
	begin
		/*
		** 18064, "Cannot create database sybsystemprocs of size 
		** %1!MB on the default device because there is not enough
		** space.  Please create this database elsewhere and rerun
		** the installmaster script."
		*/
		exec sp_prtsybsysmsgs 18064, @procdb_min_mb
		drop database sybsystemprocs
		return
	end

	/*
	** 18063, "Done creating database sybsystemprocs on the 
	** default device."
	*/
	exec sp_prtsybsysmsgs 18063
end
else
begin
	-- Database exists.  Check that it meets our minimum size requirement.

	select @procdb_mb = sum(size) / @lpages_per_mb
	from master.dbo.sysusages where dbid=db_id(@procdb_name)
	if (@procdb_mb < @procdb_min_mb)
	begin
		/*
		** 18060, "The database sybsystemprocs needs to be atleast 
		** %1!MB in size. It is currently at %2!MB."
		*/
		exec sp_prtsybsysmsgs 18060, @procdb_min_mb, @procdb_mb
		return 
	end
end

/*
** If we reach this point, the procedure database must exist and must
** be at least our minimum size.  We can work.
*/

/*
** 18061, "Installing system stored procedures in the sybsystemprocs
** database."
*/
exec sp_prtsybsysmsgs 18061

/* Turn on the trunc. log on checkpoint option for the database */
exec sp_dboption @procdb_name, "trunc", true
go

/*
** Don't use the previously defined db name variable here; it's gone!
*/
if exists (select * from master.dbo.sysdatabases
		where name = "sybsystemprocs")
begin
	use sybsystemprocs
end
else
begin
	/*
	** 19528, "The '%1!' database does not exist. Terminating the installation."
	*/
	raiserror 19528, "sybsystemprocs"
	select syb_quit()
end
go
if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go
checkpoint
go
dump transaction sybsystemprocs with truncate_only
go
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** This file creates the tables needed for the Microsoft stored procedures.
** It also loads the needed values into those tables.
** The tables are:
**	spt_datatype_info_ext
**	spt_datatype_info
**	spt_server_info
**
** Under no circumstances should changes be made to the tables stored in
** this routine unless they are to fix problems with ODBC connectivity.
** These tables interface with the ODBC connectivity routines:
**	sp_columns
**	sp_datatype_info
**
** In addition, any changes made to this file will require the Sybase SQL
** server to be recertified as ODBC compliant by the certification group
** at Sybase (current name is "Interoperability Engineering Technology
** Solutions Group").
*/
/*
** raiserror Messages for a_mstables [Total 1]
**
** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
*/

use sybsystemprocs
go

if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go

/*
** spt_datatype_info_ext
*/

if (exists (select * from sysobjects
		where name = 'spt_datatype_info_ext' and type = 'U'))
    drop table spt_datatype_info_ext
go
create table spt_datatype_info_ext 
(
	user_type	smallint  not null, 
	create_params	varchar(32) null
) lock allpages
go

grant select on spt_datatype_info_ext to public
go


insert into spt_datatype_info_ext
	/* CHAR 	 user_type, create_params */
	values			 (1, "length" )

insert into spt_datatype_info_ext
	/* VARCHAR	 user_type, create_params */
	values			 (2, "max length" )

insert into spt_datatype_info_ext
	/* BINARY	 user_type, create_params */
	values			 (3, "length" )

insert into spt_datatype_info_ext
	/* VARBINARY	 user_type, create_params */
	values			 (4, "max length" )

insert into spt_datatype_info_ext
	/* NUMERIC	 usertype, create_params */
	values			 (10, "precision,scale" )

insert into spt_datatype_info_ext
	/* SYSNAME	 user_type, create_params */
	values			 (18, "max length" )

insert into spt_datatype_info_ext
	/* NCHAR 	 user_type, create_params */
	values			 (24, "length" )

insert into spt_datatype_info_ext
	/* NVARCHAR	 user_type, create_params */
	values			 (25, "max length" )

insert into spt_datatype_info_ext
	/* DECIMAL	 usertype, create_params */
	values			 (26, "precision,scale" )

insert into spt_datatype_info_ext
	/* UNICHAR 	 user_type, create_params */
	values			 (34, "length" )

insert into spt_datatype_info_ext
	/* UNIVARCHAR	 user_type, create_params */
	values			 (35, "max length" )

insert into spt_datatype_info_ext
	/* LONGSYSNAME	 user_type, create_params */
	values			 (42, "max length" )
go

/* 
** spt_datatype_info
*/
if (exists (select * from sysobjects
		where name = 'spt_datatype_info' and type = 'U'))
    drop table spt_datatype_info
go
create table spt_datatype_info 
(
	ss_dtype	   tinyint	not null, 
	type_name          varchar(32)  not null, 
	data_type          smallint     not null, 
	data_precision     int          null, 
	numeric_scale      smallint     null, 
	numeric_radix      smallint     null, 
	length             int          null, 
	literal_prefix     varchar(32)  null, 
	literal_suffix     varchar(32)  null, 
	create_params      varchar(32)  null, 
	nullable           smallint     not null, 
	case_sensitive     smallint     not null, 
	searchable         smallint     not null, 
	unsigned_attribute smallint     null, 
	money              smallint     not null, 
	auto_increment     smallint     null, 
	local_type_name    varchar(128) not null, 
	aux                int          null,
        maximum_scale      smallint     null,
        minimum_scale      smallint     null,
        sql_data_type      smallint     null,
        sql_datetime_sub   smallint     null,
        num_prec_radix     smallint     null,
        interval_precision smallint     null
) lock allpages
go

grant select on spt_datatype_info to public
go

/*
**	There is a complicated set of SQL used to deal with
**	the SQL Server Null data types (MONEYn, INTn, etc.)
**	ISNULL is the only conditional SQL Server function that can be used
**	to differentiate between these types depending on size.
**
**	The aux column in the above table is used to differentiate
**	the null data types from the non-null types.
**
**	The aux column contains NULL for the null data types and 0
**	for the non-null data types.
**
**	The following SQL returns the contents of the aux column (0)
**	for the non-null data types and returns a variable non-zero
**	value for the null data types.
**
**			 " I   I I FFMMDD"
**			 " 1   2 4 484848"
**	isnull(d.aux, ascii(substring("666AAA@@@CB??GG", 
**	2*(d.ss_dtype%35+1)+2-8/c.length, 1))-60)
**
**	The '2*(d.ss_dtype%35+1)+2-8/c.length' selects a specific character of
**	the substring mask depending on the null data type and its size, i.e.
**	null MONEY4 or null MONEY8.  The character selected is then converted
**	to its binary value and an appropriate bias (i.e. 60) is subtracted to
**	return the correct non-zero value.	This value may be used as a
**	constant, i.e. ODBC data type, precision, scale, etc., or used as an
**	index with a substring to pick out a character string, i.e. type name.
**
**	The comments above the substring mask denote which character is
**	selected for each null data type, i.e. In (INTn), Fn (FLOATn), 
**	Mn (MONEYn) and Dn (DATETIMn).
*/


declare @case smallint

select @case = 0
select @case = 1 where 'a' != 'A'

/* Local Binary */
insert into spt_datatype_info values
/* ss_type, name, data_type, prec, scale, rdx, len, prf, suf, 
** cp, nul, case, srch, unsigned, money, auto, local, aux 
*/
(45, "binary", -2, null, null, null, null, "0x", null, 
 "length", 1, 0, 2, null, 0, null, "binary", 0,
 null, null, null, null, null, null)

/* Local Bit */
insert into spt_datatype_info values
(50, "bit", -7, 1, 0, 2, null, null, null, 
 null, 0, 0, 2, null, 0, null, "bit", 0,
 null, null, null, null, null, null)

/* Local Char */
insert into spt_datatype_info values
(47, "char", 1, null, null, null, null, "'", "'", 
"length", 1, @case, 3, null, 0, null, "char", 0,
 null, null, null, null, null, null)

/* Local Unichar */
insert into spt_datatype_info values
(135, "unichar", -8, null, null, null, null, "'", "'", 
"length", 1, @case, 3, null, 0, null, "unichar", 0,
 null, null, null, null, null, null)

/* Local Datetime */
insert into spt_datatype_info values
(61, "datetime", 11, 23, 3, 10, 16, "'", "'", 
 null, 1, 0, 3, null, 0, null, "datetime", 0,
 null, null, 93, null, null, null)

/* Local Bigdatetime */
insert into spt_datatype_info values
(189, 'bigdatetime', 11, 26, 6, 10, 16, "'", "'", 
 null, 1, 0, 3, null, 0, null, 'bigdatetime', 0,
  null, null, 93, null, null, null)

/* Local Smalldatetime */
insert into spt_datatype_info values
(58, "smalldatetime", 11, 16, 0, 10, 16, "'", "'", 
 null, 1, 0, 3, null, 0, null, "smalldatetime", 0,
 null, null, 93, null, null, null)

/* Local Datetimn  sql server type is "datetimn" */
insert into spt_datatype_info values
(111, "smalldatetime", 0, 0, 0, 10, 0, "'", "'", 
 null, 1, 0, 3, null, 0, null, "datetime", null,
 null, null, 93, null, null, null)

/* Decimal sql server type is "decimal" */
insert into spt_datatype_info values
(55, "decimal", 3, 38, 0, 10, null, null, null,
"precision,scale", 1, 0, 2, 0, 0, 0, "decimal", 0,
 38, 0, null, null, null, null)

/* Date sql server type is "date" */
insert into spt_datatype_info values
(49, "date", 9, 10, 0, 10, null, "'", "'",
 null, 1, 0, 3, null, 0, null, "date", 0,
 null, null, 91, null, null, null)

/* Time sql server type is "time" */
insert into spt_datatype_info values
(51, "time", 10, 12, 3, 10, null, "'", "'",
 null, 1, 0, 3, null, 0, null, "time", 0,
 null, null, 92, null, null, null)

/* Bigtime sql server type is "bigtime" */
insert into spt_datatype_info values
(190, "bigtime", 10, 15, 6, 10, null, "'", "'",
 null, 1, 0, 3, null, 0, null, "bigtime", 0,
  null, null, 92, null, null, null)

/* Numeric sql server type is "numeric" */
insert into spt_datatype_info values
(63, "numeric", 2, 38, 0, 10, null, null, null,
"precision,scale", 1, 0, 2, 0, 0, 0, "numeric", 0,
 38, 0, null, null, null, null)

/* Local Float */
insert into spt_datatype_info values
(62, "float", 6, 15, null, 10, null, null, null, 
 null, 1, 0, 2, 0, 0, 0, "float", 0,
 null, null, null, null, 10, null)

/* Local RealFloat   sql server type is "floatn" */
insert into spt_datatype_info values
(109, "float        real", 0, 0, null, 10, 0, null, null, 
 null, 1, 0, 2, 0, 0, 0, "real      float", null,
 null, null, null, null, 10, null)

/* Local Real */
insert into spt_datatype_info values
(59, "real", 7, 7, null, 10, null, null, null,
 null, 1, 0, 2, 0, 0, 0, "real", 0,
 null, null, null, null, 10, null)

/* Local Smallmoney */
insert into spt_datatype_info values
(122, "smallmoney", 3, 10, 4, 10, null, "$", null, 
 null, 1, 0, 2, 0, 1, 0, "smallmoney", 0,
 null, null, null, null, null, null)

/* Local Bigint */
insert into spt_datatype_info values
(191, "bigint", -5, 19, 0, 10, null, null, null,
 null, 1, 0, 2, 0, 0, 0, "bigint", 0,
 null, null, null, null, null, null)

/* Local Ubigint */
insert into spt_datatype_info values
(67, "unsigned bigint", -5, 20, 0, 10, null, null, null,
 null, 1, 0, 2, 1, 0, 0, "ubigint", 0,
 null, null, null, null, null, null)

/* Local Int */
insert into spt_datatype_info values
(56, "int", 4, 10, 0, 10, null, null, null, 
 null, 1, 0, 2, 0, 0, 0, "int", 0,
 null, null, null, null, null, null)

/* Local Intn  sql server type is "intn" */
insert into spt_datatype_info values
(38, "smallint     tinyint", 0, 0, 0, 10, 0, null, null, 
 null, 1, 0, 2, 0, 0, 0, "tinyint   smallint", null,
 null, null, null, null, null, null)

/* Local uint */
insert into spt_datatype_info values
(66, "unsigned int", 4, 10, 0, 10, null, null, null,
 null, 1, 0, 2, 1, 0, 0, "uint", 0,
 null, null, null, null, null, null)

/* Local unsigned intn  sql server type is "uintn" */
insert into spt_datatype_info values
(68, "usmallint    ubigint", 0, 0, 0, 20, 0, null, null,
 null, 1, 0, 2, 1, 0, 0, "ubigint   usmallint", null,
 null, null, null, null, null, null)

/* Local Money */
insert into spt_datatype_info values
(60, "money", 3, 19, 4, 10, null, "$", null, 
 null, 1, 0, 2, 0, 1, 0, "money", 0,
 null, null, null, null, null, null)

/* Local Moneyn  sql server type is "moneyn" */
insert into spt_datatype_info values
(110, "smallmoney", 0, 0, 4, 10, 0, "$", null, 
 null, 1, 0, 2, 0, 1, 0, "smallmoneymoney", null,
 null, null, null, null, null, null)

/* Local Smallint */
insert into spt_datatype_info values
(52, "smallint", 5, 5, 0, 10, null, null, null, 
 null, 1, 0, 2, 0, 0, 0, "smallint", 0,
 null, null, null, null, null, null)

/* Local usmallint */
insert into spt_datatype_info values
(65, "unsigned smallint", 5, 5, 0, 10, null, null, null,
 null, 1, 0, 2, 1, 0, 0, "usmallint", 0,
 null, null, null, null, null, null)

/* Local Text */
insert into spt_datatype_info values
(35, "text", -1, 2147483647, null, null, 2147483647, "'", "'", 
 null, 1, @case, 1, null, 0, null, "text", 0,
 null, null, null, null, null, null)

/* Local Unitext */
insert into spt_datatype_info values
(174, "unitext", -10, 2147483647, null, null, 2147483647, "'", "'", 
 null, 1, @case, 1, null, 0, null, "unitext", 0,
 null, null, null, null, null, null)

/* Local Varbinary */
insert into spt_datatype_info values
(37, "varbinary", -3, null, null, null, null, "0x", null, 
 "max length", 1, 0, 2, null, 0, null, "varbinary", 0,
 null, null, null, null, null, null)

/* Local Tinyint */
insert into spt_datatype_info values
(48, "tinyint", -6, 3, 0, 10, null, null, null, 
 null, 1, 0, 2, 1, 0, 0, "tinyint", 0,
 null, null, null, null, null, null)

/* Local Varchar */
insert into spt_datatype_info values
(39, "varchar", 12, null, null, null, null, "'", "'", 
"max length", 1, @case, 3, null, 0, null, "varchar", 0,
 null, null, null, null, null, null)

/* Local Univarchar */
insert into spt_datatype_info values
(155, "univarchar", -9, null, null, null, null, "'", "'", 
"max length", 1, @case, 3, null, 0, null, "univarchar", 0,
 null, null, null, null, null, null)

/* Local Image */
insert into spt_datatype_info values
(34, "image", -4, 2147483647, null, null, 2147483647, "0x", null, 
 null, 1, 0, 1, null, 0, null, "image", 0,
 null, null, null, null, null, null)

/* Java Object for ASE 12 */
insert into spt_datatype_info values
(36, 'java.lang.Object', 1111, 2147483647, null, null, 2147483647, "'", "'",
null, 1, @case, 1, null, 0, null, 'java.lang.Object', 0,
 null, null, null, null, null, null)
go

dump tran master with truncate_only
go

/*
** spt_server_info
*/
if (exists (select * from sysobjects
		where name = 'spt_server_info' and type = 'U'))
    drop table spt_server_info
go
create table spt_server_info (
	  attribute_id		int, 
	  attribute_name	varchar(60), 
	  attribute_value	varchar(255)) lock allpages
go

insert into spt_server_info
	values (1, "DBMS_NAME", "SQL Server")

/* 
** DO NOT change the DBMS_VER value!    It is NOT supposed to be
** the same as @@version, even though ASE RefMan indicates otherwise.
** This value needs to be kept in-sync with ODBC driver from Merant/Intersolv,
** so this may only be changed in accordance with the driver.  Also see 
** note at the beginning of this file.
*/
insert into spt_server_info
	values (2, "DBMS_VER", 
   "SQL Server/12.5/P/Generic/OS/1/OPT/Sat Jun 30 00:01:37 PDT 2001")

insert into spt_server_info
	values (6, "DBE_NAME", "")
insert into spt_server_info
	values (10, "OWNER_TERM", "owner")
insert into spt_server_info
	values (11, "TABLE_TERM", "table")
insert into spt_server_info
	values (12, "MAX_OWNER_NAME_LENGTH", "30")
insert into spt_server_info
	values (16, "IDENTIFIER_CASE", "MIXED")
insert into spt_server_info
	values (15, "COLUMN_LENGTH", "255")
insert into spt_server_info
	values (13, "TABLE_LENGTH", "255")
insert into spt_server_info
	values (100, "USERID_LENGTH", "30")
insert into spt_server_info
	values (17, "TX_ISOLATION", "4")
insert into spt_server_info
	values (18, "COLLATION_SEQ", "")
insert into spt_server_info
	values (14, "MAX_QUAL_LENGTH", "30")
insert into spt_server_info
	values (101, "QUALIFIER_TERM", "database")
insert into spt_server_info
	values (19, "SAVEPOINT_SUPPORT", "Y")
insert into spt_server_info
	values (20, "MULTI_RESULT_SETS", "Y")
insert into spt_server_info
	values (102, "NAMED_TRANSACTIONS", "Y")
insert into spt_server_info
	values (103, "SPROC_AS_LANGUAGE", "Y")
insert into spt_server_info
	values (103, "REMOTE_SPROC", "Y")
insert into spt_server_info
	values (22, "ACCESSIBLE_TABLES", "Y")
insert into spt_server_info
	values (104, "ACCESSIBLE_SPROC", "Y")
insert into spt_server_info
	values (105, "MAX_INDEX_COLS", "32")
insert into spt_server_info
	values (106, "RENAME_TABLE", "Y")
insert into spt_server_info
	values (107, "RENAME_COLUMN", "Y")
insert into spt_server_info
	values (108, "DROP_COLUMN", "Y")
insert into spt_server_info
	values (109, "INCREASE_COLUMN_LENGTH", "N")
insert into spt_server_info
	values (110, "DDL_IN_TRANSACTION", "Y")
insert into spt_server_info
	values (111, "DESCENDING_INDEXES", "Y")
insert into spt_server_info
	values (112, "SP_RENAME", "Y")
go
/*
** NOTE: the following applies to Microsoft changes, not Sybase.  Do not change
** for Sybase check-ins unless we are synchronizing with Microsoft changes.
**
** The last row in spt_server_info has been used as the version number of the 
** file. The convention is jj.nn.dddd, where:
** 	jj is the major version number ("01" now), 
**	nn is the minor version number ("01" now), and 
**	dddd is the date in the form of month and day (mmdd) of the date you 
**	check in this file.  Add (current year-1991)*12 to the month to keep 
**	in sync with the driver version numbers.  Checking in on Feb 5 1993
**	would mean setting the value to 01.01.2605.
**
*/
insert into spt_server_info
	values (500, "SYS_SPROC_VERSION", "01.01.2822")
go
go
dump transaction sybsystemprocs with truncate_only
go
/* Temporarily create the #tempmonitors, #tempconfigures
** and #devicemap tables so that they exists for the creation
** of subordinate sysmon stored procedures.
**
** Only the creation of these temporary tables are required, there 
** is no need to have any row in the tables.
**
** WARNING:
**	If you make any changes to modify the table schema, changes
**	need to be done in sp_sysmon stored procedure also.
**
** These will be dropped before sp_sysmon is loaded.
**
**  History:
**	01/25/96 (maxb)   Created for bugid 82625
**	11/23/98 (rajesh) Changed the style  of creating tables
**			  to have consistent declarations
*/

/* Creating  temporary table #tempmonitors from sysmonitors */
select * into #tempmonitors from master.dbo.sysmonitors where 1 = 2

/* Creating table #tempconfigures from sysconfigures and syscurconfigs */ 
select name, convert(varchar(255), value) as value into 
#tempconfigures from master..sysconfigures  where 1 = 2

/* Creating temporary table #devicemap */
create table #devicemap(name char(40),
			phyname char(127),
			group_name char(24))
go

create table #obj_details(dbid int, owner varchar(30), objid int,
			indid int, index_name varchar(30),
			size_KB int)
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ha_check_certified')
begin
	drop procedure sp_ha_check_certified
end
go
print "Installing sp_ha_check_certified"
go

/* 
** ha_temp_install is created to remember the fact that installmaster or
** installhasvss is in progress.  This is done only if the server has HA
** feature enabled.  Any change to this table's schema should be made in 
** crthatables also.
**
**  History:
**	09/3/99 (raghavan)   Created for HA
*/

/* 
** Creating temporary table ha_temp_install in tempdb to 
** remember the fact that installmaster is in progress 
*/
if (exists (select 1 from tempdb.dbo.sysobjects where 
	name = 'ha_temp_install' and type = 'U'))
		drop table tempdb.dbo.ha_temp_install 
go

create table tempdb.dbo.ha_temp_install (install_in_progress tinyint) 
					lock allpages
go

/* Procedures to check if a SP is HA compliant or NOT */
if exists (select * from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ha_check_certified')
begin
	print "Dropping sp_ha_check_certified"
	drop procedure sp_ha_check_certified
end
go

create procedure sp_ha_check_certified 
	@proc_name varchar(100),
	@ha_certified tinyint
as

declare @IN_install  tinyint 	/* Is installmaster/installhasvss
			     	** in progress ?
			     	*/
set nocount on
select @IN_install = 0

/* See if we are using HA specific SP for a HA enabled server */

if ((@@cmpstate > 0) and (@ha_certified = 0))
begin
		if (exists (select 1 from tempdb.dbo.sysobjects where 
			name = 'ha_temp_install' and type = 'U'))
		begin
			select @IN_install = 1 
		end

		/*
		** During installmaster/installhasvss, we do not want to raise
		** an error when a non HA version of the SP is invoked.
		*/
		if (@IN_install = 0)
		begin
			/*raiserror 18842, @@servername, @proc_name */
			print "Server '%1!' is booted with 'enable HA configuration option', but the procedure '%2!' is not of HA version. Please check if 'installhasvss' has been run.", @@servername, @proc_name
			return (1)
		end
end

set nocount off
return (0)

go
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

/*
** raiserror Messages for a_datatypes [Total 1]
**
** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
*/

/*
**   spt_jdatatype_info
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go

if (exists (select * from sysobjects
		where name = 'spt_jdatatype_info' and type = 'U'))
    drop table spt_jdatatype_info
go
/** SECTION END: CLEANUP **/

create table spt_jdatatype_info 
(
	ss_dtype	   tinyint	not null, 
	type_name          varchar(32)  null, 
	data_type          smallint     not null, 
	data_precision     int          null, 
	numeric_scale      smallint     null, 
	numeric_radix      smallint     null, 
	length             int          null, 
	literal_prefix     varchar(32)  null, 
	literal_suffix     varchar(32)  null, 
	create_params      varchar(32)  null, 
	nullable           smallint     not null, 
	case_sensitive     smallint     not null, 
	searchable         smallint     not null, 
	unsigned_attribute smallint     null, 
	money              smallint     not null, 
	auto_increment     smallint     null, 
	local_type_name    varchar(128) not null, 
	aux                int          null,
	maximum_scale	   smallint	null,
	minimum_scale	   smallint	null,
	sql_data_type	   smallint	null,
	sql_datetime_sub   smallint	null,
	num_prec_radix	   smallint	null,
	interval_precision smallint	null
)
go

grant select on spt_jdatatype_info to public
go

/*
**	There is a complicated set of SQL used to deal with
**	the SQL Server Null data types (MONEYn, INTn, etc.)
**	ISNULL is the only conditional SQL Server function that can be used
**	to differentiate between these types depending on size.
**
**	The aux column in the above table is used to differentiate
**	the null data types from the non-null types.
**
**	The aux column contains NULL for the null data types and 0
**	for the non-null data types.
**
**	The following SQL returns the contents of the aux column (0)
**	for the non-null data types and returns a variable non-zero
**	value for the null data types.
**
**			 ' I   I I FFMMDD'
**			 ' 1   2 4 484848'
**	isnull(d.aux, ascii(substring('666AAA@@@CB??GG', 
**	2*(d.ss_dtype%35+1)+2-8/c.length, 1))-60)
**
**	The '2*(d.ss_dtype%35+1)+2-8/c.length' selects a specific character of
**	the substring mask depending on the null data type and its size, i.e.
**	null MONEY4 or null MONEY8.  The character selected is then converted
**	to its binary value and an appropriate bias (i.e. 60) is subtracted to
**	return the correct non-zero value.	This value may be used as a
**	constant, i.e. ODBC data type, precision, scale, etc., or used as an
**	index with a substring to pick out a character string, i.e. type name.
**
**	The comments above the substring mask denote which character is
**	selected for each null data type, i.e. In (INTn), Fn (FLOATn), 
**	Mn (MONEYn) and Dn (DATETIMn).
*/


declare @case smallint

select @case = 0
select @case = 1 where 'a' != 'A'

/* Local Binary */
insert into spt_jdatatype_info values
/* ss_type, name, data_type, prec, scale, rdx, len, prf, suf, 
** cp, nul, case, srch, unsigned, money, auto, local, aux 
*/
(45, 'binary', -2, null, null, null, null, '0x', null, 
 'length', 1, 0, 2, null, 0, null, 'binary', 0,
 null, null, null, null, null, null)

/* Local Bit */
insert into spt_jdatatype_info values
(50, 'bit', -7, 1, 0, 2, null, null, null, 
 null, 0, 0, 2, null, 0, null, 'bit', 0,
 null, null, null, null, null, null)

/* Local Char */
insert into spt_jdatatype_info values
(47, 'char', 1, null, null, null, null, '''', '''', 
'length', 1, @case, 3, null, 0, null, 'char', 0,
 null, null, null, null, null, null)

/* Local Bigdatetime */
insert into spt_jdatatype_info values
(189, 'bigdatetime', 11, 26, 6, 10, 16, '''', '''',
 null, 1, 0, 3, null, 0, null, 'bigdatetime', 0,
 null, null, 93, null, null, null)

/* Local Datetime */
insert into spt_jdatatype_info values
(61, 'datetime', 93, 23, 3, 10, 16, '''', '''', 
 null, 1, 0, 3, null, 0, null, 'datetime', 0,
 null, null, 93, null, null, null)

/* Local Smalldatetime */
insert into spt_jdatatype_info values
(58, 'smalldatetime', 93, 16, 0, 10, 16, '''', '''', 
null, 1, 0, 3, null, 0, null, 'smalldatetime', 0,
 null, null, 93, null, null, null)

/* Local Datetimn  sql server type is 'datetimn' */
insert into spt_jdatatype_info values
(111, 'smalldatetime', 93, 0, 0, 10, 0, '''', '''', 
null, 1, 0, 3, null, 0, null, 'datetime', null,
 null, null, 93, null, null, null)

/* Date sql server type is "date" */
insert into spt_jdatatype_info values
(49, "date", 9, 10, 0, 10, null, "'", "'",
 null, 1, 0, 3, null, 0, null, "date", 0,
 null, null, 91, null, null, null)

/* Time sql server type is "time" */
insert into spt_jdatatype_info values
(51, "time", 10, 12, 3, 10, null, "'", "'",
 null, 1, 0, 3, null, 0, null, "time", 0,
 null, null, 92, null, null, null)

/* Bigtime sql server type is "bigtime" */
insert into spt_jdatatype_info values
(190, "bigtime", 10, 15, 6, 10, null, "'", "'",
 null, 1, 0, 3, null, 0, null, "bigtime", 0,
 null, null, 92, null, null, null)

/* Decimal sql server type is 'decimal' */
insert into spt_jdatatype_info values
(55, 'decimal', 3, 38, 0, 10, 0, null, null,
'precision,scale', 1, 0, 2, 0, 0, 0, 'decimal', 0,
 38, 0, null, null, null, null)

/* Numeric sql server type is 'numeric' */
insert into spt_jdatatype_info values
(63, 'numeric', 2, 38, 0, 10, 0, null, null,
'precision,scale', 1, 0, 2, 0, 0, 0, 'numeric', 0,
 38, 0, null, null, null, null)

/* Local RealFloat   sql server type is 'floatn' */
insert into spt_jdatatype_info values
(109, 'float        real', 1111, 0, null, 10, 0, null, null, 
null, 1, 0, 2, 0, 0, 0, 'real      float', null,
 null, null, null, null, 10, null)

/* Local Real */
insert into spt_jdatatype_info values
(59, 'real', 7, 7, null, 10, null, null, null,
null, 1, 0, 2, 0, 0, 0, 'real', 0,
 null, null, null, null, 10, null)

/* Local Double */
insert into spt_jdatatype_info values
(62, 'double precision', 8, 15, null, 10, null, null, null,
null, 1, 0, 2, 0, 0, 0, 'double precision', 0,
 null, null, null, null, 10, null)

/* Local Smallmoney */
insert into spt_jdatatype_info values
(122, 'smallmoney', 3, 10, 4, 10, null, '$', null, 
null, 1, 0, 2, 0, 1, 0, 'smallmoney', 0,
 4, 4, null, null, null, null)

/* Local Int */
insert into spt_jdatatype_info values
(56, 'int', 4, 10, 0, 10, null, null, null, 
null, 1, 0, 2, 0, 0, 0, 'int', 0,
 null, null, null, null, null, null)

/* Local Intn  sql server type is 'intn' */
insert into spt_jdatatype_info values
(38, 'smallint     tinyint', 1111, 0, 0, 10, 0, null, null, 
null, 1, 0, 2, 0, 0, 0, 'tinyint   smallint', null,
 null, null, null, null, null, null)

/* Local Money */
insert into spt_jdatatype_info values
(60, 'money', 3, 19, 4, 10, null, '$', null, 
null, 1, 0, 2, 0, 1, 0, 'money', 0,
 4, 4, null, null, null, null)

/* Local Moneyn  sql server type is 'moneyn'*/ 
insert into spt_jdatatype_info values
(110, 'moneyn', 3, 0, 4, 10, 0, '$', null, 
null, 1, 0, 2, 0, 1, 0, 'moneyn', null,
 4, 4, null, null, null, null)

/* Local Smallint */
insert into spt_jdatatype_info values
(52, 'smallint', 5, 5, 0, 10, null, null, null, 
null, 1, 0, 2, 0, 0, 0, 'smallint', 0,
 null, null, null, null, null, null)

/* Local Text */
insert into spt_jdatatype_info values
(35, 'text', -1, 2147483647, null, null, 2147483647, '''', '''', 
null, 1, @case, 1, null, 0, null, 'text', 0,
 null, null, null, null, null, null)

/* Java Object for ASE 12 */
insert into spt_jdatatype_info values
(36, 'java.lang.Object', 1111, 2147483647, null, null, 2147483647, '''', '''', 
null, 1, @case, 1, null, 0, null, 'java.lang.Object', 0,
 null, null, null, null, null, null)

/* Local Varbinary */
insert into spt_jdatatype_info values
(37, 'varbinary', -3, null, null, null, null, '0x', null, 
'max length', 1, 0, 2, null, 0, null, 'varbinary', 0,
 null, null, null, null, null, null)

/* Local Tinyint */
insert into spt_jdatatype_info values
(48, 'tinyint', -6, 3, 0, 10, null, null, null, 
null, 1, 0, 2, 1, 0, 0, 'tinyint', 0,
 null, null, null, null, null, null)

/* Local Varchar */
insert into spt_jdatatype_info values
(39, 'varchar', 12, null, null, null, null, '''', '''', 
'max length', 1, @case, 3, null, 0, null, 'varchar', 0,
 null, null, null, null, null, null)

/* Local Image */
insert into spt_jdatatype_info values
(34, 'image', -4, 2147483647, null, null, 2147483647, '0x', null, 
null, 1, 0, 1, null, 0, null, 'image', 0,
 null, null, null, null, null, null)
go

dump tran master with truncate_only
go

/*
**   End of spt_jdatatype_info
*/

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_procxmode')
begin
	drop procedure sp_procxmode
end
go
print "Installing sp_procxmode"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
*/

create procedure sp_procxmode
@procname varchar(767) = null,
@execmode varchar(30) = null
as

declare @uid int
declare @oid int
declare @msg varchar(250)	/* message text */
declare @dbname varchar(255)
declare @owner varchar(30)
declare @objname varchar(257)
declare @objid int
declare @alltranmask int
declare @retcode int
declare @cmd varchar(255)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* 
** If either parameter is null we will be joining with a temporary table
** to convert transaction mode numbers (0, 16, 32, 256) to strings 
** ("Unchained", "Chained", "Any Mode", "Dynamic Ownership Chain").
** The "Dynamic Ownership Chain" is not an exclusive mode. It exists 
** in conjunction with one of the other three.
*/
if ((@procname is null) or (@execmode is null))
begin
	create table #execmode (intval integer, charval varchar(30))
	insert into #execmode values(0,  'Unchained')
	insert into #execmode values(16, 'Chained')
	insert into #execmode values(32, 'Any Mode')
	insert into #execmode values(256,'Dynamic Ownership Chain')

	select @alltranmask = 16 + 32
end

/* 
** If the first parameter is null, we're to report the transaction-modes
** of every stored procedure in the current database.
*/
if (@procname is null)
begin
	select 'procedure name' = o.name, 'user name' = user_name(o.uid),
		'transaction mode' = t.charval
	from sysobjects o, #execmode t
	where	((o.type = 'P') or (o.type = 'XP')) and
 		(((o.sysstat2 & t.intval ) != 0) or
		 ((t.intval = 0) and (o.sysstat2 & @alltranmask) = 0))
	order by o.name

	return(0)
end

/* 
** If only the second parameter is null, we will report the
** transaction-mode of the specified procedure.
*/
if ((@procname is not null) and (@execmode is null))
begin
	/* 
	** Check if proc name is prefixed with the dbname. The proc sp_namecrack
	** cannot be used, because sp_procxmode is created before and it
	** would cause a dependency failure at creation time.
	*/
	if @procname like "%.%.%.%"
	begin
        	select @procname = substring(@procname, charindex(".", @procname) + 1, 125)
	end

	if @procname like "%.%.%"
	begin
	        select @dbname = substring(@procname, 1, charindex(".", @procname) - 1)
        	select @procname = substring(@procname, charindex(".", @procname) + 1, 125)
	end

	if @procname like "%.%"
	begin
        	select @owner = substring(@procname, 1, charindex(".", @procname) - 1)
        	select @procname = substring(@procname, charindex(".", @procname) + 1, 125)
	end

	select @objname = @procname

	/*
	** If a database qualifies, it has to be this database.
	** Execute the procedure in the target database.
	*/
	if ((@dbname is not null) and (@dbname != db_name()))
	begin
		select @cmd = @dbname + '.dbo.sp_procxmode'
		select @procname = @owner + '.' + @objname
		exec @retcode = @cmd @procname
		return (@retcode)
	end

	select @objid = object_id(@procname)
	if (@objid is not null)
	begin
		if not exists(select 1 from sysobjects
			where id = @objid 
			and type in ('P', 'XP'))
		begin
			select @objid = null
		end
	end

	if (@objid is null)
	begin
		/*
		** Force an error message, since we haven't
		** installed sp_getmessage yet.
		*/
		dbcc update_tmode(@procname, 'anymode')
		return (1)
	end

 
	select 'procedure name' = o.name, 'user name' = user_name(o.uid),
		'transaction mode' = t.charval
	from sysobjects o, #execmode t
	where	(@objid = o.id) and
		((o.type = 'P') or (o.type = 'XP')) and
 		(((o.sysstat2 & t.intval ) != 0) or
		 ((t.intval = 0) and (o.sysstat2 & @alltranmask) = 0))

	return(0)
end

/* 
** If neither parameter is null, we're to set the transaction-mode
** of the specified procedure to the specified value.
*/
if ((@procname is not null) and (@execmode is not null))
begin
	/* Start the transaction to log the execution of this procedure.
	**
	** IMPORTANT: The name "rs_logexec is significant and is used by 
	**            Replication Server
	*/
	begin transaction rs_logexec

	/*
	** Update transaction-mode in both sysobjects and DES.
	*/
	dbcc update_tmode(@procname, @execmode)

	/* If dbcc update_tmode returned an error, return
	** an error now.
	*/
	if (@@error != 0)
	begin
		rollback transaction
		return(1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, 'sp_procxmode', @dbname
		rollback transaction
		return(1)
	end
		
	commit transaction

end
go
exec sp_procxmode 'sp_procxmode', 'anymode'
go
grant execute on sp_procxmode to public
go
exec sp_procxmode 'sp_procxmode', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_validlang')
begin
	drop procedure sp_validlang
end
go
print "Installing sp_validlang"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */
create procedure sp_validlang
@name	varchar(255)
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Check to see if this language is in Syslanguages. */
if exists (select *
		from master.dbo.syslanguages
		where name = @name)
begin
	return 0
end
return 1
go
exec sp_procxmode 'sp_validlang', 'anymode'
go
grant execute on sp_validlang to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_getmessage')
begin
	drop procedure sp_getmessage
end
go
print "Installing sp_getmessage"
go


/* generic/sproc/getmessage	14.2	4/25/91 */

/* Messages from sysmessages
** 17200, "Message number must be greater than or equal to 17000."
** 17201, "'%1!' is not an official language name from Syslanguages."
** 17202, "Message number %1! does not exist in the %2! language."
*/

create procedure sp_getmessage
@message_num int,
@result varchar(1024) output,
@language varchar(30) = NULL
as

	declare @lang_id smallint 
	declare @msg varchar(1024)
	declare @returncode smallint

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* 
	** Use default language if none specified, 
	** and initialize result 
	*/
	select @lang_id = @@langid, @result = NULL

	/* Only retrieve external errors */
	if @message_num < 17000
	BEGIN
 		/* 17200   "Message number must be greater than or equal to 17000." */
		 select @msg = description from master.dbo.sysmessages
				    where error = 17200
		 print @msg
		 return (1)
	END

	/*
	** Check that language is valid.
	*/
	if @language is not NULL
	BEGIN
	    execute @returncode = sp_validlang @language
	    if @returncode != 0
	    begin
		    /* Us_english is always valid */
		    if @language != "us_english"
		    BEGIN
			    /* 
			    ** 17201, "'%1!' is not an official language
			    **	name from Syslanguages."
			    */
			    select @msg = description from master.dbo.sysmessages
						where error = 17201
						and langid = @@langid

			    /* Get english if the current language is missing */
			    if @msg is null
				select @msg = description from master.dbo.sysmessages
						where error = 17201
						and langid is NULL

			    print @msg, @language
			    return @returncode
		    END

		    /* set to us_english */
		    select @lang_id = NULL
	    end

	    else
	    select @lang_id = langid from master.dbo.syslanguages
			where @language = name

	END

	/* The langid is assigned 0 since it gets its value from @@langid. */
	/* For us_english, we have to insert it as NULL and not 0, this is */
	/* to maintain compatibility with the current conventions          */
	if @lang_id = 0 
	begin 
		select @lang_id = NULL        
	end   

	/* Get message from the proper place */
	/* System messages */
	if @message_num < 20000
	BEGIN
		select @result = description from master.dbo.sysmessages
			   where  langid = @lang_id 
			     and   error = @message_num 

		/* Get english if the current language is missing */
		if @result is null
			select @result = description from master.dbo.sysmessages
                                        where error = @message_num
                                        and (langid is NULL or langid =0)
	END
	else
	/* User messages */
	BEGIN
		/* There is no proper alternate language for user messages */
		select @result = description from sysusermessages
			   where  langid = @lang_id 
			     and   error = @message_num 

		/* this is in here for compatibility with older revs which */
		/* by mistake used to add langid as 0 in sysusermessages   */
		if @result is null and @lang_id is NULL
			select @result = description from sysusermessages
					where (langid = 0 or langid is NULL)
					and error = @message_num

	END

	/* Warn the user if the message can't be found */
	if @result is null
	begin
		/* 17202, "Message number %1! does not exist in the %2! language." */
		select @msg = description from master.dbo.sysmessages
			where error = 17202
			and langid = @@langid

		if @language is null
			select @language = @@language

		if @msg is null
			select @msg = "Message number %1! does not exist in the %2! language."

		print @msg, @message_num, @language

		return (1)
	end

return (0)
go
exec sp_procxmode 'sp_getmessage', 'anymode'
go
grant execute on sp_getmessage to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_getsize')
begin
	drop procedure sp_aux_getsize
end
go
print "Installing sp_aux_getsize"
go

/* This stored procedure is for parsing a size string of the form:
**		 "%f[pPkKmMgG]
** and return the value in equivalent "k" units if @format_str is NULL.
** If a format string is specified then another conversion to the required
** format is done. @output_str has the string equivalent of the return value.
** If a format string is specified then @ret_size value will be set to 0.
** For example sp_aux_getsize "1024K",@ret_size, "M" will put 1 in @ret_size.
**
**	Messages for sp_aux_getsize
** 
** 18146, "Syntax error encountered. Sizes must be of the form int[KMGP].
**         For example, a size of 5 megabytes may be specified as '5M'."
**
** 18149, "Invalid size of %1! encountered. Sizes must be greater than zero."
*/
create procedure sp_aux_getsize
@size_str		varchar(30),
@ret_size		int output,
@input_size		int = NULL,
@output_str		varchar(30) = NULL output
as

declare 
	@unit_loc		int,
	@multiplier		int,
	@one_char		char(1),
	@digits			varchar(30),
	@units			varchar(30),
	@float_size		float,
	@count			int,
	@found_invalid_char	int,
	@num_decimal		int,
	@digit_str_len		int

select @unit_loc = patindex("%[kKmMgGpP]%", @size_str)

if @unit_loc != 0
begin
	/*
	** Separate the unit specifier from the digits.
	*/
	select @digits = substring(@size_str, 1, @unit_loc - 1)
	select @units = lower(substring(@size_str, @unit_loc, 30))

	/*
	** Remove any blanks that may have been between the digits 
	** and the unit specifier (for example, '2 M').
	*/
	select @digits = rtrim(@digits)

	/* 
	** Make sure the unit specifier is valid.  Acceptable values
	** are [pPkKmMgG]; however; we will allow the user to specify 
	** [kKmMgG]b. For example, 8Mb will be allowed.
	*/
	if ((datalength(@units) > 2) 
	 or ((datalength(@units) > 1) and (substring(@units, 2, 1) != 'b'))
	 or ((datalength(@units) > 1) and (substring(@units, 1, 1) = 'p'))) 
	begin
		/* 18146, "Syntax error encountered. Sizes must be
		** of the form int[KMGP]. For example, a size of 5 
		** megabytes may be specified as '5M'."
		*/
		raiserror 18146
		select @ret_size = 0
		return 0
	end

	select @units = substring(@units, 1, 1)
end
else
begin
	select @digits = substring(@size_str, 1, char_length(@size_str))
	select @units = "k"
end

/*
** Ensure that @digits contains a valid floating-point 
** number.
*/
if (@digits is NULL)
begin
	/*
	** 18146, "Syntax error encountered. Sizes must be of the form
	**        int[KMGP]. For example, a size of 5 megabytes may be
	**        specified as '5M'."
	*/
	raiserror 18146
	select @ret_size = 0
	return 0
end

select @found_invalid_char = patindex("%[^0-9.]%", @digits)
select @num_decimal = 0

if (@found_invalid_char = 0)
begin
	/*
	** Shake out errors like '.2.0M'
	*/
	select @count = 1
	select @digit_str_len = char_length(@digits)

	while (@count <= @digit_str_len)
	begin
		select @one_char = substring(@digits, @count, 1)
		if (@one_char = ".")
		begin
			select @num_decimal = @num_decimal + 1
		end
		select @count = @count + 1
	end
end

if ((@found_invalid_char != 0) or (@num_decimal > 1))
begin
	/* 
	 ** 18146, "Syntax error encountered. Sizes must be of the form
	 **        int[KMGP]. For example, a size of 5 megabytes may be
	 **        specified as '5M'."
	 */
	 raiserror 18146
	 select @ret_size = 0
	 return 0
end

if @input_size is NULL
begin
	select @float_size = convert(float, @digits)

	if @float_size < 0
	begin
		select @size_str = rtrim(@size_str)
		/*
		** 18149, "Invalid size of %1! encountered. Sizes must be
		** greater than zero."
		*/
		raiserror 18149, @size_str
		return 0
	end

	if (@units = "p")
		select @float_size = @float_size * @@maxpagesize / 1024
	else if (@units = "m")
		select @float_size = @float_size * 1024 
	else if (@units = "g")
		select @float_size = @float_size * 1024 * 1024
end
else
begin
	select @float_size = @input_size
end
	
if @input_size is not NULL
begin
	/* Here the input size is assumed to be in K units */
	if (@units = "p")
		select @float_size = @float_size / (@@maxpagesize / 1024)
	else if (@units = "m")
		select @float_size = @float_size / 1024 
	else if (@units = "g")
		select @float_size = @float_size /(1024 * 1024) 
end

/*
**  Now round config size to the nearest integer value since
**  we'll be inserting this into sysconfigures as the integer
**  representation of the number of kilobytes for this size of this
**  cache.  But if a format string is given as an input, round it off
**  to the 4 digit precision after a decimal point.
*/
if @input_size is not NULL
begin
	select @ret_size = 0
	select @output_str = ltrim(str(round(@float_size, 4),15,4)) + @units
end
else
begin
	select @ret_size = convert(int, round(@float_size, 0))
end
return 1
go
exec sp_procxmode 'sp_aux_getsize', 'anymode'
go
grant execute on sp_aux_getsize to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_namecrack')
begin
	drop procedure sp_namecrack
end
go
print "Installing sp_namecrack"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */

create procedure sp_namecrack
@name	varchar(1023),
@site	varchar(255) = null output,
@db	varchar(255) = null output,
@owner	varchar(255) = null output,
@object	varchar(255) = null output
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @site = null, @db = null, @owner = null, @object = null

/*
**  Is there a site name?
*/
if @name like "%.%.%.%"
begin
	select @site = substring(@name, 1, charindex(".", @name) - 1)
	select @name = substring(@name, charindex(".", @name) + 1, 1025)
end

/*
**  Is there a database name?
*/
if @name like "%.%.%"
begin
	select @db = substring(@name, 1, charindex(".", @name) - 1)
	select @name = substring(@name, charindex(".", @name) + 1, 1025)
end

/*
**  Is there a owner?
*/
if @name like "%.%"
begin
	select @owner = substring(@name, 1, charindex(".", @name) - 1)
	select @name = substring(@name, charindex(".", @name) + 1, 1025)
end

select @object = @name

return (0)
go
exec sp_procxmode 'sp_namecrack', 'anymode'
go
grant execute on sp_namecrack to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_autoformat')
begin
	drop procedure sp_autoformat
end
go
print "Installing sp_autoformat"
go

/*
** Generated by spgenmsgs.pl on Fri Jul 25 17:36:44 2003 
*/
/*
** raiserror Messages for autoformat [Total 5]
**
** 17870, "Table '%1!' does not exist in database '%2!'. %3!"
** 18088, "The target database does not exist."
** 18588, "Column '%1!' does not exist in table '%2!'."
** 19206, "%1!: Execute immediate SQL failed. SQL statement is: %2!"
** 19237, "No columns were found in syscolumns in database '%1!' for table '%2!'."
*/
/*
** sp_getmessage Messages for autoformat [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
** **************************************************************************
** sp_autoformat
**
** Generic stored procedure to select data from any table and auto-format
** column's that are of [var]char (string) type (except text) so that these
** column's appear only wide as the maximum-sized data in the table being
** selected from.
**
** We also provide for a way to ONLY select a subset of the columns in the
** table. This list can be passed via the @selectlist argument, and should
** be a comma-separated list like what would be used by the user if they
** were doing a normal SELECT from this table. This list should ONLY contain
** the raw column names, and no further expressions around it.
**
** The output will be generated in the order that the columns are requested
** via this @selectlist argument.
**
** Restrictions:
** =============
**
**  . Does not fully support use of quoted identfiers for table and
**    column names.
**
**  . The @selectlist is expected to be comma-separated list.
**
**  . This proc does *not* validate that the columns in the WHERE clause,
**    ORDER BY provided by the user actually exist in the table being
**    selected from. These are just tacked on to the final SELECT statement.
**    If there are errors in these arguments, you will just get a run-time
**    error from execute immediate.
**
**  . The length of the generated SQL statement is max of 2048 bytes. For
**    tables with large # of columns, this might overflow. (Provision can
**    be made for the caller to supply a SQL buffer in the future.)
**
**  . There is some support for multi-byte character types but the
**    actual reporting of the data is untested.
**
** Parameters:
**	@fulltabname	- Full table name, possibly 2-, 3-part
**	@selectlist	- SELECT list of columns to output.
**	@whereclause	- Any WHERE predicates on table.
**	@orderby	- Any ORDER BY clause for output.
**	@fmtspecifier	- Format specifier to display output, say in XML.
**			  (Future extension. Currently only for: 'for xml')
**	@trace		- Tracing levels.
**
** NOTE(s):
** =========
**
**  - If the @selectlist is provided, then only these columns will be
**    projected out. If not, columns are projected out in colid order,
**    just like a 'select *' output.
**
** - @selectlist should be formatted as:
**
**	[ <Column's AS-Name label> ][ ]*=[ ]*<column name>
**
**  	. The <Column's AS-Name label> is optional.
**  	. There can be white spaces around the '=' separator.
**
** - This procedure creates a temporary table to store the column information
**   for the table being processed. The table is small, but causes space
**   requirements on tempdb. Column names of this table has a bit cryptic 
**   names - this is to avoid potential conflict with column names of a table
**   to process.
**
** - If the table being reported on is large-ish, and there are multiple
**   'char'-type columns, then the processing could be slightly slow as we
**   make as many passes over the input table as there are char-type columns
**   to determine each column's max-length.
**
** Examples:
** =========
**
	sp_autoformat systypes

	sp_autoformat syscolumns, 'id, colid, name'

	sp_autoformat syscolumns, "TableID = id, 'Column ID'=colid, name"
			, "where id = 3"
** Trace-levels:
** ==============
**	0	- Default; no tracing.
**	1	- High-level tracing of major phases.
**	2	- Detailed tracing for each phase.
**	3	- Dump select-list, as-list at end of each iteration.
**	4	- Dump contents of #temp table as it is processed.
**
**  Trace messages are intentionally left in-line as they are meant only
**  for debugging and internal uses.
**
** Returns:
**	0	- If all processing went ok.
**	1	- For usage errors/internal errors.
**	<n>	- The @@error value that was received when an error occured.
**		  This could be the return value from execute immediate.
**		  Client can trap this and do further processing based on
**		  the error number.
{
*/
create procedure sp_autoformat(
			  @fulltabname	varchar(767)
			, @selectlist	varchar(8192)	= NULL
			, @whereclause	varchar(4096)	= NULL
			, @orderby	varchar(4096)	= NULL
			, @fmtspecifier	varchar(32)	= NULL
			, @trace	int		= 0
) as
begin
	declare @whoami		varchar(255)
	      , @whoami_sp	varchar(258)
	      , @currdbname	varchar(30)
	      , @sitename	varchar(30)	-- unused.
	      , @dbname		varchar(30)
	      , @dbid		int		-- @dbname's dbid.
	      , @owner		varchar(30)
	      , @tablename	varchar(255)
	      , @lcl_tablename	varchar(767)
	      , @colname	varchar(510)
	      , @asname		varchar(275)	-- Could be longer than
	      					-- column name
	      , @asname_valid	int
	      , @sqlstr		varchar(8000)
	      , @dot_loc	int		-- location of '.' in names
	      , @comma_loc	int		-- location of ',' in lists
	      , @equal_loc	int		-- location of '=' in name.
	      , @objid		int
	      , @maxlength	int		-- really in # of chars.
	      , @autoformat	tinyint
	      , @sel_colnum	int		-- column number
	      , @as_colnum	int		-- as-list column number
	      , @retval		int
	      , @mbyte_char_str	varchar(30)
	      , @mbyte		int		-- whether column is multi-byte
	      , @sellist_given	tinyint		-- Boolean
	      , @colid		int		-- colid

	      , @this_col_spec_len	int
	      , @trace_highlevel	int
	      , @trace_detailed		int
	      , @trace_dumplists	int
	      , @trace_temptable	int
	      , @setrowcount		int
	      , @type			int
	      , @collength		int

	select	  @setrowcount = @@setrowcount	

	select	  @whoami = object_name(@@procid, db_id('sybsystemprocs'))
		, @currdbname	= db_name()

		-- Get rid of any leading spaces in input arguments.
		, @fulltabname	= ltrim(@fulltabname)
		, @whereclause	= ltrim(@whereclause)
		, @orderby	= ltrim(@orderby)

		-- Initially assume that it is a one-part name.
		--
	select	  @dbname = NULL
		, @owner = user_name()		-- current user.
		, @tablename = @fulltabname
		, @objid = object_id(@fulltabname)
		, @sellist_given = 0

		, @trace_highlevel	= 1
		, @trace_detailed	= 2
		, @trace_dumplists	= 3
		, @trace_temptable	= 4

	if (@trace >= @trace_highlevel)
	begin
		print "%1!: (Nesting Level: %2!) fulltabname: '%3!'"
			, @whoami , @@nestlevel , @fulltabname
	end

	/*
	** If we are under a user defined xact, disallow this since we may
	** we create tables via select-into and that is not allowed in a
	** multi-statement xact.
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_autoformat"
		select @retval = 1
		goto error_exit
	end

	set transaction isolation level 1    
	set chained off

	-- Extract out the 1st part of a 3-part or 2-part name
	if (charindex(".",@fulltabname) > 0)
	begin
		exec sp_namecrack @fulltabname
			, @sitename output
			, @dbname output
			, @owner output
			, @tablename output
	end
	else
	begin
		select @tablename = @fulltabname,
		@sitename = null, @dbname = null, @owner = null
	end

	-- Now that we have the basename for the table, do special processing
	-- to see if it is a #temp table. And manage the db-context for the
	-- temp table. User -might- be asking for a #temp table that is not
	-- the currently-assigned tempdb. If so, let the passed-in dbname be.
	-- Otherwise, set the dbname to be the user's currently assigned temp
	-- dbname.
	--
	if  ((@dbname is NULL) and (substring(@tablename, 1, 1) = "#") )
	begin
		select @dbname = db_name(@@tempdbid)
	end

	-- By now if @dbname is NULL, use current db to search for table.
	--
	if (@dbname IS NULL)
		select @dbname = db_name()

	-- ******************************************************************
	-- Error checking for invalid dbname, object name etc.
	--
	select @dbid = db_id(@dbname)
	if (@dbid IS NULL)
	begin
		raiserror 18088
		select @retval = 1
		goto error_exit
	end

	-- select @objid = object_id(@dbname + "." + @owner + "." + @tablename)
	select @lcl_tablename = @dbname + "." + @owner + "." + @tablename
	select @objid = object_id(@lcl_tablename)
	if (@objid IS NULL)
	begin
		-- Table does not exist in database. The last arg is NULL,
		-- as we don't need to further describe the action of what
		-- failed.
		--
		raiserror 17870, @fulltabname, @dbname, NULL
		select @retval = 1
		goto error_exit
	end

	if (@trace >= @trace_highlevel)
	begin
		print "%1!: (Nesting Level: %2!) %3! dbname: '%4!' owner: '%5!' tablename: '%6!' Objid: %7!"
			, @whoami , @@nestlevel
			, @currdbname, @dbname, @owner, @tablename
			, @objid
	end

	-- ******************************************************************
	-- Create a #temp table that will be used to further process the
	-- column list for the table being selected from.
	-- All we are doing here is to create a template table using      
	-- datatypes from syscolumns, systypes. Use the source tables from
	-- master to avoid deadlocking on syscolumns in tempdb.           
	--
	select    c.colid		as '_clid#af' 	-- colid
		, c.name		as '_clname#af' -- column name
		, t.usertype		as '_usrtype#af'-- usrtype
		, t.type		as '_type#af'	-- system type
		, t.name		as '_typnm#af'	-- type name
		, c.length		as '_colen#af'	-- length
		, convert(int not null, 0) as '_maxlen#af' -- max data length
		, convert(tinyint, 0) 	as '_auto#af'	-- autoformat bit
		, convert(tinyint, 0)	as '_slc#af'	-- appears in the select list
		, convert(int, 0)	as '_sorder#af' -- position in the select list
		, convert(varchar(50), c.name)  as '_asname#af' 
		, convert(tinyint, 0)	as '_mbyte#af'
	into	#colinfo_af lock allpages
	from master..syscolumns c, master..systypes t
	where 1 = 0

	set rowcount 0

	-- Insert column's datatype info and other book-keeping information
	-- for all columns in the table into the above #temp table.
	--
	if (@dbname != 'tempdb')
	begin
		select @sqlstr = 
		  "INSERT #colinfo_af"
		+ "(_clid#af,_clname#af,_usrtype#af,_type#af,_typnm#af,_colen#af"
		+ ",_maxlen#af,_auto#af,_slc#af,_sorder#af"
		+ ",_asname#af,_mbyte#af" + ")"

		-- Initially all columns are considered unselected,
		-- Initial load of the data is in colid order for
		-- the SELECT. This allows the @selectlist to be NULL
		-- and we still get the right results.
		-- And initial selectorder is 0 as we have not
		-- processed the select list, yet.
		--
		+  " SELECT c.colid,c.name,t.usertype,t.type,t.name"
			+ ",case when c.length < 80 then 80 else c.length end"
			+ ",0"		-- maxlength
			+ ",0"		-- autoformat
			+ ",1"		-- selected
			+ ",c.colid"		-- selectorder
			+ ",c.name"	-- asname
			+ ",0"		-- mbyte (multi-byte char column)

		+ " FROM " + @dbname + ".dbo.syscolumns c,"
			   + @dbname + ".dbo.systypes t"
		+ " WHERE c.id=" + convert(varchar, @objid)
		+    " AND c.usertype=t.usertype"

		select @whoami_sp = @whoami + '(1)'

		exec (@sqlstr)
		select @retval = @@error
		if (@retval != 0)
		begin
			raiserror 19206, @whoami_sp, @sqlstr
			goto error_exit
		end

	end
	else
	begin
		INSERT #colinfo_af	
		(_clid#af, _clname#af, _usrtype#af, _type#af, _typnm#af,
		_colen#af, _maxlen#af, _auto#af, _slc#af, _sorder#af,
		_asname#af, _mbyte#af)
		SELECT c.colid,c.name,t.usertype,t.type,t.name
		,case when c.length < 80 then 80 else c.length end
		,0          -- maxlength
		,0          -- autoformat
		,1          -- selected, assume by default all columns
		,c.colid    -- selectorder 
		,c.name     -- asname
		,0          -- mbyte (multi-byte char column)
		FROM tempdb.dbo.syscolumns c, tempdb.dbo.systypes t
		WHERE c.id= @objid AND c.usertype=t.usertype

	end

	-- *************************************************************
	-- Initially we assume that all columns in the table are being
	-- selected.
	--
	select @sel_colnum = count(*) from #colinfo_af

	-- If table's columns were not found in the syscolumns of the
	-- db specified (or chosen by this script), then there is an
	-- error somewhere. Flag that and bail.
	--
	if (@sel_colnum = 0)
	begin
		raiserror 19237 , @dbname, @fulltabname
		select @retval = 0
		goto error_exit
	end

	if (@trace >= @trace_temptable)
	begin
		exec sp_autoformat #colinfo_af, @trace = @trace
		
		select * from #colinfo_af

		print ""
		if (@trace >= @trace_highlevel)
		begin
			print "%1!: (Nesting Level: %2!) %3! dbname: '%4!' owner: '%5!' tablename: '%6!' Objid: %7!"
				, @whoami , @@nestlevel
				, @currdbname, @dbname, @owner, @tablename
				, @objid
		end
	end

	/*
	** *************************************************************
	** Parse the @selectlist, if any, and update the #temp table to
	** record the order that the user has requested in which the
	** columns should appear in the final output.
	*/
	if (@selectlist is NOT NULL)
	begin	-- {

		-- Mark all columns as not being selected as we have
		-- user-specified SELECT list.
		--
		update #colinfo_af
		set   _slc#af = 0		-- all columns are not selected
		    , _sorder#af = 0		-- no colid order

		if (@@error != 0)
		begin
			select @retval = @@error
			goto error_exit
		end

		if (@trace >= @trace_highlevel)
		begin
			print "Processing select list: %1!", @selectlist
		end
			-- Remember that user provided a select-list,
			-- which will soon be parsed away to become NULL.
		select    @sellist_given = 1

			-- Reset the select-list column #; will be recomputed.
			, @sel_colnum = 0

		while (@selectlist is NOT NULL)
		begin
			if (@trace >= @trace_dumplists)
			begin
				print "  Processing 'SELECT' list: %1!"
					, @selectlist
			end

			select @comma_loc = charindex(',', @selectlist)

			-- Extract out the current column.
			--
			select @colname = case @comma_loc
					    when 0 then @selectlist
					    else substring(@selectlist, 1,
							(@comma_loc - 1))
					  end

			-- Remember length of this entire pattern, with
			-- possibly embedded '=', as we need that length
			-- to move past this column specifier.
			--
			select @this_col_spec_len = datalength(@colname)

			select @sel_colnum = @sel_colnum + 1

			-- Parse the column specifier which can be one of:
			--
			--	select id
			--	select 'This ID' = id
			--
			-- (Column's AS-name is optional.)
			--
			select @equal_loc = charindex('=', @colname)

			if (@equal_loc != 0)
			begin
				-- L.h.s of '=' is label, AS-name
				select @asname = substring(@colname, 1,
							(@equal_loc - 1))

				-- R.h.s of '=' is column name.
				select @colname = substring(@colname,
							(@equal_loc + 1),
						(@this_col_spec_len
						 - datalength(@asname)
						 - 1) )

				select @asname = rtrim(ltrim(@asname))
					, @colname = rtrim(ltrim(@colname))
			end
			else
			begin
				select @colname = rtrim(ltrim(@colname))
				select @asname = @colname
			end

			select @asname_valid = valid_name(@asname)
			if (@trace >= @trace_detailed)
			begin
				print "    %1! Column: '%2!', AS-name: '%3!' valid ID: %4!"
					, @sel_colnum, @colname, @asname
					, @asname_valid
			end

			 -- Filter out duplicate columns in select-list
			 -- If column exists but selected = 1, then it
			 -- has been seen already. Raise an error.
			 --
			if ((select count(*) from #colinfo_af
			     where _clname#af = @colname
			       and _slc#af = 1) != 0)
			begin
				/*
				** This is a possibly temporary restriction,
				** so no raiserror is being done. This error
				** might go away in the future.
				*/
				print "Column '%1!' specified multiple times in the SELECT list. This is currently unsupported."
					, @colname
				select @retval = 1
				goto error_exit
			end

			-- Record the column's order # in the #temp table.
			-- And store its AS-name for the output.
			--
			update #colinfo_af
			set 	  _sorder#af = @sel_colnum
				, _slc#af = 1
				, _asname#af = @asname
			where _clname#af = @colname

			-- User is expected to be honest and provide a
			-- select-list that is exactly contained in the
			-- table's column-list. If we did not update
			-- exactly one row, it is an error. (0 rows
			-- updated means column was not found in the list
			-- of columns. More than one row updated means that
			-- the same column appeared twice in the select list.)
			--
			if (@@rowcount != 1)
			begin
				raiserror 18588, @colname, @fulltabname
				if (@trace >= @trace_temptable)
				begin
					
					select * from #colinfo_af
					order by _clid#af
					
				end
				select @retval = 1
				goto error_exit
			end

			if (@@error != 0)
			begin
				select @retval = @@error
				goto error_exit
			end

			-- Move past the previous column specifier (which
			-- possibly includes an embedded '=') and (any)
			-- ','-separator
			--
			select @selectlist =
				case @comma_loc
				  when 0 then NULL
				  else substring(@selectlist, (@comma_loc + 1),
					  (datalength(@selectlist)
					  	- @this_col_spec_len
						- 1)
					)
				end

			-- If the separator was the last item, and there is
			-- no more data after that (i.e. 'id, name,') flag
			-- that condition and raise an error. We should keep
			-- the behaviour consistent with that of
			-- 'id, name, '; where there are trailing spaces
			-- after the last comma.
			--
			if ((@comma_loc != 0) and (@selectlist IS NULL))
			begin
				raiserror 18588, @selectlist, @fulltabname
				select @retval = 1
				goto error_exit
			end
		end

	end	-- }	if (@selectlist is NOT NULL)

	if (@trace >= @trace_temptable)
	begin
		select * from #colinfo_af
	end

	/*
	** *************************************************************
	** Process the #temp table looking for columns that need auto-
	** -formatting.
	**
	**  . Scan each row of the #temp table.
	**  . Identify columns of [var]char, uni[var]char, and sysname
	**    types. (See below for complete list of types that need 
	**    auto-formatting.)
	**  . Update the #temp table w/max lengths for each column which
	**    is of this type.
	**  . Set a bit in table tagging this column, to avoid re-work.
	*/
	if (@trace >= @trace_highlevel)
	begin
		print "Processing #temp table looking for columns needing auto-formatting."
	end

	-- List of usertype values for char-type data that are multi-byte:
	-- 24 -- nchar
	-- 25 -- nvarchar
	-- 34 -- unichar
	-- 35 -- univarchar
	select @mbyte_char_str = "24, 25, 34, 35"


	/*
	** Note about the datatypes being handled here:
	**  . [var]binary is being skipped. We dont' want to deal with
	**    truncation of trailing 0s business right now.
	**  . TEXT (image) is being skipped as it is too much processing.
	*/
	declare curcolumns cursor for
	select _clname#af, _type#af, _colen#af, _clid#af
	from #colinfo_af
	where _type#af in (    38	-- intn, bigint null
			,  39	-- varchar, [long]sysname, nvarchar
			,  47	-- char, nchar
			,  48	-- tinyint
			,  49	-- date
			,  50	-- bit
			,  51	-- time
			,  52	-- smallint
			,  55	-- decimal
			,  56	-- int
			,  58	-- smalldatetime
			,  59	-- real
			,  60	-- money
			,  61	-- datetime
			,  62	-- float
			,  63	-- numeric
			,  65	-- usmallint
			,  66	-- uint
			,  67	-- ubigint
			,  68	-- uintn
			, 106	-- decimaln
			, 108	-- numericn
			, 109	-- floatn
			, 110	-- moneyn
			, 111	-- datetimn
			, 122	-- smallmoney	
			, 123	-- daten
			, 135	-- unichar
			, 147	-- timen
			, 155	-- univarchar
			, 187	-- bigdatetimen
			, 188 	-- bigtimen   
			, 189   -- bigdatetime
			, 190   -- bigtime
			, 191	-- bigint
	)
	and _sorder#af > 0

	/*
	** Reuse existing table instead of creating a new one.
	** Later a self-join may be done as well as two tables join.
	** Those duplicate rows will have columns: colname, maxlength
	** set and colid = -1.
	*/
	select @sqlstr = "INSERT #colinfo_af(_clid#af,_clname#af,_usrtype#af,
			_type#af,_typnm#af,_colen#af,_auto#af,_slc#af,_sorder#af,_asname#af,_mbyte#af,_maxlen#af)
		SELECT -1,_clname#af,0,0,'',0,0,0,0,'',0 , "
	open curcolumns

	fetch curcolumns into @colname, @type, @collength, @colid

	while (@@sqlstatus = 0)
	begin	-- {

		if (@trace >= @trace_detailed)
		begin
			print "    Column '%1!'", @colname
		end

		-- Some background: the first isnull() caters
		-- for a case where we have 0 rows at all,
		-- so the minimum length is 1. The second
		-- isnull() enforces a minimum length of 4
		-- when NULL values occur in the column, to
		-- accomodate 'NULL'. The convert() to varchar
		-- is used to determine the length of
		-- non-varchar data.
		--
		--  if(int1==int2 and int1,int2 > 0)
		-- 	=>  sign(int1/int2) * sign (int2/int1) = 1

		select @sqlstr = @sqlstr +
		"isnull(max(isnull(char_length("
		+ "convert(varchar("
		+  convert(varchar,@collength) + "),"
		+ @colname  + ")"  + "),4)),1)"
		+ " *sign(_clid#af/" + convert(varchar(4),@colid) +
		")*sign (" + convert(varchar(4),@colid) + "/_clid#af) +"	

		fetch curcolumns into @colname, @type, @collength,@colid


	end	-- }	while (@@sqlstatus = 0)

	close curcolumns

	deallocate cursor curcolumns

	select @whoami_sp = @whoami + '(2)'

	-- finalize the INSERT for EI call
	select  @sqlstr = @sqlstr + "0" + " FROM #colinfo_af," 
			+ @fulltabname + " " + @whereclause

	if (@trace >= @trace_dumplists)
	begin
		select @sqlstr
	end

	exec(@sqlstr)

	select @retval = @@error
	if (@retval != 0)
	begin
		raiserror 19206, @whoami_sp, @sqlstr
		goto error_exit
	end

	/*
	** temp table has duplicate set of rows now. fix maxlength values
	** and get rid of duplicate part of the table.
	*/
	update #colinfo_af
	set _maxlen#af = c2._maxlen#af,
	_auto#af = 1,
	_mbyte#af = sign(charindex(#colinfo_af._usrtype#af,@mbyte_char_str))
	from #colinfo_af , #colinfo_af c2
	where #colinfo_af._clname#af = c2._clname#af
	and c2._maxlen#af > 0		-- rows inserted by EI
	and #colinfo_af._maxlen#af = 0	-- initial set or rows

	delete #colinfo_af where _clid#af < 0

	-- Numeric values need to be right-justified. At this point, we have
	-- determined the maximum length for each column based on the value contents,
	-- but that will still lead to incorrect formatting when the column name 
	-- is longer than this maximum length. Therefore, set the max. length of
	-- the formatted column to the column name length if the latter is larger.
	update #colinfo_af
	set _maxlen#af = char_length(_asname#af)
	where _maxlen#af < char_length(_asname#af)

	if (@trace >= @trace_temptable)
	begin
		select * from #colinfo_af
	end

	/*
	** ****************************************************************
	** Go back and process the #temp table, extracting out each column
	** and generate a SQL statement to account for the max-lengths of
	** columns that need auto-formatting. If the user had given us a
	** SELECT list, then only pick those columns. Otherwise, pick all
	** columns (select *).
	*/
	select 	  @sqlstr = "SELECT"
		, @sel_colnum = 1

	declare curcolumns cursor for
	select _clname#af, _maxlen#af, _auto#af, _asname#af, _mbyte#af, _type#af
		, _colen#af
	from #colinfo_af
	where _slc#af = 1
	order by _sorder#af

	open curcolumns

	fetch curcolumns into     @colname, @maxlength, @autoformat
				, @asname , @mbyte, @type, @collength

	while (@@sqlstatus = 0)
	begin
		select @sqlstr = @sqlstr
				+ case @sel_colnum when 1 then "" else ", " end

		select @sel_colnum = @sel_colnum + 1

		if (@autoformat = 1)
		begin
			select @sqlstr = @sqlstr
				+ @asname + '=' +
				case when @type in (39,   -- char, nchar                          
						    47,   -- varchar, [long]sysname, nvarchar     
						    135,  -- unichar                              
						    155)  -- univarchar                           
				then
					-- Expect to handle all potentially long, character
					-- datatypes here
					"SUBSTRING(convert(varchar("+convert(varchar,@collength)+"),"  
						+ @colname
						+ "),1,"
						+ case @mbyte
							 when 0
							 then convert(varchar, @maxlength)
							 else convert(nvarchar, @maxlength)
						  end
						+ ")"
	  			else 
					-- We need to right-adjust the integer datatypes; since this
					-- will not display NULL values as 'NULL' anymore due to the 
					-- string concatenation, we need to explicitly stick in 'NULL'.
					-- Note that 80 characters is enough for all integer datatypes.
					"right(space(80)+isnull(convert(varchar(80),"					  
						+ @colname
						+ "),'NULL')," + convert(varchar, @maxlength) + ")"
				end
		end
		else
		begin
			-- Only generate an AS-name clause when the AS-name
			-- is known to be different than the column name.
			--
			select @sqlstr = @sqlstr
					+ case @asname
					    when @colname then NULL
					    else @asname + '='
					  end
					+ @colname
		end

		fetch curcolumns into     @colname, @maxlength, @autoformat
					, @asname , @mbyte, @type, @collength
	end

	close curcolumns

	deallocate cursor curcolumns

	-- Append the FROM list for the select from the table.
	--
	select @sqlstr =  @sqlstr 

			-- Go back to using the full table name as the
			-- user passed to us. #temp tables were processed
			-- earlier to generate the name that the user
			-- should have been using.
			--
			+ " FROM " + @fulltabname
			+ " " + @whereclause
			+ " " + @orderby
			+ " " + @fmtspecifier

	select @whoami_sp = @whoami + '(3)'
	if (@trace = 0)
	begin
		set rowcount @setrowcount
	end

	exec (@sqlstr)
	select @retval = @@error
	if (@retval != 0)
	begin
		raiserror 19206, @whoami_sp, @sqlstr
		goto error_exit
	end

	return 0

error_exit:
	return @retval
	
end
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_autoformat', 'anymode'
go
grant execute on sp_autoformat to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_remotesql')
begin
	drop procedure sp_remotesql
end
go
print "Installing sp_remotesql"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
*/
create procedure sp_remotesql
	@server varchar(255),	/* name of remote server */
	@query varchar(255)	/* statement to be executed on remote server */
/*
** The caller may supply up to 250 additional arguments of type
** char or varchar.  These will be concatenated to the end of the
** query buffer initialized by the @query arg.  This query buffer
** is passed directly to server '@server', where it is executed.
** Any and all results are passed directly back to Omni's client.
*/
as
	if @@error > 0
		return @@error
go
exec sp_procxmode 'sp_remotesql', 'anymode'
go
grant execute on sp_remotesql to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_check_remote_tempdb')
begin
	drop procedure sp_check_remote_tempdb
end
go
print "Installing sp_check_remote_tempdb"
go

/*
** Messages for sp_check_remote_tempdb
**
** 19818, "Local temporary database '%1!' is skipped for this operation. The
**         database is accessible from the owner instance '%2!' only."
** 19820, "The database '%1!' is only accessible from the owner instance 
**	   '%2!'. Please execute the procedure on that instance.
*/

/*
** Description
**      It checks if the database is a local tempdb owned by a remote
**	instance and print msg depending on the action requested. 
**
** Parameters
**      @dbid	- Database id
**	@action - 'skip' or 'reject'. Depending on the value it
**		  will raise a skip or reject warning. Any other
**		  value will avoid printing any message.
** Returns
**      1       - Database is local tempdb owned by remote instance. 
**      0       - Otherwise
*/
create procedure sp_check_remote_tempdb 
@dbid int, 
@action sysname = NULL
as
begin
	declare @instanceid int, 
		@instancename sysname,
		@dbname varchar(255),
		@error int,
		@msg varchar(1024)

	if (@@clustermode = 'shared disk cluster')
	begin
   		select @instanceid = isnull(db_instanceid(@dbid), 0)
   		if (@instanceid > 0 and @instanceid != @@instanceid)
   		begin
			if (@action = 'skip' )
				select @error = 19818
			else if (@action = 'reject')
				select @error = 19820
			else
				select @error = 0

			if (@error != 0)
			begin
				select @dbname = db_name(@dbid)
				select @instancename = 
					instance_name(@instanceid)

        			exec sp_getmessage @error, @msg output
				print " "
        			print @msg, @dbname, @instancename
			end

			return 1
   		end
	end

	return 0
end 
go
exec sp_procxmode 'sp_check_remote_tempdb', 'anymode'
go
grant execute on sp_check_remote_tempdb to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_configure')
begin
	drop procedure sp_configure
end
go
print "Installing sp_configure"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/configure */

/*
** Messages for "sp_configure"          17410
**      Must use "langid" when referencing spt_values
**
** 17260, "Can't run %1! from within a transaction." 
** 17410, "Configuration option doesn't exist."
** 17411, "Configuration option is not unique."
** 17413, "The value of the 'number of devices' must not be less than the number of active devices '%1!'
** 17414, "You can't set the default language to a language ID that is not defined in Syslanguages."
** 17415, "Configuration option value is not legal."
** 17418, "'%1!' is an invalid file command. The valid commands are 'verify', 'read', 'write', and 'restore'."
** 17419, "Configuration option changed. The SQL Server need not be rebooted since the option is dynamic.
** 18123, "Configuration option changed. The SQL Server must be rebooted before the change in effect since the option is static."
** 18124, "No matching configuration options.  Here is a listing of groups:"
** 18125, "Must provide the parameter 'filename'."
** 18133, "The character set, '%1!', is invalid since it is not defined in Syscharsets."
** 18134, "The sortorder, '%1!', is invalid since it is not defined in Syscharsets."
** 18397, "Changing the value of '%1!' does not increase the amount of 
**        memory Adaptive Server uses.
**
** 18549, "Invalid third argument supplied: '%1!'. Valid choices are
**	   'with truncate' or 'default'."
**
** 18915, "An additional %1! K bytes of memory is available for 
** 	  reconfiguration. This is the difference between 'max memory' 
**	  and 'total logical memory'."
**
** 18916, "Changing the value of '%1!' to '%2!' increases the amount of
** 	  memory ASE uses by %3! K."
**
** 18917, "Changing the value of '%1!' to '%2!' reduces the amount of
** 	  memory ASE uses by %3! K. The reduced memory may be reused
**	  when this configure value changes, but will not be released
**	  until ASE restarts."
**
** 18932, "Resulting configuration value and memory use have not changed 
**	  from previous values: new configuration value %1!, previous %2!."
**
** 19106, "Cannot change the value of configuration parameter 'global cache 
**	  partition number' when the server is in recovery."
** 
** 19107, "Cannot change the value of configuration parameter 'max concurrently 
**	  recovered dbs' because the server is still in recovery setup."
**
** 19108, "Cannot change the configuration parameter 'max concurrently
**	   recovered dbs' to %1 when the server is in recovery. The only value 
**	   allowed is 1.
**
** 19109, "Cannot change the value of configuration parameter 'global async
**	  prefetch limit' when the server is in recovery."
**
** 19416, "Provider class '%1!' is not a recognized messaging provider class."
**
** 19519, "Cannot run sp_configure for server '%1!' since you are not
**	  connecting to it." 
**
** 19520, "Cannot configure '%1!' for an instance, since it is a strictly 
**	  cluster-wide option." 
**
** 19521, "Cannot configure '%1!' to cluster-wide since all active instances 
**	  have instance-specific setting on this option."
**
** 19570, "Cannot drop the instance-specific configuration for configuration
**	  parameter '%1!' since the configuration setting does not exist."
**
** 19574, "An instance name needs to be provided. "
**
** 19654, "Warning: In Shared Disk Cluster, all instances share the same 
**	  configuration file. Please run sp_configure to read the configuration 
**        file for all other instances to keep the configuration consistent."
** 19816, "You cannot set configuration values from inside a local temporary
**	  database."
** 19874, "Cannot configure '%1!' to cluster-wide since it is an 
**	  instance-specific-only option."
** 19953, "Cannot change the value of configuration parameter 'config file 
**	  version' because it is server generated."
**
** 19961, "WARNING: Compatibility mode will not be used when 'abstract plan dump/load/replace' is on."
** 19962, "WARNING: Compatibility mode may not be used when statement cache and literal autoparam are enabled."
** 19966, "WARNING: Enabling compatibility mode will not affect the query plans already stored in the procedure cache."
** 19967, "WARNING: The configuration option 'statement cache size' is configured with value '%1!'. Enabling compatibility mode will not affect the query plans already stored in the statement cache."
*/

create procedure sp_configure
@configname varchar(255) = NULL,	/* configure option name */
@configvalue int = NULL,		/* configure value */
@configvalue2 varchar(255) = NULL,	/* config file command/charset info */
@configvalue3 varchar(255) = NULL	/* physical name of file */
as

declare @confignum int			/* number of option to be configured */
declare @configcount int		/* number of options like @configname */
declare @whichone	int		/* using english or default lang ? */
declare @cmd		smallint	/* configuration file command */
declare @status int			/* return status for misc calls */
declare @children int			/* number of children in a group */
declare @parent int			/* config number of parent group */
declare @msg varchar(1024)		/* temp buffer for messages */
declare @sysconfig smallint		/* contents of sysconfigures.config */
declare @sysname varchar(255)		/* contents of sysconfigures.comment */
declare @sysparent smallint		/* contents of sysconfigures.parent */
declare @sysstatus int			/* contents of sysconfigures.status */
declare @value int 			/* default charset/sort order id */
declare @user_displaylevel int		/* user display level */
declare @numdevices int			/* number of active devices */
declare @sorder_chset_id int            /* current sortorder or character set id */
declare @use_wildcard tinyint           /* use wildcard to search option name or not */
declare @match_count int                /* number of option found by name match */
declare @cmpstate     	int         	/* Local NODE state in companionship */
declare @additional_free_memory	 int    /* Additional Free memory */
declare @logical_memory	 int            /* total logical memory before 
					   change*/
declare @lmemconfignum int		/* confignum for 'total logical memory' */
declare @additional_memory	 int    /* increase in logical memory due 
					   to change*/
declare	@oldcfgvalue		int	/* 
					** previous config value for parameter
					** with integer type.
					*/
declare @oldcfgvalue_char	varchar(255)
					/*
					** previous config value for parameter
					** with character type.
					*/
declare @defvalue	varchar(255)	/* default config value */
declare @fullconfigname varchar(255) 	/* configure option name */
declare @bvalue     	int         	/* base value after unit 
					   converting */
declare @unit		varchar(20)
declare @nocase         tinyint         /* case-sensitive sort order flag */
declare @rec_state	varchar(30)	/* the server recovery state */
declare @new_class	smallint	/* for valid messaging provider
					** class
					*/
declare @is_equal       int             /*
					** flag to check whether configuration
					** value and run value are same or not.
					*/ 
declare @configcount2	int		/* number of options for an instance. */
declare @configcount3	int		/* number of options for an instance. */
declare @match_count2	int  		/* number of option found by name and
					** instance match.
					*/
declare @instanceid	tinyint		/* instance id */
declare @use_cluster	int		/* if cluster-wide value is used. */
declare @remote_instance_name	varchar(255)
					/* remote instance name */
declare @remote_instance_id	tinyint
					/* remote instance id */
declare @retstat	int
declare @sqlbuf		varchar(255)

declare @non_default_options int  	/* this option is set when nondefault
					   settings  are to be displayed */
declare @tmp_rtms_value  int           /* to store the value of 'enable real time messaging'*/
declare @all_rtms_provider_set int 	/* to store bit map while all rtms provider enabled*/
declare @cfg_rtms_provider_mask int 	/* to check if the required rtms provider enabled */	
declare @cfg_rtms_all_mask     int   	/* to check if all options of rtms enabled */ 					
declare @optlevel_def	varchar(20)	/* default value for optlevel */
declare @optlevel_run	varchar(20)	/* run value for optlevel */
declare @optlevel_curr	varchar(20)	/* current value for optlevel */

declare @config_value_to_check int	/* value of config option to be 
					** checked with compatibility mode.
					*/

select @whichone = 0
select @status = 0
select @cmd = 1
select @value = NULL
select @user_displaylevel = NULL
select @sorder_chset_id = 0
select @is_equal = 0
select @use_wildcard = 1
select @config_value_to_check = NULL
select @use_cluster = 0
select @instanceid = NULL

/*
** Check if the default sort order is case-insensitive.
*/
if ("A" = "a")
        select @nocase = 1
else
        select @nocase = 0

/*
**  Disallow running sp_configure within a transaction since it might make
**  recovery impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
		raiserror 17260, "sp_configure"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1
set nocount on

/*
** Prepare values for'optimizer level'.
*/
select * into #optlevel 
from master.dbo.spt_values where type = 'OL'
and name like 'ase%'

select @optlevel_def = name
from master.dbo.syscurconfigs , #optlevel
where config = 507
and number = convert(int,defvalue)

select @optlevel_run = name
from master.dbo.syscurconfigs , #optlevel
where config = 507
and number = convert(int,value2)

select @optlevel_curr = name
from master.dbo.syscurconfigs , #optlevel
where config = 507
and number = convert(int,value)

/*
**      If the "default sortorder" is case insensitive dictionary sort order,
** the procedure will just print out all the options and their values
** without grouping if no option name is given.
*/
if (@nocase = 1 and @configname is NULL)
begin
	/* Display all config parameters for specified instance. */
	if @configvalue3 is not NULL
	begin

		begin 
			select "Parameter Name" = convert(char(30), name), 
			       "Default" = CASE WHEN b.config = 507 THEN @optlevel_def
			       ELSE convert(char(11), 
				 space(11-char_length(
				 convert(varchar(11), defvalue))) + 
				 convert(varchar(11), defvalue))
				 END,
			       "Memory Used" = convert(char(11), 
				 space(11-char_length( 
				 convert(varchar(11), c.comment))) + 
				 convert(varchar(11), c.comment)), 
			       "Config Value" = CASE WHEN b.config = 507 THEN @optlevel_curr
			       ELSE convert(char(12), 
				 space(12-char_length( 
				 isnull(b.value2, 
				 convert(char(32), b.value)))) + 
				 isnull(b.value2, convert(char(32), b.value)))
				 END,
			       "Run Value" = CASE WHEN b.config = 507 THEN @optlevel_run
			       ELSE convert(char(12), 
				 space(12-char_length(isnull(c.value2, 
				 convert(char(32), c.value)))) + 
				 isnull(c.value2, convert(char(32), c.value)))
				 END,
			       "Unit" = convert(char(20), c.unit),

				"Type" = convert(char(20), c.type)

			from master.dbo.sysconfigures b, 
			     master.dbo.syscurconfigs c 
			where 

			b.config *= c.config 
			and b.config != 19 
			and parent != 19 

			
			return (0) 
		end 
	end



	return (0)
end




/* check whether nondefault settings are to be displyed.*/
if (@configname is not NULL)
begin

	if "display nondefault settings" like "%" + @configname + "%"
	begin
		declare @countno int
	
		/*check if configuration option is unique*/
		
		select @countno = count(*)
		from master.dbo.sysconfigures
		where name like "%" + @configname + "%"
		  and parent != 19


		/*
		** if configuration option is not unique, display the duplicates
		** and return
		*/	
		if @countno > 0
		begin
				
			select name
			into #temptab		
			from master.dbo.sysconfigures a
			where name like "%" + @configname + "%"
	   	      	      and parent != 19
			
			insert into #temptab values 
			("display nondefault settings")
				
			raiserror 17411
			print ""
			print "Choose option from the following"
			print ""
			exec sp_autoformat #temptab
			return(1)
		end		
		/*
		** if configuration option is unique set non_default_options=1, 
		** and make configname=NULL so that next block is bypassed
		*/	
		else
		begin	
			select @non_default_options = 1
			select @configname = NULL	
		end

	end
end
	
/* Validate the configname if it not NULL */
if @configname is not NULL
begin
	/* Check the duplicate rows for cluster-wide settings. */ 
	select @configcount = count(*) 
		from master.dbo.sysconfigures 
			where name like "%" + @configname + "%" 
			and parent != 19


        /*
        **      If configure option is not unique and case-insensitive
        ** dictionary sort order is used, check if unique option found
        ** by exact name match, if so, then disable wildcard match
        ** for searching option name.
        */
        if ((@configcount > 1 

		)
		and @nocase = 1)
 

        begin
                /* check if unique option found by exact name match */
                select @match_count = count(*)
                        from master.dbo.sysconfigures
                                where name = @configname
                                and parent != 19

		
                if (@match_count = 1

		) 
                begin
                        select @use_wildcard = 0  /* don't use wildcard */

			if @match_count = 1
			begin
                        	select @configcount = @match_count
			end


                end
        end

	/*
	** If more than one option like @configname,
	** show the duplicates and return.
	*/
	if @configcount > 1

	begin
		/*
		** 17411, "Configuration option is not unique."
		*/
		raiserror 17411
		print ""

               select "Parameter Name" = convert(char(30), name),
                        "Default" = CASE WHEN a.config = 507 THEN @optlevel_def
				ELSE convert(char(11), space(11-char_length(
                                    convert(varchar(11), defvalue)))+
                                    convert(varchar(11), defvalue))
				END,
                        "Memory Used" = convert(char(11), space(11-char_length(
                                        convert(varchar(11), b.comment)))+
                                        convert(varchar(11), b.comment)),
                        "Config Value" = CASE WHEN a.config = 507 THEN @optlevel_curr
				ELSE convert(char(12), space(12-char_length(
                          isnull(a.value2, convert(char(32), a.value)))) +
                          isnull(a.value2, convert(char(32), a.value)))
				END,
                        "Run Value" = CASE WHEN a.config = 507 THEN @optlevel_run
				ELSE convert(char(12), space(12-char_length(
                          isnull(b.value2, convert(char(32), b.value)))) +
                          isnull(b.value2, convert(char(32), b.value)))
				END,
			"Unit" = convert(char(20), b.unit),

			"Type" = convert(char(10), b.type)
			

		from master.dbo.sysconfigures a,
			master.dbo.syscurconfigs b
		where 

			    a.config *= b.config
			and name like "%" + @configname + "%"
			and parent != 19
			and a.config != 19

		order by name

		/*
		**  If @configname like '%memory%' print message. 
		**  18915, "An additional %1! K bytes of memory is available 
		**  for reconfiguration. This is the difference between 
		**  'max memory' and 'total logical memory'."
		**
		*/
		if (lower(@configname) like '%memory%')
		begin
			select 	@additional_free_memory = 
					(max(b.value) - min(b.value)) * 2 
			from 	master.dbo.sysconfigures a,
				master.dbo.syscurconfigs b
			where 	a.name in ('max memory', 
					   'total logical memory')

			and	a.config = b.config


			exec sp_getmessage 18915, @msg output
			print @msg,@additional_free_memory
		end	
		return (1)
	end
	
	/*
	** if it is a valid option and the @configvalue is not NULL,
	** set the option
	*/
	if (@configcount != 0) and (@configvalue is not NULL)
	begin
		/* set @confignum */
		select	@confignum = config,
			@sysstatus = status,
			@fullconfigname = name
			from master.dbo.sysconfigures
				where name like "%" + @configname + "%"
				and parent != 19
				and config != 19

		/* Disallow running sp_configure on "config file version". */ 
		if (@confignum = 504) 
		begin 
			/* 
			** 19953, "Cannot change the value of configuration 
			** parameter 'config file version' because it 
			** is server generated." 
			*/ 
			raiserror 19953 
			return (1) 
		end



		/*
		** Later, we will want to test whether the config value is
		** actually changing.  Obtain the current and default values
		** for this config so we can ignore requests that result in
		** no change.  Here, if the parameter datatype is (var)char,
		** @oldcfgvalue will be 0; if it's an int, @oldcfgvalue_char
		** will be NULL.
		*/
		select	@oldcfgvalue = b.value,
			@oldcfgvalue_char = b.value2,
			@defvalue = c.defvalue
			from master.dbo.sysconfigures b,
			     master.dbo.syscurconfigs c
				where b.config = @confignum

		  		and b.config *= c.config


		/* 
		** The @oldcfgvalue could be NULL if this is the 
		** first time configuration of an instance value.  
		** If this is the case, get the @oldcfgvalue from 
		** the cluster-wide settings.  
		*/ 
		if @oldcfgvalue is NULL 
		begin 
			select @oldcfgvalue = b.value,
			       @oldcfgvalue_char = b.value2,
			       @defvalue = c.defvalue
				from master.dbo.sysconfigures b, 
			     	     master.dbo.syscurconfigs c 
					where b.config = @confignum 

					and b.config *= c.config 

		end


 		if (@configvalue2 = "default")
		begin
			select @value = 1
			if @oldcfgvalue_char is null
				select @configvalue = convert(int, @defvalue)
		end
		else
			select @value = 0

		/*
		**  If the option name is "configuration file",
		**  take action, then return.
		*/
		if @confignum = 114
		begin
			/*
			** if the file command is not one of the valid
			** commands, complain and then quit.
			*/
			if @configvalue2 not in ("read", "write", "restore",
						 "verify")
			begin
				/*
				** print the message to show the valid
				** file command
				*/
				raiserror 17418, @configvalue2
				return(1)
			end

			/*
			** if filename is NULL
			*/
			if (@configvalue3 is NULL)
			begin
				/* 18125, "Must provide the parameter 'filename'." */
				raiserror 18125
				return(1)
			end

			/*
			** Must have sa_role to run these commands 
			*/
       			if (proc_role("sa_role") < 1)
			begin
				return(1)
			end

			select @cmd = case
			   when (@configvalue2 = "verify") then 2
			   when (@configvalue2 = "read"  ) then 3
			   when (@configvalue2 = "write" ) then 4
			   else 5	-- "restore"
			end


			select @status = config_admin(@cmd,0,0,0,NULL,
						@configvalue3)

			if (@status = 1)
			begin
        			return(0)
			end

			return (1)
		end

		if @confignum = 123
		begin
			/* get current default charset id */
			select @value = value from
				master.dbo.sysconfigures
				where config = 131
		
			select @sorder_chset_id = @value
			if @configvalue2 is not NULL
			begin
				/*
				** Get default charset id from name and
				** validate the charset id.
				*/
				select @value = id
					from master..syscharsets
					where name = @configvalue2 
					and type between 1000 and 1999

				if @value is null
				begin
					/* 18133, "The character set, '%1!', is invalid since it 
					** is not defined in Syscharsets."
					*/
					raiserror 18133, @configvalue2
					return (1)
				end
			end
		end

		else
		if @confignum = 131
		begin
			/* get current default sortord id */
			select @value = value from
				master.dbo.sysconfigures
				where config = 123

			select @sorder_chset_id = @value
			if @configvalue2 is not NULL
			begin
				/*
				** Get default sortorder id from name and
				** validate the sortord id.
				*/
				select @value = id
					from master..syscharsets
					where name = @configvalue2
					and type between 2000 and 2999

				if @value is null
				begin
					/* 18134, "The sortorder, '%1!', is invalid since it 
					** is not defined in Syscharsets."
					*/
					raiserror 18134, @configvalue2
					return (1)
				end
			end
		end

		/*
		** If an attempt to enable a disk mirroring is made, and
		** if this happens to be a server with HA services turned
		** on, we disallow. Currently we do not support ASE HA
		** services along with sybase mirroring.
		*/
		if (@confignum = 140 and @configvalue = 0)
		begin
			select @cmpstate = @@cmpstate
			if @cmpstate >= 0
			begin
				/* 18816 Mirroring not allowed in ASE HA */
				raiserror 18816
				return(1)
			end
		end
		
		/*
		** If an attempt to disable disk mirroring is being made,
		** ensure that there are no devices that are currently
		** being mirrored.
		*/
		else
		if (@confignum = 140 and @configvalue = 1)
		begin
			if (select count(*) from master.dbo.sysdevices
				where status & 512 = 512) > 0
			begin

			  /* 18750, Unable to disable disk mirroring
			  ** because some devices are currently
			  ** mirrored. Use 'disk unmirror' to
			  ** unmirror these devices and then
			  ** re-run this sp_configure command.
			  */

			  raiserror 18570
			  return (1)
			end
		end

		/* 
		**  If this is the number of current audit table we want
		**  to make sure that if "with truncate" option is not 
		**  provided new table is empty other wise fail.
		*/
		else
		if @confignum = 260
		begin
			if @configvalue2 is not NULL
			begin
				if (@configvalue2 not in ("with truncate", 
								"default"))
				begin
					/*
					** 18549, "Invalid third argument
					**         supplied: '%1!'. Valid
					**	   choices are 'with truncate'
					**	   or 'default'."
					*/
					raiserror 18549, @configvalue2
					return(1)
				end
			end
			else
			begin
				select @value = 2
			end
		end

		/*
		** global cache partition number
		*/
		else
		if  @confignum = 337
		and @configvalue is not NULL
		begin
			select @rec_state = @@recovery_state
			if (@rec_state not like "NOT_IN_RECOVERY%")
			begin
				raiserror 19106
				return(1)
			end

			/*
			** Partition number must be a power of 2
			** between 1 and 128.
			*/
			if (@configvalue not between 1 and 128)
			or (@configvalue & (@configvalue - 1) != 0)
			begin
				raiserror 18611
				return(1)
			end
		end

		/*
		** If this is to change the number of maximum concurrently
		** recovered dbs, check to make sure that the server is
		** not currently in the tuning process. We don't allow
		** change to this config parameter if the server is in
		** tuning process.
		** If the server is still in recovery process, the only value
		** that the config parameter may be changed to is 1, which is
		** to change back to do serial recovery.
		*/
		else
		if @confignum = 415
		begin
			select @rec_state = @@recovery_state
			if (@rec_state like "RECOVERY_TUNING%")
			begin
				raiserror 19107
				return (1)
			end
			else if (@rec_state not like "NOT_IN_RECOVERY%" and
				 @configvalue != 1)
			begin
				raiserror 19108, @configvalue
				return (1)
			end

		end

		/*
		** If the config parameter is "global async prefetch limit",
		** do not allow this change if server is in recovery process.
		*/
		else
		if @confignum = 303
		begin
			select @rec_state = @@recovery_state
			if (@rec_state not like "NOT_IN_RECOVERY%")
			begin
				raiserror 19109
				return(1)
			end
		end

		/*
		** If configure parameter is "enable real time messaging",
		** check @configvalue2
		**
		**	- null means enable for all supported messaging
		**	  on that platform.
		**	- 'TIB_JMS' means enable/disable for TIBJMS only.
		**	- 'IBM_MQ' means enable/disable for IBM MQ only.
		**	- 'EAS_JMS' means enable/disable for EASJMS only.
		**  	- 'SONICMQ_JMS' means enable for SONICMQ_JMS only.
		**
		** @configvalue will be changed to a bit mask.
		*/
		if (@value != 3) and (@confignum = 429)
		begin
			if (@configvalue2 is not null)
			begin
				/* Get the class number */
				select @new_class = number
					from master.dbo.spt_values
					where lower(name) = lower(@configvalue2)
					      and type = 'X'

				/* Unrecognized provider class */
				if @@rowcount = 0
				begin
					raiserror 19416, @configvalue2
					return(1)
				end
				
				/* Not a supported provider class */
				if (@new_class != 12) and (@new_class != 13)
				    and (@new_class != 14) and (@new_class != 15)
				begin
					raiserror 19416, @configvalue2
					return(1)
				end
			end			
			
			/* Get the rtms provider mask */
			select @cfg_rtms_all_mask = number
				from master.dbo.spt_values
				where lower(name) = 'all providers'
					and type = 'RT'

			select @all_rtms_provider_set = sum(number)
				from master.dbo.spt_values
                                where type = 'RT'
					and low = 1
			select @all_rtms_provider_set = @all_rtms_provider_set 
							+ @cfg_rtms_all_mask

			if (@configvalue2 is not null)
			begin
				select @cfg_rtms_provider_mask = number
					from master.dbo.spt_values
					where lower(name) = lower(@configvalue2)
					and type = 'RT'
					and low = 1
				/* Not a supported RTMS provider */
				if (@cfg_rtms_provider_mask is null)
				begin
					raiserror 19416, @configvalue2
                                        return(1)
				end
			end
			else if (@configvalue != 0)
			begin
				select @cfg_rtms_provider_mask = @cfg_rtms_all_mask
			end
			else 
			begin
				select @cfg_rtms_provider_mask = @all_rtms_provider_set
			end
		end
	
		/*
		** Raise warning messages if abstract plan 
		** dump/load/replace, literal autoparam or
		** statement cache are already on when 
		** compatibility mode is being enabled.
		*/
		if (@confignum = 502 and @configvalue = 1)
		begin
			/* Raise warning message 19966 */
			exec sp_getmessage 19966, @msg output
			print @msg 
		
			/*
			** Raise warning message 19961 if abstract 
			** plan dump/load/replace is already on. 
			*/
			if exists (select * 
				   from  master.dbo.sysconfigures
				   where config in (383, 384, 385)
				   	 and value = 1)
			begin
                                exec sp_getmessage 19961, @msg output
                                print @msg 
			end
	
			/*
			** Raise warning message 19967 if  
			** statement cache is already on. 
			*/
			select @config_value_to_check = value 
			from  master.dbo.sysconfigures
			where config = 414 

			if (@config_value_to_check is not NULL 
			    and @config_value_to_check != 0)
			begin
                                exec sp_getmessage 19967, @msg output
                                print @msg, @config_value_to_check

				/*
				** Raise warning message 19962 if  
				** literal autoparam is already on. 
				*/
				if exists (select * 
					   from  master.dbo.sysconfigures
					   where config = 462 
					   	 and value = 1) 
				begin
                                	exec sp_getmessage 19962, @msg output
                                	print @msg 
				end
			end

			/*
			** Raise warning message if the value of  
			** histogram tuning factor is not 1, the   
			** default value in ASE 12.5. 
			*/
			select @config_value_to_check = value 
			from  master.dbo.sysconfigures
			where config = 433 

			if (@config_value_to_check is not NULL 
			    and @config_value_to_check != 1)
			begin
				exec sp_getmessage 19965, @msg output
        			print @msg,  @config_value_to_check 
			end

		end

		/*
		** Raise warning messages if compatibility mode 
		** is already on when abstract plan dump/load/replace
		** or literal autoparam is being enabled.
		*/
		if exists (select * 
			   from  master.dbo.sysconfigures
			   where config = 502 and value = 1) 
		begin
			/*
			** Check if abstract plan dump/load/replace
			** is being enabled.
			*/
			if ((@confignum = 383 or 
		     	     @confignum = 384 or 
		     	     @confignum = 385) and 
		    	     @configvalue = 1)
			begin
                                exec sp_getmessage 19961, @msg output
                                print @msg 
			end
		
			/*
			** Check if literal autoparam is being enabled.
			** Note that literal autoparam itself is not
			** a problem but the combination of both
			** statement cache and literal autoparam will
			** have some effect. 
			*/
			if (@confignum = 462 and @configvalue = 1) 
			begin
				/* if statement cache is also on */
				if exists (select * 
					   from  master.dbo.sysconfigures
					   where config = 414 
					   	 and value != 0)
				begin
                               		exec sp_getmessage 19962, @msg output
                                	print @msg 
				end
			end

			/*
			** Check if statement cache is being enabled 
			** because we may have literal autoparam 
			** enabled already. In that case, we need to 
			** raise warning message for literal autoparam
			** as above too. 
			*/
			if (@confignum = 414 and @configvalue != 0) 
			begin
				/* if literal autoparam is already on */
				if exists (select * 
					   from  master.dbo.sysconfigures
					   where config = 462
					   	 and value = 1 ) 
				begin
                                	exec sp_getmessage 19962, @msg output
                                	print @msg 
				end
			end
		end

		/* get @logical_memory */
		select 	@lmemconfignum = config
		from 	master.dbo.sysconfigures
		where 	name = 'total logical memory'


		select 	@logical_memory = value 
		from 	master.dbo.syscurconfigs
		where 	config = @lmemconfignum


		select	@unit = unit
		from	master.dbo.syscurconfigs
		where	config = @confignum	


		/* optimizer level */
		if (@confignum = 507)
		begin
			select @configvalue = number from master.dbo.spt_values
			where type = 'OL' and name = @configvalue2
		end
		/*
		** If configure value is 0, looking for the value
		** in configvalue2. As "default character set id" and
		** "default sortorder_id" can be changed together, if
		** @configvalue is 0 in this case, we will get syntax
		** error. So for such parameters where @unit is "id", 
		** we will not check value of configvalue2.
		*/
		if (@configvalue = 0
		and @configvalue2 is not NULL
		and @confignum != 507
		and @configvalue2 not in("default", "read", "write", "restore",
					"verify", "with truncate"

					)
		and @unit not in ("name", "not applicable", "switch")
		and (@unit != "id" or @confignum in (124, 168)))
		begin
			/* convert "pPkKmMgG" to equivalent "k" units */
			exec @status = sp_aux_getsize @configvalue2, @bvalue output

			if @status = 0
			begin
				/* Invalid syntax */
				return(1)
			end

			/* sp_aux_getsize returns value in K unit. */
			/*
			** If we are updating max memory, do the conversion
			** to 2k-pages ourselves
			*/
			if @confignum = 396
			begin
				select @configvalue = @bvalue / 2
			end
			else
			begin
				select @bvalue = @bvalue * 1024

				/* 
				** normalize it according to its unit and put
				** back to @configvalue. 
				*/
				select @configvalue = config_admin(20, 
					@confignum, @bvalue, 0, NULL, NULL)

			end
		end

                /*
                **  If this is the number of default language, we want
                **  to make sure that the new value is a valid language
                **  ID in Syslanguages.
                */
                if @confignum = 124
                begin
                        if not exists (select *
                                from master.dbo.syslanguages
                                        where langid = @configvalue)
                        begin
                                /* 0 is default language, us_english */
                                if @configvalue != 0
                                begin
                                        /* 17414, "You can't set the default 
					** language to a language ID that is
					** not defined in Syslanguages."
                                        */
                                        raiserror 17414
                                        return (1)
                                end
                        end
                end


		/*
		** If this is the number of devices configuration
		** parameter, we want to make sure that it's not being
		** set to lower than the number of devices in sysdevices.
		*/
		if @confignum = 116
		begin
			/*
			** Get the number of devices.
			*/
			select @numdevices = count(*)
			from master.dbo.sysdevices
			where status & 2 = 2

			if (@configvalue < @numdevices)
			begin
				/* 17413, "The value of the 'number of 
				** devices' must not be less than the number
				** of active devices '%1!'
				*/
				raiserror 17413, @numdevices
				return (1)
			end
		end

		/*
		** Before changing the config value, if this parameter
		** is "number of open databases", make sure it cannot
		** be reduced during recovery.
		*/
		if @confignum = 105
		begin
			select @rec_state = @@recovery_state
			if ((@rec_state not like "NOT_IN_RECOVERY%") and
				(@configvalue < @oldcfgvalue))
			begin
				raiserror 19114
				return(1)
			end
		end

		/*
		** Now we're done checking for @configvalue2 = "default", so
		** we can modify it.  If this is a char param and @configvalue2
		** is "default", reset it to be the actual default.
		*/
		if  @configvalue2 = "default"
		and @oldcfgvalue_char is not null
		begin
			select @configvalue2 = @defvalue
		end

		/*
                ** Check for parameter with integer and character datatype
                ** that if the new and old values for the configuration 
                ** parameter are same, then the value of configuration 
                ** parameter will not be changed. 
                */
		if ((@oldcfgvalue_char is NULL AND @configvalue = @oldcfgvalue)
		 OR (@oldcfgvalue_char is not NULL AND @configvalue2 = @oldcfgvalue_char))
		begin			
			/*
			** Now the old and new values for the first parameter
			** are same. But as "default sortorder id" and "default
			** character set id" both can be changed in sp_configure
			** together, check if the first parameter in sp_configure
			** is one of these and if the new and old values for the
			** second parameter are same, then value of both the
			** parameters should not be changed. The condition
			** mentioned below will always be true for other
			** configuration parameters or if only one configuration
			** parameter is given in sp_configure.
			*/
			
			if (@confignum not in (123, 131)) OR 
			   (@value = @sorder_chset_id)
			begin
				/* Set the @is_equal flag to true */
				select @is_equal = 1

			end
				
		end



		/*
		**If for 'enable real time messaging',  
		**We need to check the bitmap
		*/
		if (@value != 3) and (@confignum = 429)
		begin
			if (@oldcfgvalue = @cfg_rtms_all_mask)
				select @tmp_rtms_value = @all_rtms_provider_set
			else 
				select @tmp_rtms_value = @oldcfgvalue
			
			select @tmp_rtms_value = @tmp_rtms_value & @cfg_rtms_provider_mask
			/*
			** If @configvalue != 0, it means to enable RTDS. 
			** Set it as 1 
			*/
			if (@configvalue != 0) and (@configvalue != 1)
				select @configvalue = 1
			
			if (@configvalue != 0) and (@tmp_rtms_value !=0)
				select @is_equal = 1
			else if (@configvalue = 0) and (@tmp_rtms_value = 0)
				select @is_equal = 1
			else 
				select @is_equal = 0

			if (@is_equal = 1)
				select @configvalue = @oldcfgvalue			
		end
		
		
		
		
		/* 
		** If the new and old values are not the same, call
		** config_admin() to set the new value.  Otherwise just
		** set @status = 1 (success).
		*/
		select @status = case
               	   when (@is_equal = 1) then 1
		   else config_admin(@cmd, @confignum, 
					@configvalue, @value,

					NULL,

				@configvalue2) end
		/* if successful */
		if (@status = 1)
		begin
			if (@confignum = 507)
			begin
				select @optlevel_curr = @configvalue2,
					@optlevel_run = @configvalue2
			end
				
			/* Display the new value */
               		select "Parameter Name" = convert(char(30), name),
                        "Default" = CASE WHEN b.config = 507 THEN @optlevel_def
				ELSE convert(char(11), space(11-char_length(
                                    convert(varchar(11), defvalue)))+
                                    convert(varchar(11), defvalue))
				END,
                        "Memory Used" = convert(char(11), space(11-char_length(
                                        convert(varchar(11), c.comment)))+
                                        convert(varchar(11), c.comment)),
                        "Config Value" = CASE WHEN b.config = 507 THEN @optlevel_curr
				ELSE convert(char(12), space(12-char_length(
                          isnull(b.value2, convert(char(32), b.value)))) +
                          isnull(b.value2, convert(char(32), b.value)))
				END,
                        "Run Value" = CASE WHEN b.config = 507 THEN @optlevel_run
				ELSE convert(char(12), space(12-char_length(
                          isnull(c.value2, convert(char(32), c.value)))) +
                          isnull(c.value2, convert(char(32), c.value)))
				END,
			"Unit" = convert(char(20), c.unit),
			"Type" = convert(char(20), c.type)

			from master.dbo.sysconfigures b,
				master.dbo.syscurconfigs c
			where 
				b.config = @confignum and

				b.config *= c.config 


			/*
                        ** If the configuration value and run value are equal
                        ** then display a message that there will not be any
                        ** change in configuration parameter and exit.
                        */

                        if (@is_equal = 1)
                        begin
				if (@confignum = 507)
				begin
					select @configvalue2 = @optlevel_curr,
				   	   @oldcfgvalue_char = @optlevel_curr
				end
                                /*
                                ** 18932, Resulting configuration value
                                ** and memory use have not changed from
                                ** previous values: new configuration
                                ** value %1!, previous configuration %2!
                                */
                                exec sp_getmessage 18932, @msg output
				/* for integer datatype. */
                                if (@oldcfgvalue_char is NULL)
                                begin
                                        print @msg,  @configvalue, @oldcfgvalue
                                end
                                else
                                begin
                                /* for character datatype. */
                                        print @msg,  @configvalue2, @oldcfgvalue_char
                                end
                                return(0)
                        end

			/*
			** print reboot message if this option is not
			** dynamic.
			*/
			if ((@sysstatus & 8) = 8)
			begin
				exec sp_getmessage 17419, @msg output
				print @msg
			end
			else
			begin
				exec sp_getmessage 18123, @msg output
				print @msg
			end
			/*
			** Lets us calculate @additional_memory i.e. the 
			** increase in 'total logical memory'
			*/
			select 	@additional_memory = 
					(value - @logical_memory) * 2 
			from 	master.dbo.syscurconfigs
			where 	config = @lmemconfignum


			/*
			** print additional memory message 
			*/
			if (@additional_memory > 0)
			begin
				/*
				** 18916, Changing the value of '%1!' to '%2!' 
				** increases the amount of memory ASE uses 
				** by %3! K.
				*/
				if (@unit != "name")
				begin
					exec sp_getmessage 18916, @msg output
					print @msg,  @fullconfigname,
					      @configvalue, @additional_memory
				end
				else
				begin
					/* 
					** For configure options with name
					** as their units, they use 
					** configvalue2 (type of varchar)
					** to specify the intended value
					** insteading of configvalue (type
					** of int).
					*/
					exec sp_getmessage 18916, @msg output
					print @msg,  @fullconfigname,
					      @configvalue2, @additional_memory
				end
			end
			else if (@additional_memory < 0)
			begin
				/*
				** 18917, Changing the value of '%1!' to '%2!' 
				** reduces the amount of memory ASE uses 
				** by %3! K. The reduced memory may be
				** reused when this configure value changes,
				** but will not be released until ASE restarts.
				*/
				select @additional_memory = @additional_memory * -1 
				if (@unit != "name")
				begin
					exec sp_getmessage 18917, @msg output
					print @msg,  @fullconfigname, 
					      @configvalue, @additional_memory
				end
				else
				begin
					exec sp_getmessage 18917, @msg output
					print @msg,  @fullconfigname, 
					      @configvalue2, @additional_memory
				end
			end
			else
			begin
				/*
				** 18397, Changing the value of '%1!'
				** does not increase the amount of 
				** memory Adaptive Server uses.
				*/
				exec sp_getmessage 18397, @msg output
				print @msg,  @fullconfigname
			end

			return(0)
		end
		else
			return(1)
	end

end

/*
** @configcount=0 implies @configname is not valid
** @configname=NULL implies displaying all the parameters except for
** the parameters with the config number equal to 19 or the parent equal
** to 19 since those parameters are displayed by sp_cacheconfig.
*/
if (@configcount = 0)
begin
	/* 18124, "No matching configuration options.  
	** Here is a listing of groups:" 
	*/
	raiserror 18124
	select distinct convert(char(50), name)
		from master.dbo.sysconfigures
		where config < 100
		and parent != 19
		and config != 19
		order by name
	return(1)
end
else if (@configname is NULL and @non_default_options is NULL)
begin

	select @configname = "Config"

end

/*
** retrieve the display level from sysattributes
*/
select @user_displaylevel = int_value from master.dbo.sysattributes where
	class = 4 AND
	attribute = 0 AND
	object_type = 'L' AND
	object = suser_id()

/*
** set the default display level to 10 if it is not defined in sysattributes
*/
if (@user_displaylevel is NULL)
	select @user_displaylevel = 10

/*  
** If non_default_options is set, display only nondefault settings depending 
** on current display level and return
*/	
if(@non_default_options = 1)
begin 
	/* Display all config parameters for specified instance. */
	if @configvalue3 is not NULL
	begin
		if @configvalue3 != @@instancename
		begin
			raiserror 19519, @configvalue3
			return (1)
		end
		else
		begin
			select  Parameter_Name = convert(char(30), name), 
				Default_Value = convert(varchar(11), defvalue), 
				Memory_Used = convert(varchar(11), c.comment), 
				Config_Value = isnull(b.value2, 
						      convert(char(32), b.value)),
				Run_Value  = isnull(c.value2, 
						    convert(char(32), c.value)), 
				Unit = convert(char(20), c.unit), 
				Type_ = convert(char(10), c.type)

			into #temptable1 
			from master.dbo.sysconfigures b, 
			     master.dbo.syscurconfigs c 
			where 
			      
				b.config = c.config
			      and (c.defvalue != isnull(b.value2, 
						  convert(char(32), b.value)) 
			        or c.defvalue != isnull(c.value2, 
						  convert(char(32), c.value))) 
			      and c.config != 114 
					/* Exclude option 'configuration file' */
			      and c.type != "read-only" 
			      and display_level <= @user_displaylevel

			exec sp_autoformat #temptable1,
				@selectlist = "'Parameter Name' = Parameter_Name,
				'Default'= Default_Value,'Memory Used' = Memory_Used,
				'Config Value '= Config_Value,'Run Value'= Run_Value,
				
				'Unit' = Unit,'Type'= Type_",

				@orderby = "order by Parameter_Name"
			return (0)
		end
	end

	if @@system_view = "instance"
	begin
		/*
		** Display the information of the config parameter
		** for the current instance as well as the cluster-wide
		** one.
		*/
        	select  Parameter_Name = convert(char(30), name),
			Default_Value = convert(varchar(11), defvalue),
			Memory_Used = convert(varchar(11), c.comment),
			Config_Value = isnull(b.value2, convert(char(32), b.value)),
			Run_Value  = isnull(c.value2, convert(char(32), c.value)),
			Unit = convert(char(20), c.unit),
			Type_ = convert(char(10), c.type)

		into #temptable3
		from master.dbo.sysconfigures b,
	     	     master.dbo.syscurconfigs c
		where   

			b.config = c.config
			and (c.defvalue != isnull(b.value2, convert(char(32), b.value)) 
		    	  or c.defvalue != isnull(c.value2, convert(char(32), c.value)))	  
			and c.config != 114 
					/* Exclude option 'configuration file' */ 
			and c.type != "read-only"
			and display_level <= @user_displaylevel 

		exec sp_autoformat #temptable3, 
			@selectlist = "'Parameter Name' = Parameter_Name, 
			'Default'= Default_Value,'Memory Used' = Memory_Used, 
			'Config Value '= Config_Value,'Run Value'= Run_Value, 

			'Unit' = Unit,'Type'= Type_", 

			@orderby = "order by Parameter_Name"
	end
	else
	begin
		/* 
		** When system_view is set to 'cluster', we need to
		** display the config info across all instances. This
		** includes two part: one is the cluster-wide config
		** setting whose instanceid is NULL; the other
		** part is the info for each instance who has a valid
		** instanceid.
		*/
		select distinct
			Parameter_Name = convert(char(30), name), 
			Default_Value = convert(varchar(11), defvalue), 
			Memory_Used = convert(varchar(11), c.comment), 
			Config_Value = isnull(b.value2, convert(char(32), b.value)), 
			Run_Value  = isnull(c.value2, convert(char(32), c.value)), 
			Unit = convert(char(20), c.unit), 
			Type_ = convert(char(10), c.type)
						
		into #temptable 
		from master.dbo.sysconfigures b, master.dbo.syscurconfigs c 
		where 
			
			b.config = c.config 
			and (c.defvalue != isnull(b.value2, 
						  convert(char(32), b.value)) 
			  or c.defvalue != isnull(c.value2, 
						  convert(char(32), c.value))) 
			and c.config != 114 
					/* Exclude option 'configuration file' */ 
			and c.type != "read-only" 
			and display_level <= @user_displaylevel


		
		exec sp_autoformat #temptable, 
			@selectlist = "'Parameter Name' = Parameter_Name,
			'Default'= Default_Value,'Memory Used' = Memory_Used,
			'Config Value '= Config_Value,'Run Value'= Run_Value,

			'Unit' = Unit,'Type'=Type_",
		
			@orderby = "order by Parameter_Name"
	end
	return (0)

end 	    	
	
/*
**      If @use_wildcard = 0 and the default sortorder is case-insensitive
** dictionary sort order, use exact match: name = @configname to get row,
** otherwise use wildcard match: name like "%" + @configname + "%".
*/
 
if (@use_wildcard = 0 and @nocase = 1)
begin
        select  @confignum = config,
                @parent = config,
                @sysname = name,
                @sysstatus = status
        from master.dbo.sysconfigures
                where name = @configname
                and config != 19
end
else
begin
	select	@confignum = config, 
		@parent = config,
		@sysname = name,
		@sysstatus = status
	from master.dbo.sysconfigures
		where name like "%" + @configname + "%"
		and config != 19
end

select	@children = count(*)
	from master.dbo.sysconfigures
	where parent =  @confignum

if @children = 0
begin
	/* @@nestlevel is problem area if a sproc calls sp_configure */
	/* could pass in another param when recursing */
	if @@nestlevel > 1
	begin
		/* reached a leaf, notify parent */
		return(1)
	end
	else
	begin

		begin
			/* Display the information of the config parameter 
			** for the current server as well as the cluster-wide
			** one. Instanceid is NULL meaning this is the 
			** cluster-wide configuration.
			*/ 
			select "Parameter Name" = convert(char(30), name),
                        "Default" = CASE WHEN b.config = 507 THEN @optlevel_def
				ELSE convert(char(11), space(11-char_length(
                                    convert(varchar(11), defvalue)))+
                                    convert(varchar(11), defvalue))
				END,
                        "Memory Used" = convert(char(11), space(11-char_length(
                                        convert(varchar(11), c.comment)))+
                                        convert(varchar(11), c.comment)),
                        "Config Value" = CASE WHEN b.config = 507 THEN @optlevel_curr
				ELSE convert(char(12), space(12-char_length(
                          isnull(b.value2, convert(char(32), b.value)))) +
                          isnull(b.value2, convert(char(32), b.value)))
				END,
                        "Run Value" = CASE WHEN b.config = 507 THEN @optlevel_run
				ELSE convert(char(12), space(12-char_length(
                          isnull(c.value2, convert(char(32), c.value)))) +
                          isnull(c.value2, convert(char(32), c.value)))
				END,
			"Unit" = convert(char(20), c.unit),
			"Type" = convert(char(20), c.type)

			from master.dbo.sysconfigures b,
			     master.dbo.syscurconfigs c
			where 

				b.config *= c.config
				and name like "%" + @configname + "%"
				and b.config != 19
				and parent != 19
		end

	end

	return (0)
end
else
begin
	select @msg = "Group: " + @sysname
	print ""
	print @msg
	print ""

	/* this poor guy has kids, so recurse to leaves */
	declare config_curs cursor for 
		select config, name, parent 
		from master.dbo.sysconfigures 
		where parent = @parent
		order by name
		
	open config_curs

	fetch config_curs into @sysconfig, @sysname, @sysparent

	while (@@sqlstatus = 0)
	begin

		execute @status = sp_configure @sysname

		if (@status = 1)
		begin
			/*
			** this guy has leaves as kids,
			** so print out the leaves with
			** display level <= @user_displaylevel
			** Note: If a config parameter has more than one
			** parent, the extra parents are stored in
			** 'sysattribures'.
			*/
			create table #configure_temp (config int)

			insert into #configure_temp
				select distinct a.config
					from master.dbo.sysconfigures a,
					master.dbo.syscurconfigs b
					where
			  	   	   display_level <= @user_displaylevel
				   	   and parent = @parent
					   and a.config != 19
					   and a.config = b.config

		  		    union
				    select distinct config
					from master.dbo.syscurconfigs,
					master.dbo.sysattributes
					where
			  	   	   display_level <= @user_displaylevel
					   and class = 4
					   and attribute = 1
					   and object_type = 'CP'
				   	   and int_value = @parent
					   and object = config
					   and config != 19


			if exists (select * from #configure_temp)
			begin

				/*
				** If system_view is 'instance', display
				** the config info for the current instance
				** as well as the cluster-wide one.
				*/

			 	begin
			    		select 
					"Parameter Name" = convert(char(30), name),
					"Default" = CASE WHEN b.config = 507
						THEN @optlevel_def
						ELSE convert(char(11), 
						space(11-char_length(
						convert(varchar(11), defvalue))) +
						convert(varchar(11), defvalue))
						END,
					"Memory Used" = 
						convert(char(11), 
						space(11-char_length(
						convert(varchar(11), c.comment))) +
						convert(varchar(11), c.comment)),
					"Config Value" = CASE WHEN b.config = 507 
						THEN @optlevel_curr
						ELSE convert(char(12),
						space(12-char_length(
		 	 			isnull(b.value2, 
						convert(char(32), b.value)))) +
		 	 			isnull(b.value2, 
						convert(char(32), b.value)))
						END,
					 "Run Value" = CASE WHEN b.config = 507
					 	THEN @optlevel_run
						ELSE convert(char(12), 
						space(12-char_length(
			 			isnull(c.value2, 
						convert(char(32), c.value)))) +
			 			isnull(c.value2, 
						convert(char(32), c.value)))
						END,
			  		"Unit" = convert(char(20), c.unit),
			  		"Type" = convert(char(20), c.type)

			   		from master.dbo.sysconfigures b,
					     master.dbo.syscurconfigs c
			   		where b.config in
						(select config 
						 from #configure_temp)
					and b.config = c.config

			   		order by name
				end

			end

			drop table #configure_temp

			close config_curs
			deallocate cursor config_curs

			return(0)
		end
		else
		begin
			/*
			** this lucky guy has grandkids, so, continue
			*/
			fetch config_curs into 
				@sysconfig, @sysname, @sysparent

		end
	end

	close config_curs
	deallocate cursor config_curs

	return(0)
end

go
exec sp_procxmode 'sp_configure', 'anymode'
go
grant execute on sp_configure to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dboption')
begin
	drop procedure sp_dboption
end
go
print "Installing sp_dboption"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/a_values */

/*
** Messages for "sp_dboption"           17420
**      Use "langid" when looking at spt_values ???
**
** 17260, "Can't run %1! from within a transaction." 
** 17420, "Settable database options."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17423, "Usage: sp_dboption [dbname, optname, {true | false}]"
** 17424, "Database option doesn't exist or can't be set by user."
** 17425, "Run sp_dboption with no parameters to see options."
** 17426, "Database option is not unique."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 17430, "Run the CHECKPOINT command in the database that was changed."
** 17431, "true"
** 17432, "false"
** 17433, "Database option '%1!' turned ON for database '%2!'."
** 17434, "Database option '%1!' turned OFF for database '%2!'."
** 17289, "Set your curwrite to the hurdle of current database."
** 17436, "You cannot set the '%1!' option for a temporary database"
** 17439, "You cannot turn on ''%1!' for '%2!' because it is an HA server 
** 	that has been configured with the proxy_db option."
** 18974, "Warning: Attempting to change database options for a 
** 	   temporary database. Database options must be kept consistent
** 	   across all temporary databases."
** 19015, "The 'async log service' option is only valid for configurations 
**	   with more than 4 engines online."
** 19112, "Running CHECKPOINT on database '%1!' for option '%2!' to take effect."
** 19113, "CHECKPOINT command failed. Run the CHECKPOINT command in database '%1!' for the 
**         change to take effect."
** 19424, "Cannot run '%1!' on an archive database."
** 19884, "You cannot set the '%1!' option to '%2!' for a temporary database."
** 19518, "Warning: Attempting to change database options for a local
**         temporary database. Database options must be kept consistent
**         across all local temporary databases."
** 19886, "Please execute DUMP DATABASE before executing DUMP TRANSACTION."
** 19892, "DUMP TRANSACTION is not allowed when '%1!' is ON. Use DUMP DATABASE 
	or DUMP TRANSACTION ... WITH TRUNCATE_ONLY or WITH NO_LOG instead."
** 19987, "You cannot set the '%1!' option for temporary databases or for 
	   databases with durability %2!"
*/

create procedure sp_dboption
@dbname varchar(30) = NULL,		/* database name to change */
@optname varchar(20) = NULL,		/* option name to turn on/off */
@optvalue varchar(10) = NULL,		/* true or false */
@dockpt	tinyint	= 1			/* 
					** 0 indicates don't run checkpoint 
					** else run checkpoint automatically
					*/
as

declare @dbid int			/* dbid of the database */
declare @dbuid int			/* id of the owner of the database */
declare @statvalue int,			/* number of option */
	@stattype char(2),		/* status field flag */
	@statopt smallint,		/* option mask, part 1 */
	@stat2opt smallint,		/* option mask, part 2 */
	@stat3opt int			/* option mask, part 3 */
declare @optcount int			/* number of options like @optname */
declare @success_msg varchar(1024)	/* success status message */
declare @msg varchar(1024)
declare @sptlang	int
declare @true		varchar(10)
declare @false		varchar(10)
declare @whichone	int		/* which language? */
declare	@optmsgnum	int		/* identify one msgnum to compare */
declare	@msgcnt		int		/* count distinct dups */
declare @tempdb_mask	int		/* all tempdb status bits */
declare @local_tempdb_mask int		/* all local tempdb status bits */
declare @isatempdb	int		/* changing options on a temp. db ? */
declare @ismixedlog	int		/* does database have mixed log,data */ 
declare @engines	int		/* Get the number of engines */
declare @isarchivedb	int		/* Is this an archive database? */
declare @DMPX_NOTOK_NONLOGGED_WRITES	int /* Same definition as in dmpld.h */
declare @DMPX_NOTOK_TRUNCATED_ONLY	int /* Same definition as in dmpld.h */
declare @durability	varchar(30)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0, @isatempdb = 0, @isarchivedb = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end


/*
**  If no @dbname given, just list the possible dboptions.
**  Only certain status bits may be set or cleared.  
**	   settable                	    not settable
**      ------------------------------  --------------------------
**	allow select into/bulkcopy (4)	don't recover (32)
**	read only (1024)		not recovered (256)
**	dbo use only (2048)		dbname has changed (16384)
**	single user (4096)
**	truncate log on checkpoint (8)
**	no checkpoint on recovery (16)
**	allow null (8192)
**	ddl in tran (512)
**      ALL SETTABLE OPTIONS (15900)
**	abort xact on log full (1, type='D2')
**	no space accounting (2, type='D2')
**	auto identity(4, type='D2')
**	identity in nonunique index(8, type='D2')
**	auto identity unique index(64, type='D2')
**	async log service	  (1024 type='D3')
**	delayed commit   	  (2048 type='D3')
**      scratch database (16777216 type='D3')
*/

/*
** Look for the "settable options" mask in spt_values
*/
select @statopt = number
from master.dbo.spt_values
where type = "D"
  and name = "ALL SETTABLE OPTIONS"

select @stat2opt = number
from master.dbo.spt_values
where type = "D2"
  and name = "ALL SETTABLE OPTIONS"


select @stat3opt = number
from master.dbo.spt_values
where type = "D3"
   and name = "ALL SETTABLE OPTIONS"

/*
** If we can't find the option masks, guess at them
*/
if @statopt is null
	select @statopt  = 4 | 8 | 16 | 512 | 1024 | 2048 | 4096 | 8192
if @stat2opt is null
	select @stat2opt = 1 | 2 | 4 | 8 | 64
if @stat3opt is null
	select @stat3opt = 1024 | 2048 | 16777216

if @dbname is null
begin
	exec sp_getmessage 17420, @msg output
	print @msg

	if @sptlang = 0
	    select database_options = name
		from master.dbo.spt_values
		where ((type = "D"
			and number & @statopt = number
			and number & @statopt != @statopt)
		    or (type = "D2"
			and number & @stat2opt = number
			and number & @stat2opt != @stat2opt)
		    or (type = "D3"
			and number & @stat3opt = number
			and name != "ALL SETTABLE OPTIONS"))
		order by name
	else
	    select database_options = name, convert(char(22), description)
		from master.dbo.spt_values, master.dbo.sysmessages
		where ((type = "D"
			and number & @statopt = number
			and number & @statopt != @statopt)
		    or (type = "D2"
			and number & @stat2opt = number
			and number & @stat2opt != @stat2opt)
		    or (type = "D3"
			and number & @stat3opt = number
			and name != "ALL SETTABLE OPTIONS"))
		  and msgnum = error
		  and langid = @sptlang
		order by name
	return (0)
end

/*
**  Verify the database name and get the @dbid and @dbuid
*/
select @dbid = dbid, @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so and list the databases.
*/
if @dbid is NULL
begin
	raiserror 17421
	return (1)
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if ((suser_id() != @dbuid) and (proc_role("sa_role") < 1))
	return(1)

/*
**  You can not change any of the options in master.  If the user tries to
**  do so tell them they can't.
*/
if @dbid = 1
begin
	raiserror 17422
	return (1)
end

/*
** Determine if we are changing options for a temporary database.
*/
select @tempdb_mask =  number
	from master.dbo.spt_values
	where   type = "D3" and name = "TEMPDB STATUS MASK"

if (@dbid = 2) or exists (select * from master.dbo.sysdatabases
	     	            where dbid = @dbid
	     	            and (status3 & @tempdb_mask) != 0)
begin
	select @isatempdb = 1
end
else
if exists (select * from master.dbo.sysdatabases
                            where dbid = @dbid
                            and (status3 & 4194304) = 4194304)
begin
	select @isarchivedb = 1
end

select @durability = db_attr(@dbid, "durability")

/*
** If attempting to change the options for a temporary database, the user
** should be warned that database options across all temporary databases
** should be kept consistent.
*/
select @local_tempdb_mask = 0

if (@@clustermode != "shared disk cluster" and @isatempdb = 1)
begin
	exec sp_getmessage 18974, @msg output
	print @msg
end
else if (@@clustermode = "shared disk cluster")
begin
	select @local_tempdb_mask = number
		from master.dbo.spt_values
		where   type = "D3" and name = "LOCAL TEMPDB STATUS MASK"

	if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid
			and (status3 & @local_tempdb_mask) != 0)
	begin
		/*
		** In SDC, #table appears only in local tempdbs, global tempdb
		** is mostly like the regular databases, dboptions doesn't
		** need to be same among global tempdbs.
		**
		** 19518, "Warning: Attempting to change database options for a
		**	   local temporary database. Database options must be
		**	   kept consistent across all local temporary 
		**	   databases."
		*/
		exec sp_getmessage 19518, @msg output
		print @msg
	end
end

/*
**  Check remaining parameters.
*/
exec sp_getmessage 17431, @true out
exec sp_getmessage 17432, @false out
if @optname is NULL or lower(@optvalue) not in 
	("true", "false", @true, @false) or @optvalue is null
begin
	raiserror 17423
	return (1)
end

/*
**  Use @optname and try to find the right option.
**  If there isn't just one, print appropriate diagnostics and return.
*/
select @optcount = count(*)
   from master.dbo.spt_values
	where name like "%" + @optname + "%"
	  and ((type = "D"
		and number & @statopt = number)
	    or (type = "D2"
		and number & @stat2opt = number)
	    or (type = "D3"
		and number & @stat3opt = number))
/*
**  If more than one option like @optname, make sure they are not the same
**  option ("trunc" and "trunc.", for example)
*/
if @optcount > 1
begin
	select  @optmsgnum = msgnum
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))

	select @msgcnt = count(msgnum)
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
	          and msgnum != @optmsgnum

	/* 
	** msgcnt of 0 indicates we really have just 1 unique dboption, 
	** probably due to alternate spelling.
	*/
	if (@msgcnt = 0) 
		select @optcount = 1
end
/*
** If no option, and alternate language is set, use other language
*/
if @optcount = 0 and @sptlang != 0
begin
    select @optcount = count(*)
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
		  and msgnum = error
		  and langid = @sptlang
    select @whichone = 1
    /*
    **  If more than one option like @optname, make sure they are not the same
    **  option ("trunc" and "trunc.", for example)
    */
    if @optcount > 1
    begin
	select  @optmsgnum = msgnum
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
		  and msgnum = error
		  and langid = @sptlang

	select @msgcnt = count(msgnum)
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
	    	    or (type = "D3"
		        and number & @stat3opt = number))
		  and msgnum = error
		  and langid = @sptlang
	          and msgnum != @optmsgnum

	/* 
	** msgcnt of 0 indicates we really have just 1 unique dboption, 
	** probably due to alternate spelling.
	*/
	if (@msgcnt = 0) 
		select @optcount = 1
    end
end

/*
**  If no option, show the user what the options are.
*/
if @optcount = 0
begin
	raiserror 17424

	exec sp_getmessage 17425, @msg output
	print @msg
	return (1)
end

/*
**  If more than one option like @optname, show the duplicates and return.
*/
if @optcount > 1
begin
	raiserror 17426

	if @sptlang = 0
	    select duplicate_options = name
		from master.dbo.spt_values
			where name like "%" + @optname + "%"
			  and ((type = "D"
				and number & @statopt = number)
			    or (type = "D2"
				and number & @stat2opt = number)
	    	    	    or (type = "D3"
		        	and number & @stat3opt = number))
	else
	    select duplicate_options = name, convert(char(22), description)
		from master.dbo.spt_values, master.dbo.sysmessages
			where (name like "%" + @optname + "%"
				or description like "%" + @optname + "%")
			  and ((type = "D"
				and number & @statopt = number)
			    or (type = "D2"
				and number & @stat2opt = number)
	    	    	    or (type = "D3"
		        	and number & @stat3opt = number))
			  and msgnum = error
			  and langid = @sptlang

	return (1)
end


if db_name() != "master"
begin
	raiserror 17428
	return (1)
end

/*
** User cannot set a temporary  database in single user mode or as a scratch 
** database.
*/
select @statvalue = number
   from master.dbo.spt_values
	where name like "%" + @optname + "%"
	  and ((type = "D"
		and number & @statopt = number)
	    or (type = "D2"
		and number & @stat2opt = number)
	    or (type = "D3"
		and number & @stat3opt = number))
 
if (@isatempdb = 1) and ((@statvalue & (4096 | 16777216)) != 0)
begin
	raiserror 17436, @optname
	return (1)
end

/* disallow turning off the 'select into' option for a temporary database. */
if 	(@isatempdb = 1) 
    and (@statvalue = 4) 
    and (lower(@optvalue) in ('false', @false))
begin
	raiserror 19884, @optname, @false
	return (1)
end
/* 
** Only the 'single user option' may be changed in an archive database.
*/
if (@isarchivedb = 1) and (@statvalue != 4096)
begin
	raiserror 19424, "sp_dboption"
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_dboption"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
**  Get the number which is the bit value to set
*/
if @whichone = 0
       	  select @statvalue = number, @stattype = type, @success_msg = name
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%"
		  and ((type = "D"
			and number & @statopt = number)
		    or (type = "D2"
			and number & @stat2opt = number)
		    or (type = "D3"
			and number & @stat3opt = number))
else
    select @statvalue = number, @stattype = type, @success_msg = name
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%"
			and ((type = "D"
			      and number & @statopt = number)
			  or (type = "D2"
			      and number & @stat2opt = number)
		    	  or (type = "D3"
				and number & @stat3opt = number))
			and msgnum = error
			and langid = @sptlang

/*
** We do not allow 'sybsecurity' to be set to 'single user' since,
** if auditing is enabled and we try to set 'sybsecurity' database to
** 'single user' then, the audit process is killed because audit process
** tries to do 'usedb' and it fails (look at utils/auditing.c).
*/
if (@dbname = "sybsecurity") and (@statvalue = 4096)
begin
	/*
	** 17435, "The 'single user' option is not valid for the
	** 'sybsecurity' database.
	*/
	raiserror 17435
	return (1)
end
 
/*
** We do not allow Async logging services on system  databases. 
*/

if (@statvalue = 1024) and (@stattype = "D3") 
begin
	/* 
	** Not valid for master, model and systemp tempdb, user define tempdbs and
	** the sybsecurity database
	*/
	if (@dbname in ("master","model", "sybsystemdb", "sybsystemprocs", "sybsecurity", "dbccdb", "dbccalt", "sybsyntax"))
		OR (@isatempdb = 1)
	begin
		/*
		** 18984, The 'async log service' option is not valid 
		** for system databases 
		*/
		raiserror 18984
		return(1)
	end

	/* We don't allow this option for databases with mixed log and data */
	select @ismixedlog = status2 & 32768 
		from master.dbo.sysdatabases
			where dbid = @dbid

	if(@ismixedlog = 32768)
	begin
		/*
		** 18986, The 'async log service' option is only valid for 
		** configurations with more than 4 engines online.
		*/
		raiserror 18986
		return(1)
	end

	select @engines = count(engine)
		from master.dbo.sysengines
		where status != "offline"

	if (@engines < 4)
	begin
		raiserror 19015
		return(1)
	end
end

/*
** For IMDB/RDDB databases disallow 'delayed commit' and 'async log service'.
*/
if   ((@durability in ('at_shutdown', 'no_recovery'))
  and (@statvalue in (1024, 2048))
  and (@stattype = "D3")
 )
begin
       select @durability = upper(@durability)
       raiserror 19987,  @optname, @durability
       return (1)
end
	
/*
**  Now update sysdatabases.
*/
if lower(@optvalue) in ("true", @true)
begin
	/* 
	** If this is the option to set 'abort tran on log full' to 
	** true for sybsecurit database, then don't allow.
	*/
	if (db_name(@dbid) = "sybsecurity" 
		and @stattype = "D2" and @statvalue = 1)
	begin
		/*
		** AUDIT_CHANGE: New error message needs to be reserved and
		** the print statement needs to be removed.
		*/
		print "You cannot set 'abort tran on log full' to true for sybsecurity database."
		return (1)
	end

	/*
	** Disallow DDL IN TRAN 
	**	if proxydb option is set (@@crthaproxy = 1)
	**	if this server is a HA server (@@cmpstate >= 0)
	**	if database is not a tempdb
	*/
	if ((@statvalue = 512) and (@@crthaproxy = 1) and
		(@@cmpstate >= 0) and (@isatempdb = 0))
	begin
		/*
		** Cannot set DDL_IN_TRAN option for HA servers
		** configured with proxy_db option.
		*/
		exec sp_getmessage 17439, @msg output
		print @msg, @success_msg, @dbname
		return (1)
	end

	if (@stattype = "D")
		update master.dbo.sysdatabases
			set status = status | @statvalue
				where dbid = @dbid
	else if( @stattype = "D2")
		update master.dbo.sysdatabases
			set status2 = status2 | @statvalue
				where dbid = @dbid
	else
		update master.dbo.sysdatabases
			set status3 = status3 | @statvalue
				where dbid = @dbid
	exec sp_getmessage 17433, @msg output
	print @msg, @success_msg, @dbname
end

/*
**  We want to turn it off.
*/
else
begin

	if (@stattype = "D")
		update master.dbo.sysdatabases
			set status = status & ~@statvalue
				where dbid = @dbid
	else if (@stattype = "D2")
		update master.dbo.sysdatabases
			set status2 = status2 & ~@statvalue
				where dbid = @dbid
	else
		update master.dbo.sysdatabases
			set status3 = status3 & ~@statvalue
				where dbid = @dbid
	exec sp_getmessage 17434, @msg output
	print @msg, @success_msg, @dbname
end

if (@dockpt != 0)
begin
	exec sp_getmessage 19112, @msg output
	print @msg, @dbname, @success_msg

	/*
	**  Run the CHECKPOINT command on the database that was changed. If
	**  that fails advise the user to run the CHECKPOINT command in the database 
	**  that was changed.
	*/
	checkpoint @dbname

	if (@@error != 0)
	begin
		exec sp_getmessage 19113, @msg output
		print @msg, @dbname
	end
end
else
begin
	exec sp_getmessage 17430, @msg output
	print @msg
end

return (0)
go
exec sp_procxmode 'sp_dboption', 'anymode'
go
grant execute on sp_dboption to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropdevice')
begin
	drop procedure sp_dropdevice
end
go
print "Installing sp_dropdevice"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/dropdevice */

/*
** Messages for "sp_dropdevice"         17482
**
** 17260, "Can't run %1! from within a transaction." 
** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices." 
** 17482, "Device is being used by a database. You can't drop it."
** 17483, "Device dropped."
*/

create procedure sp_dropdevice
@logicalname	varchar(255)		/* logical name of the device */

as
declare @msg varchar(1024)
declare @len1 int, @len2 int
declare @status int
declare @status2 int
declare @factor int
declare @adbclass int

select @adbclass = 28

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_dropdevice"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
**  Check and make sure that the device actually exists.
*/
if not exists (select * 
		from master.dbo.sysdevices
			where name = @logicalname)
begin
	/*
	** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices." 
	*/
	raiserror 17471
	return (1)
end

/*
**  Check and make sure that no database is using the device.
**  If so, print out who is using it and exit.
*/
if exists (select *
	from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname)
begin
	/*
	** 17482, "Device is being used by a database. You can't drop it."
	*/
	raiserror 17482
   
	select @factor = @@maxpagesize / @@pagesize 

	select @len1 = max(datalength(a.name)),
	       @len2 = max(datalength(c.name))
	from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname

	if (@len1 > 23 or @len2 > 21)
	    select database_name = a.name,
		device = c.name,
		size = convert(varchar(25), (size / 512) * @factor) + " MB"
	    from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname
	    order by a.name, c.name, size
	else
	    select database_name = convert(char(23), a.name),
		device = convert(char(21), c.name),
		size = convert(varchar(25), (size / 512) * @factor) + " MB"
	    from master.dbo.sysdatabases a, master.dbo.sysusages b, 
			master.dbo.sysdevices c
		where a.dbid = b.dbid
			and b.vdevno = c.vdevno
			and ((c.status & 6 != 0) or (c.status2 & 8 != 0))
			and c.name = @logicalname
	    order by a.name, c.name, size

	return (1)
end
else if exists (select 1
        from master..sysattributes a
        where a.class=@adbclass
        and a.object_type = 'D'
        and a.attribute = 1
        and a.object_cinfo = @logicalname)
begin
        /*
        ** 17482, "Device is being used by a database. You can't drop it."
        */
        raiserror 17482

        select convert(char(30), name), convert(char(40), char_value)
        from master.dbo.sysdatabases a, master.dbo.sysattributes b
        where b.class = @adbclass
        and b.object_type = 'D'
        and b.attribute = 1
        and b.object_cinfo = @logicalname
        and b.object = a.dbid

        return (1)
end

/*
**  Everything's ok so drop the device.
*/
select @status = status from master.dbo.sysdevices
	where name = @logicalname
	
select @status2 = status2 from master.dbo.sysdevices
	where name = @logicalname
/*
** If database device or cache device (status2 & 8), close it and remove it 
** from the sysdevices table using "disk release" command.  If dump device,
** remove it from sysdevices table.
**/
if (((@status & 6) != 0) or ((@status2 & 8) != 0))
	disk release name = @logicalname
else
	delete master.dbo.sysdevices 
		where name = @logicalname
if (@@error != 0)
	return (1)

/*
** 17483, "Device dropped."
*/
exec sp_getmessage 17483, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_dropdevice', 'anymode'
go
grant execute on sp_dropdevice to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_version')
begin
	drop procedure sp_version
end
go
print "Installing sp_version"
go

/*
** Generated by spgenmsgs.pl on Thu Sep 16 22:53:10 2004 
*/
/*
** raiserror Messages for version [Total 6]
**
** 18524, "%1!: Permission denied. This operation requires System Administrator (sa_role) role."
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
** 19378, "Delete from the table %1! affected %2! rows but expected %3! rows to be deleted. Command aborted."
** 19379, "Update of the table %1! affected %2! rows but expected %3! rows to be updated. Command aborted."
** 19380, "Error in accessing the table %1!."
** 19381, "Invalid argument to %1!. It requires a non-null value."
*/
/*
** sp_getmessage Messages for version [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*      5.0     1.0     09/10/04      sproc/src/version */

/*
** This procedure SP_VERSION is used to find the
** version of the install scripts. In addition to 
** this it also gives the details of the successfull
** installation such as begining and ending Date with
** Time of the installation.
**
** This procedure uses the master.dbo.sysattributes
** to store all the required information. The
** columns used for storing the information is
** as follows
**
**	Column Name	Information stored
**	------------	------------------
**	object_cinfo 	Script file name
**	char_value	Version String
**	comments	Date and Time info.
**	int_value	Code value
**			(used internally)
**	
** In sysattributes this procedure will access the rows
** defined under the class 23.
**	
** Usage:
** ------
** sp_version [@Scriptfile [, @verbose [, @version [, @code ] ] ] ]
**
** Returns:
**	 0	 - Successful execution.
**	 1	 - Invalid options.
**	 2	 - Insert/Update failures.
**
*/

create procedure sp_version
	@script_file	varchar(255)	= NULL,
	@verbose	varchar(3)	= NULL,
	@version	varchar(255)	= NULL,
	@code		varchar(5)	= NULL	
as

declare @class 		int
	, @check_exist	int
	, @date		varchar(150)
	, @start_date	varchar(150)
	, @end_date	varchar(150)
	, @featurecode	varchar(2)
	, @attr_code	int
	, @loc_error	int
	, @loc_rowcount	int

select @class = 23
	, @check_exist = 0
	, @start_date = NULL
	, @end_date =  NULL
	, @featurecode = 'sv'
	, @attr_code = 2	-- randomly choosen for this feature

/*
** If code = NULL means it is in reportin mode.
*/

if (@code IS NULL)	
begin	--{
	/*
	** Check whether the information is for
	** a specific install script. If so return
	** the required information. Otherwise return
	** all the rows with class = 23.
	*/
	if(@version IS NULL)
	begin --{
		select object_cinfo as Script, char_value as Version,
			comments as "Start_End_Date", 
			case int_value
			when 0 then 'Incomplete'
			else 'Complete'
			end as "Status"
		into #sysattributes
		from master.dbo.sysattributes
		where class = @class and object_type = @featurecode
		  and attribute = @attr_code
		  and (@script_file IS NULL
			or object_cinfo like @script_file)
	
		/*
		** If verbose option is set then print all the information 
		** including the date and time information.
		*/

		if (@verbose IS NULL)
		begin
			exec sp_autoformat #sysattributes,
					 "Script, Version, Status", null,
					"ORDER BY 1"
		end
		else if (@verbose = 'all')	
		begin
			exec sp_autoformat #sysattributes, 
					"Script, Version, Status, 
					'Start/End Date' = Start_End_Date", 
					null, "ORDER BY 1"
		end
		else
		begin
			raiserror 19194, "verbose","all"
			return(1)
		end 
	end --}
	else
	begin --{
		/* 
		** version is non-null means it is updating / insert mode
		** raise appropriate error messages for script file and
		** code value.
		*/
		if (@script_file IS NULL)
			raiserror 19381, "script_file"
		raiserror 19194, 'code', "'start', 'end'."
		return (1)
	end --}
return (0)
end	--}
else if (@version IS NULL or @script_file IS NULL)
begin
	/*
	** If code is not NULL then check if script_file or version is NULL.
	** If any of them are NULL then give an appropriate error message.
	*/
	if (@version IS NULL) 
		raiserror 19381, "version"
	if (@script_file IS NULL)
		raiserror 19381, "script_file"
	if (@code != 'start' and @code != 'end')
		raiserror 19194, 'code', "'start', 'end'"
	return (1)
end
else
begin
	/*
	** If all the above conditions are satisfied and code is not NULL
	** then we need to insert / update the version string. To do this
	** check whether the use has 'sa_role'.
	*/
	if (proc_role("sa_role") = 0)
	begin
		raiserror 18524, "sp_version"
		return (1)
	end
end

if (@code = 'start')	
begin	--{
	/*
	** code = 'start' means the begining of the installation (install
	** script). Before adding a new row to sysattributes check
	** for the previous rows and take appropriate action.
	*/
	
	begin tran update_version_string
	
	delete from master.dbo.sysattributes
	where class = @class and object_type = @featurecode
	  and attribute = @attr_code
	  and object_cinfo = @script_file

	select @loc_error = @@error, @loc_rowcount = @@rowcount	
	
	if (@loc_error != 0)	--{
	begin
		raiserror 19380, "sysattributes"
		rollback update_version_string
		return (2)
	end	--}

	if (@loc_rowcount > 1)	--{
	begin
		raiserror 19378, "sysattributes", @@rowcount, "1"
		rollback update_version_string
		return (2)
	end	--}

	insert into master.dbo.sysattributes(class, object_type, 
	attribute, object_cinfo, char_value, int_value, comments)
	  values(@class, @featurecode, @attr_code, @script_file,
	     @version, 0, "[Started=" + convert(varchar, getdate())+"]")

	if (@@error != 0)
	begin
		raiserror 19380, "sysattributes"
		rollback update_version_string
		return (2)
	end

	commit tran update_version_string
	return (0)
end	--}
else if (@code = 'end')	
begin	--{
	/*
	** @code = 'end' represents the successfull installation
	** of the script. Change int_value to reflect this
	** Before updating check whether the script is 
	** is registered for the installation. If so update
	** row for the script file with int_value = 0.
	** Otherwise raise an error.
	*/

	begin tran complete_version_string

	/*
	** The script is registered at the begining of the
	** Installtaion.
	*/

	select @date = convert(varchar, getdate())
	
	select @start_date=comments
	from master.dbo.sysattributes
	where class=@class and attribute = @attr_code
	  and object_type = @featurecode
	  and object_cinfo=@script_file
	

	if (@start_date IS NOT NULL)	--{
	begin
		select @end_date = @start_date
			+ '-[Completed=' + @date+']'

		update master.dbo.sysattributes
		set int_value = 1, comments=@end_date
		where class=@class and attribute = @attr_code
		  and object_type = @featurecode
		  and object_cinfo=@script_file

		select @loc_error = @@error, @loc_rowcount = @@rowcount	

		if (@loc_error != 0 ) --{	
		begin
			raiserror 19380, "sysattributes"
			rollback complete_version_string
			return (2)
		end	--}

		if (@loc_rowcount > 1) --{	
		begin
			raiserror 19379, "sysattributes", @@rowcount, "1"
			rollback complete_version_string
			return (2)
		end	--}
	end	--}
	else
	begin	--{	

		select @end_date = "[Completed=" + @date+"]"

		insert into master.dbo.sysattributes
		(class, object_type, attribute, object_cinfo, char_value, 
							int_value, comments)
		values(@class, @featurecode, @attr_code, @script_file, 
							@version, 1, @end_date)
		
		if (@@error != 0)	--{
		begin
			raiserror 19380, "sysattributes"
			rollback complete_version_string
			return (2)
		end	--}

	end	--}
	
	commit tran complete_version_string
	return (0)
end	--}
else	
begin
	raiserror 19194, 'code', "'start', 'end'"
	return (1)
end
go
go
exec sp_procxmode 'sp_version', 'anymode'
go
grant execute on sp_version to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

declare @retval int
exec @retval = sp_version 'installmaster', NULL, '15.5/EBF 17340 SMP/P/x86_64/Enterprise Linux/ase155/2391/64-bit/OPT/Mon Nov  9 14:15:35 2009', 'start'
if (@retval != 0) select syb_quit()
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_validaltlang')
begin
	drop procedure sp_validaltlang
end
go
print "Installing sp_validaltlang"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */

create procedure sp_validaltlang
@name	varchar(255)
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Check to see if this alias is in Syslanguages. */
if exists (select *
		from master.dbo.syslanguages
		where alias = @name)
begin
	return 0
end
return 1
go
exec sp_procxmode 'sp_validaltlang', 'anymode'
go
grant execute on sp_validaltlang to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_chklangparam')
begin
	drop procedure sp_chklangparam
end
go
print "Installing sp_chklangparam"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/chklangparam */
/*
** sp_checklangparam is called by sp_addlanguage to check the lists of
** full month names, short month names, and day names.  It returns a status
** indicating whether any errors were found:
**	0 - name list is valid
**	1 - spaces were found, which are not allowed
**	2 - not enough names in the list (must be exactly @numnames of them)
**	3 - too many names in the list (must be exactly @numnames of them)
**	4 - some name(s) are too long
**	5 - some name(s) have non-aphabetic characters
*/

/*
** Messages for "sp_chklangparam"       17373
**
** %1! is either "month" or "day" 
** 17373, "List of %1! names contains spaces, which are not allowed."
** 17374, "List of %1! names has too few names."
** 17375, "List of %1! names has too many names."
** 17376, "List of %1! names has name(s) which are too long."
** 17377, "List of %1! names contains name(s) which have '%2!' non-alphabetic characters."
** %2! is the character set name 
*/

create procedure sp_chklangparam
@namelist varchar(251),		/* month or day name list */
@msgparam varchar(30),		/* name of list, for error messages */
@numnames int,			/* correct number of names in the list */
@maxnamelen int			/* maximum length of any name in list */
as

	declare @totallen		int
	declare @mthlen			int
	declare @mthname		varchar(251)
        declare @csid                   int
        declare @csname                 varchar(30)

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

        /* Get the Character Set id (csid) */
	/* (Up to the version 4.2)
	   select @csid = csid from master..syscharsets
                where id = (select value from master..sysconfigures
                        where config = 123)
	*/
	/* (After 4.9) */
	select @csid = value from master..sysconfigures 
			where config = 131

        /* Get the Character Set Name (csname) */
        select @csname = name from master..syscharsets
                where id = @csid and type < 2000

	/* Make sure the list has no blanks. */
	if ( charindex( " ", @namelist ) != 0 )
	begin
		/*
		** 17373, "List of %1! names contains spaces, which are not allowed."
		*/
		raiserror 17373, @msgparam
		return 1
	end

	/* Keep track of number of *CHARACTERS* */
	select @totallen = char_length( @namelist )
	/* select @totallen = datalength( @namelist ) */
	while ( @totallen > 0 )
	begin
		/* Move to the next name in the list. */
		select @namelist = right( @namelist, @totallen )

		/* If this is not the last name in the list then there must
		** be another comma.
		*/
		if ( @numnames > 1 )
		begin
			select @mthlen = charindex( ",", @namelist ) - 1
			if ( @mthlen < 0 )
			begin
				/*
				** 17374, "List of %1! names has too few names."
				*/
				raiserror 17374, @msgparam
				return 2
			end
		end

		/* This is the last name in the list, so there cannot be
		** another comma.  This name is all remaining characters
		** in the list.
		*/
		else
		begin
			if ( charindex( ",", @namelist ) != 0 )
			begin
				/*
				** 17375, "List of %1! names has too many names."
				*/
				raiserror 17375, @msgparam
				return 3
			end
			select @mthlen = @totallen
		end

		/* Check the name length. */
		if ( @mthlen > @maxnamelen )
		begin
			/*
			** 17376, "List of %1! names has name(s) which are too long."
			*/
			raiserror 17376, @msgparam
			return 4
		end

		/*
		** Check to see that the names contain only valid
		** P_ALPHA characters; not even DIGITs should be allowed.
		** Note that valid_name() returns a bit-mask of the lexical
		** values found in the string passed to it, where P_ALPHA
		** is 0x01.
		*/
		if (valid_name(substring(@namelist, 1, @mthlen)) != 1)
		begin
      			/*
			** 17377, "List of %1! names contains name(s) which have 
			** '%2!' non-alphabetic characters."
			*/
			raiserror 17377, @msgparam, @csname
			return 5
		end

		/* Move to the next name in the list. */
		select @numnames = @numnames - 1
		select @totallen = @totallen - @mthlen - 1
	end

	/* No problems were found with the name list. */
	return 0
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpgroup')
begin
	drop procedure sp_helpgroup
end
go
print "Installing sp_helpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helpgroup"          17630
**
** 17333, "No group with the specified name exists."
*/
create procedure sp_helpgroup
@grpname varchar(30) = NULL		/* group name of interest */
as

declare @msg varchar(1024)
declare @len1 int, @len2 int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  If no group name given, list all the groups.
*/
if @grpname is NULL
begin
	select Group_name = name, Group_id = gid 
	into #helpgrouprs
	from sysusers G
	where ((G.uid between @@mingroupid and @@maxgroupid) or G.uid = 0) 
	and not exists (select * from sysroles R where G.uid = R.lrid)
	exec sp_autoformat @fulltabname = #helpgrouprs,
		@orderby = "order by Group_name"
	drop table #helpgrouprs

	return (0)
end

/*
**  Check to see if group exists.
*/
if not exists (select * from sysusers where name = @grpname
		and ((uid between @@mingroupid and @@maxgroupid) or uid = 0))
	or exists (select name from master.dbo.syssrvroles 
		where name = @grpname) 
begin
	/* 17333, "No group with the specified name exists." */
	exec sp_getmessage 17333, @msg output
	print @msg
	return (1)
end

if (@grpname != "public")
begin
	/*
	**  List the particulars for the group.
	*/
    	    	select Group_name = g.name, Group_id = g.gid,
		Users_in_group = u.name, Userid = u.uid
		into #helpgroup1rs
		from sysusers u, sysusers g where g.name like @grpname
		and g.uid = u.gid and 
		((g.uid between @@mingroupid and @@maxgroupid) or g.uid = 0)
		and u.uid != u.gid
	exec sp_autoformat @fulltabname = #helpgroup1rs,
		@orderby = "order by Group_name,Users_in_group" 
	drop table #helpgroup1rs
end
else
begin
	/*
	**  Special case for "public" group.  List all users, including users
	**  in other groups.  They also belong to "public" group.
	*/
    		select Group_name = g.name, Group_id = g.gid,
		Users_in_group = u.name, Userid = u.uid
		into #helpgroup2rs
		from sysusers u, sysusers g
		where g.name like @grpname and
		((g.uid between @@mingroupid and @@maxgroupid) or g.uid = 0)
		and u.uid != u.gid
	 exec sp_autoformat @fulltabname = #helpgroup2rs,
		 @orderby = "order by Group_name,Users_in_group"
	drop table #helpgroup2rs
end
return (0)
go
exec sp_procxmode 'sp_helpgroup', 'anymode'
go
grant execute on sp_helpgroup to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpuser')
begin
	drop procedure sp_helpuser
end
go
print "Installing sp_helpuser"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helpuser"           17700
**
** 17700, "Users aliased to user."
** 17701, "The name supplied is a group name."
** 17702, "The name supplied is aliased to another user."
** 17703, "The name supplied is not a user, group, or aliased."
** 17704, "Curread label needs to dominate the hurdle of the current database."
** 17705, "The supplied name is a role name. Please resubmit the command with 
**		the name of a user, group or aliased."
*/
create procedure sp_helpuser
@name_in_db varchar(255) = NULL
as

declare @msg varchar(1024)
declare @len1 int, @len2 int, @len3 int



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on


/*
**  If no @name_in_db, list all the users.
*/
if @name_in_db is NULL
begin



	select Users_name = u.name, ID_in_db = u.uid,
		Group_name = g.name,
		Login_name = m.name
	into #sphelpuser2rs
			from sysusers u, sysusers g,
				master.dbo.syslogins m
			where u.suid *= m.suid
				and u.gid *= g.uid
				and ((u.uid < @@mingroupid and u.uid != 0) 
				or (u.uid > @@maxgroupid))
	exec sp_autoformat @fulltabname = #sphelpuser2rs,
		@orderby = "order by Users_name"
	drop table #sphelpuser2rs


    return (0)
end

/*
**  See if the @name_in_db is a user.  If so, print out the info for
**  the user, including users pretending to be the user (sysaliases).
*/
if exists (select * from sysusers 
		where name = @name_in_db
		and ((uid < @@mingroupid and uid != 0) 
		or (uid > @@maxgroupid)))
begin



	    select Users_name = u.name, ID_in_db = u.uid,
		Group_name = g.name,
		Login_name = m.name
	    into #sphelpuser4rs	
		from sysusers u, sysusers g, master.dbo.syslogins m
		where u.suid *= m.suid
		and u.gid *= g.uid
		and u.name = @name_in_db
		and ((u.uid < @@mingroupid and u.uid != 0) 
		or (u.uid > @@maxgroupid))
	    exec sp_autoformat @fulltabname =  #sphelpuser4rs	
	    drop table #sphelpuser4rs	


	declare @suid	int

	select @suid = suid
		from sysusers 
			where name = @name_in_db

	/*
	** If anyone is using @name_in_db as an alias print it out.
	*/
	if exists (select *
			from sysalternates
		where altsuid = @suid)
	begin
		/* 17700, "Users aliased to user." */
		exec sp_getmessage 17700, @msg out
		print @msg
		select Login_name = suser_name(suid)
		into #sphelpuser5rs
			from sysalternates
				where altsuid = @suid
		exec sp_autoformat @fulltabname = #sphelpuser5rs,
			@orderby = "order by Login_name"
		drop table #sphelpuser5rs
	end

	return (0)
end

/*
**  Maybe the @name_in_db is a group.  If so print out the info.
*/
if exists (select * from sysusers
		where name = @name_in_db
		and ((uid = 0) or (uid between @@mingroupid and @@maxgroupid)))
	and not exists (select name from master.dbo.syssrvroles
		where name = @name_in_db)
begin
	/* 17701, "The name supplied is a group name." */
	exec sp_getmessage 17701, @msg out
	print @msg
	execute sp_helpgroup @name_in_db
	return (0)
end

/*
**  Check if @name_in_db might be aliased.
*/
if exists (select *
		from sysalternates
			where suid = suser_id(@name_in_db))
begin
	/* 17702, "The name supplied is aliased to another user." */
	exec sp_getmessage 17702, @msg out
	print @msg





	select Alias_name = u.name, ID_in_db = u.uid,
		Group_name = g.name,
		Login_name = m.name
	into #sphelpuser7rs
	from sysusers u, sysusers g, sysalternates a,
	master.dbo.syslogins m
	where u.suid *= m.suid
	and u.gid *= g.uid
	and ((u.uid < @@mingroupid and u.uid != 0) 
	or (u.uid > @@maxgroupid))
	and a.suid = suser_id(@name_in_db) 
	and a.altsuid = u.suid
	exec sp_autoformat @fulltabname = #sphelpuser7rs
	drop table #sphelpuser7rs


	return (0)
end

/*
**  Maybe the @name_in_db is a role.  If so print out the message.
*/
if exists (select name from master.dbo.syssrvroles
		where name = @name_in_db)
begin
	/* 17705, "The supplied name is a role name. Please resubmit the 
	** command with the name of a user, group or aliased" 
	*/
	raiserror 17705
	return (1)
end

/* 17703, "The name supplied is not a user, group, or aliased." */
raiserror 17703
return (1)
go
exec sp_procxmode 'sp_helpuser', 'anymode'
go
grant execute on sp_helpuser to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_locklogin')
begin
	drop procedure sp_locklogin
end
go
print "Installing sp_locklogin"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	5.0	1.0	10/22/91	sproc/src/locklogin */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:17 2006 
*/
/*
** raiserror Messages for locklogin [Total 3]
**
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 18388, "You must be in the master database in order to run '%1!'."
** 18409, "The built-in function '%1!' failed. Please see the other messages printed along with this message."
** 19606, "To lock inactive accounts, you must run 
** 	    'sp_passwordpolicy 'set','enable last login updates',1'."
** 19607, "You cannot specify both 'inactive_days' and 'unlock' at the same time."
*/
/*
** sp_getmessage Messages for locklogin [Total 16]
**
** 17260, "Can't run %1! from within a transaction."
** 17880, "No such account -- nothing changed."
** 17912, "Error in locking the account."
** 17913, "Locked account(s):"
** 17914, "Account unlocked."
** 17917, "Error: locktype must either be 'lock' or 'unlock'."
** 17918, "Nothing changed."
** 17919, "Account locked."
** 18419, "Account 'sybmail' cannot be unlocked."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."
** 19390, "One or more accounts do not exist on the companion server."
** 19391, "Warning: One or more accounts specified are active."
** 19392, "Permission Denied. The current account is already locked."
** 19393, "The sets of sa/sso logins on the primary and companion servers are not same."
** 19394, "The set of logins specified is empty."
** 19395, "The login or role to be excluded from locking/unlocking is invalid."
** 19444, "The range for %1! is %2! to %3!."
** 19643, "No account(s) locked."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**		if (@nHARSTClass = 1)
**			begin tran ha_dynsyn
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**		if (@@error != 0)
**			goto clean_all
**		if (@nHARSTClass = 1)
**		begin
**			insert master.dbo.rmt_ha_syslogins ......
**			if (@@error != 0)
**				goto clean_all
**			
**			commit tran ha_dynsyn
**		end
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**			if (@nHARSTClass = 1)
**				rollback tran ha_dynsyn
**		
**		return (1)
*/

create procedure sp_locklogin
@loginame varchar(30) = NULL,		/* name of the login to be locked */
@locktype varchar(30) = NULL,		/* "locked" or "unlock"            */
@except	  varchar(30) = NULL,		/* login/role to be exempted	*/
@inactive_days int    = NULL            /* no of inactive days of a login */
as
declare @suid int			/* suid of login to be modified   */
declare @msg	varchar(1024)		/* message text */
declare @dummy int
declare @HA_CERTIFIED tinyint   	/* Is the SP HA certified ? */
declare @retstat  int
declare @current_id int			/* suid of the current login */
declare @except_is_login tinyint	/* flag to indicate if exception is login/role */ 
declare @except_is_role  tinyint
declare @encompasses_all_logins tinyint 
declare @warning_active	tinyint
declare @row_count_temp	int
declare @encompasses_all_rmt_ha_logins tinyint
declare @temp_current_id int
declare @current_date datetime
declare @scope varchar(32)		/* SDC command execution scope */

select @HA_CERTIFIED = 0
select @except_is_login = 0
select @except_is_role = 0
select @encompasses_all_logins = 1
select @encompasses_all_rmt_ha_logins = 1
select @warning_active = 0
select @row_count_temp = 0
select @current_date = getdate()



declare @log_for_rep int
declare @db_rep_level_all int
declare @db_rep_level_none int
declare @db_rep_level_l1 int
declare @lt_rep_get_failed int

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_locklogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/* create a dummy table to store temporary rows */
create table #dummy_table(suid int)

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	exec sp_getmessage 17260, @msg output
	print @msg, "sp_locklogin"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_locklogin"
	return (1)
end



/*
** Check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sso_role") = 0)
	return (1)


if @loginame is NULL and @locktype is NULL
begin
	/*
	** 17913, "Locked account(s):"
	*/
	exec sp_getmessage 17913, @msg output
	print @msg
	select name
	from master.dbo.syslogins
	where ((status & 2) = 2) /* LOGIN_LOCKED */
	return (0)
end

if (@loginame is not NULL)
begin 
	/*  Check if any such account exists */

	if not exists (select suid 
			from master.dbo.syslogins 
			where name like @loginame)
	begin
		/*
		** 17880, "No such account -- nothing changed."
		*/
		exec sp_getmessage 17880, @msg output
		print @msg
		return (1)
	end

end 


if ((@locktype != "unlock") and (@locktype != "lock"))
begin
	/*
	** 17917, "Error: locktype must either be 'lock' or 'unlock'."
	*/
	exec sp_getmessage 17917, @msg output
	print @msg
	/*
	** 17918, "Nothing changed."
	*/
	exec sp_getmessage 17918, @msg output
	print @msg
	return (1)
end

/* 
** Check if the exception specified is a login or a role 
** and set the variable @except_is_login accordingly
*/

if (@except is not NULL)
begin
	if exists (select 1 from master.dbo.syslogins 
			where name = @except)
	begin
		/* @except is a login  */

		select @except_is_login = 1 
	end

	/* Check if @except is a valid role */
	if exists (select 1 from master.dbo.sysloginroles as srole,
			 	 master.dbo.syssrvroles as rolename
			where srole.srid = rolename.srid
			and rolename.name = @except)
	begin
		select @except_is_role = 1
	end

	if (@except_is_login = 0) and (@except_is_role = 0)
	begin
		/* 19395, The login or role to be excluded from locking/unlocking is invalid */
		exec sp_getmessage 19395, @msg output
		print @msg
		return (1)
	end
end

/*
** Check if the user specified "effectively NULL" set of logins
** to be locked/unlocked. If so, return doing nothing
** For instance the user might have specified same set of logins
** to be locked as the set to be exempted.
*/

if (@loginame is not NULL) and
	 (((@except_is_login = 1) and 
		(not exists (select suid from master.dbo.syslogins
				where name like @loginame
				and name != @except))) or
   	   ((@except_is_role = 1) and 
		(not exists (select suid from master.dbo.syslogins
				where name like @loginame and
			      	suid not in
				(select suid from master.dbo.sysloginroles 
				      	where srid = role_id(@except))))) ) 
begin

	/* 19394, "The set of logins specified is empty." */
	exec sp_getmessage 19394, @msg output
	print @msg

	return (1)
end





if @locktype = "unlock"
begin

	/* 'Sybmail' account cannot be unlocked */
	if (@loginame = "sybmail")
	begin
		/*
		** 18419, "Account 'sybmail' cannot be unlocked."
		*/
		exec sp_getmessage 18419, @msg output
		print @msg
		return (1)
	end
	
	/* '@inactive_days' and 'unlock' cannot be specified at the same time */
	if (@inactive_days != NULL)
	begin
		/*
		** 19607, "You cannot specify both
		** 'inactive_days' and 'unlock' at the same time."
		*/	
		exec sp_getmessage 19607, @msg output
		print @msg
		return (1)
	end

	/* Unlock any existing account */

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



	if (@loginame is NULL)
	begin
		if (@except_is_login = 1)	
		begin
			/*
			** Unlock logins except ones which match @except
			**
			** The columns lockdate, lockreason, locksuid are
			** reset with values NULL, NULL, NULL whenever
			** a login account is unlocked.
			**
			** The columns lockdate, lockreason and locksuid
			** are set to context specific values when an account
			** is locked. The values reflect the datetime,
			** reason code, and the suid of the login
			** that is locking the account.
			**
			** Changes to these columns should be recorded
			** in the audit trail, and will do so in a future 
			** ASE release when locking is done outside of 
			** stored procedure.
			*/
			update master.dbo.syslogins 
			set status = status & (~2),
			logincount = 0,
			lockdate = NULL,
			lockreason = NULL,
			locksuid = NULL
			where name != @except
		end
		else 
		if (@except_is_role = 1)
		begin
			/* 
			** @except is a role 
			** Unlock all logins except ones whose role matches
			** @except
			*/

			update master.dbo.syslogins 
			set status = status & (~2),
			logincount = 0,
			lockdate = NULL,
                        lockreason = NULL,
                        locksuid = NULL
                        where suid not in
				(select suid from master.dbo.sysloginroles
                              		where srid = role_id(@except))
		end
		else
		begin
			/* @except is NULL */
			update master.dbo.syslogins
			set status = status & (~2),
			logincount = 0,
			lockdate = NULL,
                        lockreason = NULL,
                        locksuid = NULL
		end
	end
	else
	begin
		/* 
		** @loginame is not NULL 
		** Same cases as above but considering @loginame as well
		** Unlock logins which match the specified @loginame 
		** excluding the ones mentioned in @except
		*/

		if (@except_is_login = 1)
		begin
			update master.dbo.syslogins
			set status = status & (~2),	/* LOGIN_UNLOCKED */
			logincount = 0,
			lockdate = NULL,
                        lockreason = NULL,
                        locksuid = NULL
			where name like @loginame
				and name != @except
		end
		else 
		if (@except_is_role = 1)
		begin
			update master.dbo.syslogins
			set status = status & (~2),
			logincount = 0,
			lockdate = NULL,
                        lockreason = NULL,
                        locksuid = NULL
			where name like @loginame and
                        	suid not in
				(select suid from master.dbo.sysloginroles
        		                where srid = role_id(@except))
		end	
		else 
		begin
			update master.dbo.syslogins 
			set status = status & (~2),
			logincount = 0,
			lockdate = NULL,
                        lockreason = NULL,
                        locksuid = NULL
			where name like @loginame
		end
	end



	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_locklogin", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec
	
	/*
	** 17914, "Account unlocked."
	*/
	exec sp_getmessage 17914, @msg output
	print @msg
	return (0)
end

/*
**  When it comes down to here, it must be the complicated "lock" case.
*/

select @current_id = suser_id()
/*
** Check if the set of logins to be locked (after taking exceptions into 
** consideration) encompasses all the sso/sa logins in the server.
** If it does, we will be locking all the sa/sso logins; so in this case 
** leave out the current login and lock the rest of the logins.
** If it doesn't, go ahead and lock the set of logins specified.
** By encompassing all sso/sa logins, we mean there must be atleast
** one login with sso privilege and at least one login with sa privilege
** outside our locking set. First we check for sso logins (srid =1) and
** then for sa logins (srid = 0) and set the flag @encompasses_all_logins 
** to false even if one of them is satisfied.
*/

if (@loginame is not NULL)
begin 
	if (@except_is_login = 1)
	begin
		/* 
		** SSO logins srid = 1 and SA logins srid = 0
		** If there exists an sso and sa login outside the
		** set of logins to be locked then it means
		** the set doesn't encompass all of sso and sa logins
		** Similar logic applied in the subsequent code
		** with changes according as login or role specified
		*/

		if exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 1 and
				(ms.name not like @loginame or ms.name = @except))
		   and 
		   exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 0 and
				(ms.name not like @loginame or ms.name = @except))
		begin
			select @encompasses_all_logins = 0
		end

	end
	else if (@except_is_role = 1)
	begin
		/*
		** Taking into consideration the exception specified is a role,
		** find out if the set of logins to be locked doesn't encompass
		** all SA and all SSO logins
		*/
		if exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 1 and	
				((ms.name not like @loginame) or 
				ms.suid in
				(select suid from master.dbo.sysloginroles
					where srid = role_id(@except))) )
		   and
		   exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 0 and	
				((ms.name not like @loginame) or 
				ms.suid in
				(select suid from master.dbo.sysloginroles
					where srid = role_id(@except))) )
		
		begin
			select @encompasses_all_logins = 0
 		end	

	end
	else
	begin
		/* 
		** @except is NULL
		** See if the set of logins to be locked encompasses
		** all SA logins or all SSO logins
		** If it doesn't encompass all SA logins and all SSO
		** logins set @encompasses_all_logins to 0.
		*/
		if exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 1 and
				ms.name not like @loginame)
		   and
		   exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 0 and
				ms.name not like @loginame)
		begin
			select @encompasses_all_logins = 0
		end

	end
end 
else 
begin
	/* @loginame = NULL */

	if (@except_is_login = 1)
	begin	
		/*
		** Set @encompasses_all_logins to 0 if there exists
		** one SA and one SSO login outside the set of logins 
		** to be locked.
		*/
		if exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 1 and
				ms.name = @except)
		   and
		   exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 0 and
				ms.name = @except)
		begin
			select @encompasses_all_logins = 0
		end

	end
	else if (@except_is_role = 1)
	begin
		/* 
		** The exception specified is a role. Set @encompasses_all_logins
		** as above considering this @except as a role
		*/
		if exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 1 and
				ms.suid in
				(select suid from master.dbo.sysloginroles
					where srid = role_id(@except)) )
		   and
		   exists (select 1 from master.dbo.syslogins as ms,
					 master.dbo.sysloginroles as msr
				where (ms.status)&2 = 0 and
				ms.suid = msr.suid and
				msr.srid = 0 and
				ms.suid in
                                (select suid from master.dbo.sysloginroles
                                        where srid = role_id(@except)) )
		begin
			select @encompasses_all_logins = 0
		end
	
	end
end

/*
** check if @inactive_days is in valid range 0-32767 and
** 'enable last login' is 1 in sysattributes.
*/
if (@inactive_days != NULL)
begin
	if ((@inactive_days < 0) or (@inactive_days > 32767))
	begin
		/*
                ** 19444,  "The range for %1! is %2! to %3!."
                */
                raiserror 19444, 'inactive days', 0, 32767
                return(1)
	end
	/*
	** no of inactive days = today's date - last login date.
	** For calculation of inactive days, last login updates must be enabled,
	** so attribute row for 'enable last login updates' 
	** in sysattribute should not be set to 0.
	** Either the row should not exists OR it should be set to 1.
	*/
	if ((select int_value from master.dbo.sysattributes
                where class = 32 and attribute = 0) = 0)
                begin
                        /*
                        ** 19606, To lock inactive accounts, you must run
                        ** sp_passwordpolicy 'set','enable last login updates',1
                        */
			raiserror 19606
                        return (1)
                end
end
/*
**  If any of the accounts to be locked are active, go ahead and try 
**  to lock them, but issue a warning message.
**  If @encompasses_all_logins = 1 then the @current_id is not locked
**  but a warning message could be displayed erroneously as the account 
**  is active. So set @temp_current_id and use it to exclude the 
**  current account. If @encompasses_all_logins = 0 @current_id shouldn't
**  come into picture - hence invalidate it.
*/

if (@encompasses_all_logins = 1)
	select @temp_current_id = @current_id
else
	select @temp_current_id = -2 /* @temp_current_id is invalidated */

/*
** SDC only, check clusterwide sysprocesses for active login
*/
if (@@clustermode = "shared disk cluster")
begin
	select @scope=@@system_view
	set system_view cluster
end

if (@loginame is not NULL) 
begin
	if (@except_is_login = 1)
	begin
		/* 
		** set @warning_active to 1 if the set of logins to
		** be locked has any active login
		*/
		if exists (select 1 from master.dbo.sysprocesses as mp,
					 master.dbo.syslogins as ms
				where mp.suid = ms.suid and
				ms.name like @loginame and
				ms.name != @except and
				ms.suid != @temp_current_id)
		begin
			select @warning_active = 1
		end

	end
	else if (@except_is_role = 1)
	begin
		/*
		** Similar to the above condition except that
		** the exception specified is a role
		*/
		if exists (select 1 from master.dbo.sysprocesses as mp,
					 master.dbo.syslogins as ms
				where mp.suid = ms.suid and
				ms.name like @loginame and
				ms.suid != @temp_current_id and
				ms.suid not in 
				(select suid from master.dbo.sysloginroles
					where srid = role_id(@except)) )
		begin		
			select @warning_active = 1
		end

	end
	else
	/* @except is NULL */
	begin
		/*
		** Find out if any login to be locked is active
		** There is no exception specified.
		*/
		if exists (select 1 from master.dbo.sysprocesses as mp,
					 master.dbo.syslogins as ms
				where ms.suid = mp.suid and
				ms.name like @loginame and
				ms.suid != @temp_current_id)
		begin
			select @warning_active = 1
		end
	end
end
else
begin
	/* @loginame = NULL */
	if (@except_is_login = 1)
	begin
		/* 
		** Find out if the set of logins to be locked has
		** any active login
		*/
		if exists (select 1 from master.dbo.sysprocesses as mp,
					 master.dbo.syslogins as ms
				where mp.suid = ms.suid and
				ms.name != @except and
				ms.suid != @temp_current_id)
		begin	
			select @warning_active = 1
		end

	end
	else if (@except_is_role = 1)
	begin
		/* 
		** Similar to the above case 
		** Here the @except specified is a role
		*/
		if exists (select 1 from master.dbo.sysprocesses as mp,
					 master.dbo.syslogins as ms
				where mp.suid = ms.suid and
				ms.suid != @temp_current_id and
				ms.suid not in 
				(select suid from master.dbo.sysloginroles
					where srid = role_id(@except)))
		begin		
			select @warning_active = 1
		end

	end
	else
	/* @except is NULL */
	begin
		if exists (select 1 from master.dbo.sysprocesses as mp,
					 master.dbo.syslogins as ms
				where ms.suid = mp.suid and
				ms.suid != @temp_current_id)
		begin
			select @warning_active = 1
		end	

	end
end
	
/*
** SDC only: restore previous system_view scope
*/
if (@@clustermode = "shared disk cluster")
begin
	set system_view @scope
end

if (@warning_active = 1)
begin
	/*
	** 19391, "Warning: One or more accounts specified are active."
	*/

	exec sp_getmessage 19391, @msg output 
	print @msg

	/* FALL THROUGH */
end




if (@encompasses_all_logins = 1)
begin 
	/*
	** Check if the current account is already locked. If yes,
	** flag an error as locking all accounts excluding the 
	** current is not possible.
	** In other words, an account which is already locked at
	** this point of time cannot be allowed to issue any lock 
	** command.
	** However, under certain race conditions where more than
	** one such accounts issue lock commands simultaneously,
	** this check doesn't guarantee consistency. If the current
	** account is locked AFTER this check passes through by some
	** other login, we have a situation where a locked account
	** will be allowed to lock other accounts. This drawback
	** cannot be overcome without removing the check and without
	** doing the check as well as locking operation in a transaction.
	** Considering it is rare that such a situation occurs, this
	** approach is adopted.
	*/

	if exists (select 1 from master.dbo.syslogins 
			where (status & 2) = 2 and
			suid = @current_id)
	begin
		/* 19392, Permission Denied. The current account is already locked. */
		exec sp_getmessage 19392, @msg output
		print @msg

		return (1)
	end

end

/*  Feel free to lock the account */

if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
	begin tran rs_logexec



/*
** There is a race condition possible. Even though we unlock the current account
** before quitting (see the later part of the code), if we lock the current account
** here AND the set of accts encompasses all SA/SSO logins, we have a situation 
** where for a brief period, all SA/SSO logins may be locked. So, if we find that
** all SA/SSO logins have been encompassed we exclude the current account(which has
** SA/SSO role) from locking in which case we set the variable @current_id to
** the suid of the current account. however if all SA/SSO logins have not been
** encompassed we need not exclude the current account from the set of logins 
** being locked, so invalidate the variable @current_id
*/

if (@encompasses_all_logins = 0)
	select @current_id = -2  /* Invalidate @current_id value */

if (@loginame is not NULL) 
begin
	if (@except_is_login = 1)
	begin
		/*
		** Lock all the accounts matching @loginame except
		** "@except" login and current account (current acct
		** may be valid or invalid)
		*/
		if (@inactive_days != NULL)
		begin
                        /*
                        ** As 'last login update' feature(securing passwords) 
			** will not be HA-ized in 15.0.2 release, we need 
			** to handle it specially on primary and companion server.
                        ** To keep locked accounts in sync, we compare 'lastlogindate' 
			** column on both servers, and use the most recent date 
			** to calculate inactive days.
                        **
                        ** Check if companion server is configured. and 
			** then accordingly decide the set of accounts to lock. 
                        */
                        if (@HA_CERTIFIED = 0)
                        begin
                                /*
                                ** Companion server is not configured, so you 
				** can use master.dbo.syslogins for lastlogindate.
				** No need to look at master.dbo.rmt_ha_syslogins
                                */
				update master.dbo.syslogins
				set status = status | 2, /* LOGIN_LOCKED */
				lockreason = 1,  /* locked because inactive */
				lockdate = @current_date,
				locksuid = suser_id()
				where name like @loginame
					and (status & 2) = 0
					and suid != @current_id
					and name != @except
					and (datediff(dd, isnull(lastlogindate, pwdate), @current_date)
						>= @inactive_days)
			end
                        else
                        begin
				/*
				** Companion server is configured.
				** If a login,
				** is inactive on primary server,
				** we check if it is inactive on companion server also.
				** If is inactive on both servers, then only it is locked.
				*/

				/*
				** A 'begin - end' block , that includes all statement in '##if - ##endif' only,
				** gives syntax error. The 'begin - end' block is considered as empty block.
				** following 'select' statement is included to avoid that error.
				*/
	                        select @dummy = 1
                        end
		end
		else /* @inactive_days = NULL  */	
		begin
			update master.dbo.syslogins
			set status = status | 2, /* LOGIN_LOCKED */
                        lockreason = 0,  /* locked manually using sp_locklogin */
                        lockdate =  @current_date,
                        locksuid = suser_id()
			where name like @loginame
				and (status & 2) = 0
				and suid != @current_id
				and name != @except
		end
	end
	else if (@except_is_role = 1)
	begin
		/*
		** Lock all the accounts matching @loginame except
		** those which have the role @except and excluding
		** current account (which may be valid or invalid)
		*/
		if (@inactive_days != NULL)
                begin
			if (@HA_CERTIFIED = 0)
                        begin
				update master.dbo.syslogins
				set status = status | 2, /* LOGIN_LOCKED */
				lockreason = 1,  /* locked because inactive */
				lockdate =  @current_date,
				locksuid = suser_id() 
				where name like @loginame
					and (status & 2) = 0
					and suid != @current_id
					and suid not in
						(select suid from master.dbo.sysloginroles
							where srid = role_id(@except))
					and (datediff(dd, isnull(lastlogindate, pwdate), @current_date)
							>= @inactive_days)
			end
			else /* HA server is configured */
			begin

	                        select @dummy = 1
			end
                end
                else /* @inactive_days = NULL  */
                begin
			update master.dbo.syslogins
			set status = status | 2,
                        lockreason = 0,  /* locked manually using sp_locklogin */
                        lockdate =  @current_date,
                        locksuid = suser_id()
			where name like @loginame 
				and (status & 2) = 0
				and suid != @current_id 
				and suid not in 
				(select suid from master.dbo.sysloginroles
        		             	where srid = role_id(@except))
		end
	end
	else
	/* @except is NULL */
	begin
		/*
		** Lock all the accounts matching @loginame 
		** excluding current account (which may be valid or invalid)
		*/
                if (@inactive_days != NULL)
                begin
			if (@HA_CERTIFIED = 0)
			begin
				update master.dbo.syslogins
				set status = status | 2, /* LOGIN_LOCKED */
				lockreason = 1,  /* locked because inactive */
				lockdate =  @current_date,
				locksuid = suser_id() 
				where name like @loginame
					and (status & 2) = 0
					and suid != @current_id
					and (datediff(dd, isnull(lastlogindate, pwdate), @current_date)
						>= @inactive_days)
			end
			else /* HA server is configured */
			begin

                                select @dummy = 1
			end
                end
                else /* @inactive_days = NULL  */
                begin
			update master.dbo.syslogins
			set status = status | 2,
                        lockreason = 0,  /* locked manually using sp_locklogin */
                        lockdate =  @current_date,
                        locksuid = suser_id()
			where name like @loginame
				and (status & 2) = 0
				and suid != @current_id
		end
	end
end
else
/* @loginame is NULL */
begin	
	if (@except_is_login = 1)
	begin		
		/* 
		** Lock all logins except that match @except 
		** leaving out current login
		*/
		 if (@inactive_days != NULL)
                 begin
			if (@HA_CERTIFIED = 0)
			begin
	                        update master.dbo.syslogins
        	        	set status = status | 2, /* LOGIN_LOCKED */
				lockreason = 1,  /* locked because inactive */
				lockdate =  @current_date,
				locksuid = suser_id()
                		where suid != @current_id
					and (status & 2) = 0
       		                 	and name != @except
                	        	and (datediff(dd, isnull(lastlogindate, pwdate), @current_date)
						>= @inactive_days)
			end
			else /* HA server is configured */
			begin

                                select @dummy = 1
			end
		end
                else /* @inactive_days = NULL  */
                begin
                        update master.dbo.syslogins
                        	set status = status | 2, /* LOGIN_LOCKED */
	                        lockreason = 0,  /* locked manually using sp_locklogin */
        	                lockdate =  @current_date,
                	        locksuid = suser_id()
	                        where suid != @current_id
					and (status & 2) = 0
		                        and name != @except
                end
	end
	else if (@except_is_role = 1)
	begin
		/* 
		** Lock all logins except whose role matches the
		** role specified as exception 
		*/
		if (@inactive_days != NULL)
		begin
			if (@HA_CERTIFIED = 0)
			begin
			update master.dbo.syslogins 
			set status = status | 2,
			lockreason = 1,  /* locked because inactive */
			lockdate =  @current_date,
			locksuid = suser_id()
			where suid != @current_id
				and (status & 2) = 0
				and suid not in
					(select suid from master.dbo.sysloginroles
						where srid = role_id(@except))
				and (datediff(dd, isnull(lastlogindate, pwdate), @current_date)
					>= @inactive_days)
			end
			else /* HA server is configured */
			begin

                                select @dummy = 1				
			end
		end
		else /* @inactive_days = NULL */
		begin
			update master.dbo.syslogins
			set status = status | 2,
	                lockreason = 0,  /* locked manually using sp_locklogin */
	                lockdate =  @current_date,
	                locksuid = suser_id()
			where suid != @current_id 
				and (status & 2) = 0
				and suid not in
					(select suid from master.dbo.sysloginroles
					where srid = role_id(@except))
		end
	end
	else
	begin
		/* No exception is specified */
		if (@inactive_days != NULL)
                begin
			if (@HA_CERTIFIED = 0)
			begin
                                update master.dbo.syslogins
                                set status = status | 2,
                                lockreason = 1,  /* locked because inactive */
                                lockdate =  @current_date,
                                locksuid = suser_id()
                                where suid != @current_id
					and (status & 2) = 0
       		                         and (datediff(dd, isnull(lastlogindate,pwdate), @current_date)
						>= @inactive_days)
                        end
			else
			begin

			select @dummy = 1
			end
		end
		else
		begin
			update master.dbo.syslogins
			set status = status | 2,
                        lockreason = 0,  /* locked manually using sp_locklogin */
                        lockdate =  @current_date,
                        locksuid = suser_id()
			where suid != @current_id
				and (status & 2) = 0
		end
	end
end

/*
** Because of some possible race-conditions unlock the account
** just before quitting to ensure the current account remains 
** unlocked. Race between different logins trying to lock a set of accounts
** The last login which executes this statement unlocks that
** account, at the end we are sure that at least one login remains unlocked
*/

select @row_count_temp = @@rowcount

if (@encompasses_all_logins = 1)
begin
	update master.dbo.syslogins
	set status = status & ~2 	/* Unlock current account before quitting */
	where suid = @current_id
end

/*
**  Check @@rowcount when it works
*/

if (@row_count_temp > 0)
begin



	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_locklogin", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec

	/*
	** 17919, "Account locked."
	*/
	exec sp_getmessage 17919, @msg output
	print @msg
	return (0)
end
else
begin
	/*
	** 19643, "No account(s) locked."
	*/
	exec sp_getmessage 19643, @msg output
	print @msg

	/* 
	** No accounts were locked, as there were no unlocked accounts to be locked.
	** so rollback the transaction , but return 0 as return value.
	*/
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
                rollback tran rs_logexec
	return (0)
end

clean_all:
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		rollback tran rs_logexec
        return (1)
go
exec sp_procxmode 'sp_locklogin', 'anymode'
go
grant execute on sp_locklogin to public
go
exec sp_procxmode 'sp_locklogin', 'rep_master'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_displaylogin')
begin
	drop procedure sp_displaylogin
end
go
print "Installing sp_displaylogin"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	5.0	1.0	10/22/91	sproc/src/displaylogin */

/*
** Messages for "sp_displaylogin"     17943
**
** 17231, "No login with the specified name exists."
** 17943, "Suid: %1!"
** 17944, "Loginame: %1!"
** 17945, "Fullname: %1!"
** 17949, "Locked: %1!"
** 17950, "Date of Last Password Change: %1!"
** 17951, "Configured Roles:"
** 18334, "Default Database: %1!"
** 18335, "Default Language: %1!"
** 18675, "Password expiration interval: %1!"
** 18676, "Password Expired: %1!"
** 18677, "Minimum Password Length: %1!"
** 18678, "Maximum failed logins: %1!"
** 18679, "Current failed login attempts: %1!"
** 18914, "Auto Login Script: %1!" 
** 19258, "Authenticate with: %1!"
** 19568, "No login with specified Server User ID exists"
** 19644, "Login Password Encryption: %1!"
** 19645, "Password column corrupted"
** 19681, "Last login date: %1!"
** 19682, "Account locked by ASE by manually executing sp_locklogin"
** 19683, "Account locked by ASE since account was inactive"
** 19684, "Account locked by ASE due to failed login attempts reaching max failed logins."
** 19685, "Account locked by ASE since login has not transitioned to SHA-256, after password downgrade."
*/

create procedure sp_displaylogin 
@loginame varchar(255) = NULL as

declare @suid int			/* suid of person to display */
declare @name varchar(30)		/* login name */
declare @suid_loginame varchar(30)	/* login name obtained through suid */
declare @fullname varchar(30)		/* login owner's full name */
declare @defdb varchar(30)
declare @deflang varchar(30)
declare @procname varchar(255)		/* login script name */
declare @procid int			/* proc id for the login script */
declare @auths    int
declare @status   int
declare @auth_status   int
declare @pwdate   datetime
declare @thisauth int
declare @authname varchar(30)
declare @msg      varchar(1024)
declare @msg_yes_or_no  varchar(30)
declare @local_msgbuf char(30)
declare @dummy int
declare @role_status	int
declare @enable_login_role int	/* value of the status bit which is used
				** for enabling a role
				*/
declare @loginexp int           /* value of login expiration */
declare @passwdexp int		/* value of password expiration */
declare @minpwdlen int		/* value of minimum password length */
declare @pwdexpired varchar(3)	/* has the login's password 
				** expired(YES/NO) ?? 
				*/
declare @maxfailedlogins int	/* value of maximum failed logins */
declare @currentfails int	/* value of current failed logins count */
declare @allauth int		/* authentication mechanisms mask */
declare @passeclass  int	/* class number of PASSWD_SECURITY 
				** class in master.dbo/sysattributes
				*/
declare @row_count int          /* value of number of rows selected */
declare @authmech varchar(15)   /* Authentication mechanism */
declare @locked varchar(4)      /* value of locked field */
declare @configroles varchar(1024) /* value of all configured roles stored
				   ** with delimiter
				   */
declare @password varbinary(128)
declare @vers1 tinyint		/* Contains byte 2 of password column */
declare @vers2 tinyint		/* Contains byte 32 of password column */
declare @encralgo varchar(30)	/* Contains type of encryption algorithm
				** information
				*/
declare @lastlogindate datetime,
	@locksuid int,
	@lockreason int,
	@lockdate datetime,
	@lockreasonmsg varchar(1024), /* Contains text for locked reason */
	@locksuidname varchar(30)     /* Contains login name who locked 
				      ** the account to be displayed
				      */

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Initialize variables */
select @enable_login_role = 1

if @loginame is NULL
	select @loginame = suser_name()

/*
**  Only accounts with SSO authorization
**  can display other login info.
**  Call proc_role() with the required SSO role.
*/

/*
** If @loginame contains only digits from 0-9 of any length
** then consider it as suid and get the corresponding name
** else consider it as name
*/
if (isnumeric(@loginame) > 0)
begin
        /*
        ** Check whether loginame contains "-","$" or "."
        ** since they are allowed by isnumeric() function
        */
        if @loginame not like '%[-$.]%'
        begin
                select @suid = convert(int,@loginame)
                select @suid_loginame = name 
			from master.dbo.syslogins where suid = @suid
		select @row_count = @@rowcount
		if @row_count != 0	/* Got a name for vaild suid */
		begin
                        /* Assign the @suid_loginame to @loginame for furthur use */
                        select @loginame = @suid_loginame						
		end		
	end
end
								
if (@loginame != suser_name ())
begin
	/* 
	** check if we are the sa or the sso. If show_role() 
	** does not find both "sa_role" and the "sso_role"
	** then we call proc_role() with each role to print
	** a messae and send the failure audit records if 
	** necessary.
	** Note: show_role does not print any message.
	*/
	if ( charindex ("sa_role", show_role())  = 0  and
	     charindex ("sso_role", show_role()) = 0  )
	begin
		select @dummy = proc_role("sa_role")	
		select @dummy = proc_role("sso_role")	
		return(1)	
	end
	else
	begin
		/*
		** Call proc_role() with each role that the user has 
		** in order to send the success audit records.  
		** Note that this could mean 1 or 2 audit records.
		*/
		if (charindex("sa_role", show_role()) > 0)
			select @dummy = proc_role("sa_role")
		if (charindex("sso_role", show_role())> 0)
			select @dummy = proc_role("sso_role")
	end
end

if @row_count = 0
begin
    	/* 19568, "No login with specified Server User ID exists." */
	raiserror 19568
       	return(1)
end
								
/*
** For getting the number of row/rows selected in the result set of cursor
** execute the query and get the rowcount in @row_count 
*/

select @row_count = count(1) from master.dbo.syslogins where name like @loginame

/*
** Declare a read only cursor to select all the required fields to be displayed
** after processing them for each login 
*/
declare display_login cursor for
select suid, password, name, fullname, dbname, language, procid,
status, pwdate, logincount, lastlogindate, locksuid, lockreason, lockdate
from master.dbo.syslogins
where name like @loginame

for read only

/* Open the cusor to fetch the contents in local variables */
open display_login

fetch display_login into
@suid, @password, @name, @fullname, @defdb, @deflang, @procid,
@status, @pwdate, @currentfails, @lastlogindate, @locksuid, @lockreason,
@lockdate

select @loginame = @name

if @suid is NULL
begin
	/*
	** 17231, "No login with the specified name exists."
	**	(was "Invalid Login user.")
	*/
	exec sp_getmessage 17231, @msg output
	print @msg
	return (1)
end

if @row_count <> 1
begin
        /*
        ** create a temporary table to store the information of logins matching
        ** a wildcard expression
        */
        create table #helpdisplay
        (
                suid int,
                name varchar(30),
                fullname varchar(30) NULL,
                dbname varchar(30),
                language varchar(30) NULL,
                procname varchar(255) NULL,
                locked varchar(4),
                pwdate datetime,
                passwdexp int,
                pwdexpired varchar(3),
                minpwdlen int,
                maxfailedlogins int,
                currentfails int NULL,
                authmech varchar(15),
                configroles varchar(1024) NULL,
		encralgo varchar(30) NULL
	)
end

while @@sqlstatus <> 2
begin
	if @@sqlstatus = 1
	begin
	        /*
	        ** 18999, "An error occurred while fetching data from a temporary
	        ** table. If there are no other error messages and this error
	        ** persists, please contact Sybase Technical Support."
	        */
		raiserror 18999						
		close display_login
		deallocate cursor display_login
		return (1)
	end
	/*
	** Process the required parameters and store values in local parameters
        ** after processing for display purpose
	*/
	
	select @procname = object_name(@procid, db_id(@defdb))

        if (@status & 2) = 2 /* LOCKED */
	begin
	        /* 17011, "yes" */
        	exec sp_getmessage 17011, @msg_yes_or_no output
	end
	else
	begin
	        /* 17010, "no" */
		exec sp_getmessage 17010, @msg_yes_or_no output
	end
        select @locked = upper(@msg_yes_or_no)
	
	begin 
		/* NOTE: For all password control related information printed
		** below, a check is made first if the specified login has 
		** a value configured for the attribute in sysattributes. If
		** there is no value, then the systemwide default is picked from
		** sysconfigures
		*/
	
		/* get the value of PASSWD_SECURITY class */
		select @passeclass = class from master.dbo.sysattributes where 
		object_type = "PS"
	
		/* Password expiration interval */
		select @passwdexp = int_value from master.dbo.sysattributes
		where class = @passeclass AND attribute = 0 AND object = @suid
			AND object_cinfo = "login"

                if @passwdexp is  NULL
                        select @passwdexp = int_value from master.dbo.sysattributes
                        where class = 27 AND attribute = 7
	
		if @passwdexp is  NULL
			select @passwdexp = value  
			from master.dbo.sysconfigures  
			where name = "systemwide password expiration"
	
		/* Has the login's password expired?? */
                /*
                ** Check if password complexity option - 'expire login'
                ** is set for this login.
                */
                select @loginexp = (@status & (hextoint("0x0004")))
                if @loginexp = 4
                        select @pwdexpired = "YES"
		else
		if @passwdexp = 0
			select @pwdexpired = "NO"
		else
	        	if ( datediff (dd, @pwdate, getdate()) >  @passwdexp )
	     	        	select @pwdexpired = "YES"
	        	else 
	      	        	select @pwdexpired = "NO"
	
		/* Minimum password length */
		select @minpwdlen = int_value from master.dbo.sysattributes
		where class = @passeclass AND attribute = 1 AND object = @suid
			AND object_cinfo = "login"

                if @minpwdlen is NULL
                        select @minpwdlen = int_value from master.dbo.sysattributes
                        where class = 27 AND attribute = 8
	
		if @minpwdlen is NULL
			select @minpwdlen = value  
			from master.dbo.sysconfigures  
			where name = "minimum password length"
	
		/* Maximum failed logins */
		select @maxfailedlogins = int_value from master.dbo.sysattributes
		where class = @passeclass AND attribute = 2 AND object = @suid
			AND object_cinfo = "login"

                if @maxfailedlogins is NULL
                        select @maxfailedlogins = int_value from master.dbo.sysattributes
                        where class = 27 AND attribute = 9
	
		if @maxfailedlogins is NULL
			select @maxfailedlogins = value 
			from master.dbo.sysconfigures
			where name = "maximum failed logins"
		
		/* Count of current failed logins */
		select @currentfails = logincount from master.dbo.syslogins
		where suid = @suid
		
		/* Set a mask with all the authentication bits */
		select @allauth = low 
		from master.dbo.spt_values
		where type="ua" and upper(name) = 'AUTH_MASK'

		if ((@status & @allauth) = 0) 
			select @auth_status = @allauth
		else
			select @auth_status = (@status & @allauth)

		select @local_msgbuf = NULL

	        /*
        	** Select the authentication mechanism name from spt_values except
	        ** 'AUTH_MASK' which is used only as a value and not as a valid
	       	** authmech name to be displayed.
        	*/
		select @local_msgbuf =  convert(char(15), name)
		from master.dbo.spt_values
		where low = @auth_status and type="ua"
		and name not in ('AUTH_MASK')

		if (@local_msgbuf is null or @local_msgbuf = 'ANY')
		begin
			select @local_msgbuf = upper(name) from master.dbo.spt_values
			where type = 'ua' and upper(name) = 'AUTH_DEFAULT'
		end
		select @authmech = @local_msgbuf

                /* Select password encryption algorithm information */
                select @vers1 = substring(@password,2,1)
                select @vers2 = substring(@password,32,1)

		/* Values 1 to 5 and 7 are valid for @vers1 field */
                if @vers1 <= 5 and @vers1 >= 1
                begin
                        if @vers2 = NULL
                                select @encralgo = "SYB-PROP"
                        else if @vers2 = 6
                                select @encralgo = "SYB-PROP,SHA-256"
                end
                else if @vers1 = 7 and @vers2 is not  NULL
                begin
                        select @encralgo = "SHA-256"
                end
                else
                begin
                        /*
                        ** 19645, "Password column corrupted"
                        */
                        exec sp_getmessage 19645, @msg output
                        select @encralgo = @msg
                end
	end
        if @row_count = 1
	begin
 	       /* Output the messages */
				
                /* 17943, "Suid: %1!" */
                exec sp_getmessage 17943, @msg output
                select @local_msgbuf = convert (varchar, @suid)
                print @msg, @local_msgbuf

                /* 17944, "Loginame: %1!" */
                exec sp_getmessage 17944, @msg output
                print  @msg, @name

                begin
                        /* 17945, "Fullname: %1!" */
	                exec sp_getmessage 17945, @msg output
	                print  @msg, @fullname
		end
                /* 18334, "Default Database: %1!" */
                exec sp_getmessage 18334, @msg output
                print  @msg, @defdb

                /* 18335, "Default Language: %1!" */
                exec sp_getmessage 18335, @msg output
                print  @msg, @deflang

                /* 18914, "Auto Login Script: %1!" */
                exec sp_getmessage 18914, @msg output
                print  @msg, @procname

                /*
                ** 17951, "Configured Roles:"
                */
	        exec sp_getmessage 17951, @msg output
	        print @msg
                select @thisauth = min(srid)
                       from master.dbo.sysloginroles
                       where suid = @suid
                while (@thisauth is not NULL)
		begin
                        select @authname = name
                              from master.dbo.syssrvroles
                              where srid = @thisauth
                        if @authname is not NULL
			begin
                                select @msg = "        " + @authname
                                select @role_status = status from master.dbo.sysloginroles
                                        where suid = @suid and srid = @thisauth
                                if ((@role_status & @enable_login_role) != 0)
	                                select @msg = @msg + " (default ON)"
		                else
		                        select @msg = @msg + " (default OFF)"
		                print  @msg
			end
                        select @thisauth = min(srid)
                                from master.dbo.sysloginroles
	                        where suid = @suid and srid > @thisauth						
		end
		
                /*
                ** 17949, "Locked: %1!"
                */
	        exec sp_getmessage 17949, @msg output
	        print @msg, @locked

                if @locked = 'YES'
                begin
                        select @msg = "        " + "Date when locked: %1!"
                        print @msg, @lockdate

                        select @msg = "        " + "Reason: %1!"
                        if @lockreason = 0
                        begin
                                /*
                                ** 19682, "Account locked by ASE by manually
                                ** executing sp_locklogin"
                                */
                                exec sp_getmessage 19682, @lockreasonmsg output
                        end
                        else if @lockreason = 1
                        begin
                                /*
                                ** 19683, "Account locked by ASE since
                                ** account was inactive"
                                */
                                exec sp_getmessage 19683, @lockreasonmsg output
                        end
                        else if @lockreason = 2
                        begin
                                /*
                                ** 19684, "Account locked by ASE due to failed
                                ** login attempts reaching max failed logins."
                                */
                                exec sp_getmessage 19684, @lockreasonmsg output
                        end
                        else if @lockreason = 3
                        begin
                                /*
                                ** 19685, "Account locked by ASE since login
                                ** has not transitioned to SHA-256, after
                                ** password downgrade."
                                */
                                exec sp_getmessage 19685, @lockreasonmsg output
                        end
                        print @msg, @lockreasonmsg

                        select @msg = "        " + "Locking suid: %1!"
			select @locksuidname = suser_name(@locksuid)
                        print @msg, @locksuidname
                end
	
		begin
                        /*
                        ** 17950, "Date of Last Password Change: %1!"
                        */
                        exec sp_getmessage 17950, @msg output
	                select @local_msgbuf =  convert(char(20), @pwdate)
			print @msg, @local_msgbuf

                        /*
                        ** 18675, "Password expiration interval: %1!"
	                */
	                exec sp_getmessage 18675, @msg output
	                select @local_msgbuf = convert (char(10), @passwdexp)
	                print @msg, @local_msgbuf

                        /*
                        ** 18676, "Password Expired: %1!"
                        */
	                exec sp_getmessage 18676, @msg output
	                select @local_msgbuf = upper(@pwdexpired)
	                print @msg, @local_msgbuf								

                        /*
                        ** 18677, "Minimum Password Length: %1!"
                        */
	                exec sp_getmessage 18677, @msg output
	                select @local_msgbuf = convert (char(10), @minpwdlen)
	                print @msg, @local_msgbuf

                        /*
                        ** 18678, "Maximum failed logins: %1!"
                        */
                        exec sp_getmessage 18678, @msg output
                        select @local_msgbuf = convert (char(10), @maxfailedlogins)
                        print @msg, @local_msgbuf

                        /*
                        ** 18679, "Current failed login attempts: %1!"
                        */
                        exec sp_getmessage 18679, @msg output
                        select @local_msgbuf = convert (char(10), @currentfails)
                        print @msg, @local_msgbuf

                        /*
                        ** 19258, "Authenticate with: %1!"
	                */
	                exec sp_getmessage 19258, @msg output
		        print @msg, @authmech                                 
		end

                /*
                ** 19644, "Login Password Encryption: %1!"
                */
                exec sp_getmessage 19644, @msg output
                print @msg, @encralgo

                /*
                ** 19681, "Last login date: %1!"
                */
                exec sp_getmessage 19681, @msg output
                print @msg, @lastlogindate
	end
	else
	begin
		/*
		** Storing the configured roles with delimiter between the values
		*/
                select @configroles = NULL
                select @thisauth = min(srid)
                        from master.dbo.sysloginroles
                        where suid = @suid
                while (@thisauth is not NULL)
                begin
                        select @authname = name
                                from master.dbo.syssrvroles
                                where srid = @thisauth
                        if @authname is not NULL
                        begin
                                select @msg = @authname
                                select @role_status = status from master.dbo.sysloginroles
                                        where suid = @suid and srid = @thisauth
                                if ((@role_status & @enable_login_role) != 0)
	                                select @msg = @msg + "(default ON)"
	                        else
		                        select @msg = @msg + "(default OFF)"
		                select @configroles = @configroles + @msg
			end
			select @thisauth = min(srid)
                                from master.dbo.sysloginroles
                                where suid = @suid and srid > @thisauth
			if @thisauth is not NULL
				select @configroles = @configroles + "; "
		end
		insert into #helpdisplay values
		(
			@suid, @name, @fullname, @defdb, @deflang, @procname,
			@locked, @pwdate, @passwdexp, @pwdexpired, @minpwdlen,
			@maxfailedlogins, @currentfails, @authmech,
			@configroles, @encralgo
		)
	end
						
	fetch display_login into
	@suid, @password, @name, @fullname, @defdb, @deflang, @procid,
	@status, @pwdate, @currentfails, @lastlogindate, @locksuid,
	@lockreason, @lockdate
end

close display_login
deallocate cursor display_login

if @row_count <> 1
begin
        exec sp_autoformat @fulltabname = #helpdisplay,
        @selectlist = "'Suid' = suid, 'Loginname' = name, 'Fullname' = fullname,
        'Default Database' = dbname, 'Default Language' = language,
        'Auto Login Script' = procname, 'Locked' = locked,
        'Date of Last Password Change' = pwdate,
        'Password expiration interval' = passwdexp,
        'Password expired' = pwdexpired,
        'Minimum password length' = minpwdlen,
        'Maximum failed logins' = maxfailedlogins,
        'Current failed login attempts' = currentfails,
        'Authenticate with' = authmech,
        'Configured Authorization' = configroles,
	'Login Password Encryption' = encralgo",
	@orderby = "order by name"
end						
return (0)
go
exec sp_procxmode 'sp_displaylogin', 'anymode'
go
grant execute on sp_displaylogin to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_is_dbo')
begin
	drop procedure sp_is_dbo
end
go
print "Installing sp_is_dbo"
go


/*
** Description
** 	Finds if the user executing the procedure is the
**	database owner.
**
** Parameters
**	@currdbname	- database name
**
** Returns
** 	1 	- User is DBO or alias to DBO
**	0	- Otherwise
**
** Notes
**	It must be called as @currdbname.sp_is_dbo @currdbname
*/
create procedure sp_is_dbo(@currdbname	varchar(256)) 
as
begin
	declare	@dbo	int

	-- Initialize as non-DBO to handle all exit conditions.

	select @dbo = 0

	-- Check for caller's error. We should always call this sproc
	-- using @currdbname.dbo.<sprocname> so that we are looking up the
	-- correct sysusers. In case of an error in caller's calling
	-- convention, flag that by returning that user is not DBO in db.
	
	if (@currdbname != db_name())
	begin
		select @dbo = 0
	end

	-- Is this login the dbo of the current db?
	-- If a dbo has 'setuser' to some other user, we do not recognize
	-- him/her as DBO any longer. This is a minor restriction that we
	-- only allow a real DBO to perform any command, and not under setuser.
	
	else if exists (select 1 from sysusers
			where 	uid = 1 and suid = suser_id())
				and (user_id() = 1)
	begin
		select @dbo = 1
	end
	else
	begin
		-- Is this login the 'dbo' alias of the db, but w/o sa_role?
		
		if exists (select 1 from sysalternates
			   where suid = suser_id()
			     and altsuid = (select suid from sysusers
			     		    where uid = 1) )
		begin
			select @dbo = 1
		end
	end

	return @dbo
end
go
exec sp_procxmode 'sp_is_dbo', 'anymode'
go
grant execute on sp_is_dbo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dbxt_recreate_proc')
begin
	drop procedure sp_dbxt_recreate_proc
end
go
print "Installing sp_dbxt_recreate_proc"
go


/* AutoDBExtend */
/*
** Generated by spgenmsgs.pl on Sun Aug 10 03:54:03 2003 
*/
/*
** raiserror Messages for dbxt_common [Total 1]
**
** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
*/
/*
** sp_getmessage Messages for dbxt_common [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
** This is the first file of dbxt* sprocs that gets loaded in installdbextend
** script. Stick in here the initial setup stuff that needs to happen in 
** this script.
*/
print "Installing procedures from dbxt_common ..."
go

use sybsystemprocs
go

if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go

-- ===========================================================================
-- Create the procedure to drop other sprocs first. This will also report
-- the message that the proc is being dropped and recreated.
--
if exists (select 1 from sysobjects
	   where name = "sp_dbxt_recreate_proc"
	     and type = 'P'
	     and sysstat & 7 = 4
	   )
	drop procedure sp_dbxt_recreate_proc
go

/*
{
*/
create procedure sp_dbxt_recreate_proc (@procname varchar(256)) as
begin
	if exists (select 1 from sysobjects
		    where id = object_id(@procname)
		      and type = 'P'
		      and sysstat & 7 = 4
	)
	begin
		print "Re-installing %1!", @procname
		exec ("drop procedure " + @procname)
	end
	else
	begin
		print "Installing %1!", @procname
	end
end
go
go
exec sp_procxmode 'sp_dbxt_recreate_proc', 'anymode'
go
grant execute on sp_dbxt_recreate_proc to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_split_string')
begin
	drop procedure sp_split_string
end
go
print "Installing sp_split_string"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_substring_count')
begin
	drop procedure sp_substring_count
end
go
print "Installing sp_substring_count"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_replace_string_plus')
begin
	drop procedure sp_replace_string_plus
end
go
print "Installing sp_replace_string_plus"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_versioncrack')
begin
	drop procedure sp_versioncrack
end
go
print "Installing sp_versioncrack"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:41 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/utils [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/utils [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go
/*
**	SP_SPLIT_STRING
**
**	A utility procedure to split a given string at the first occurance of a
**	given sub string into two sub strings - one to the left and one to the 
**	right of the first occurance of the given sub string. This can be done
**	in a case sensitive or case insensitive mode. By default it would be
**	case sensitive. Can be used by any procedure, although currently called
**	by sp_spaceusage* set of procedures.
**	
**	Paramter
**		@str		- The string to split.	
**		@substr		- The substring around which to split @str.
**		@casesensitive	- Whether case sensitive mode/not?
**	
**	Returns
**		- The left substring.
**		- The right substring.
**
**	NOTE:	No trimming of white space is done.
**
**		0 - if all goes well
**		1 - substring not found or NULL, string NULL
{
*/
create procedure sp_split_string
(
	  @str			varchar(512)
	, @substr		varchar(512)
	, @casesensitive	bit		= 1
	, @left			varchar(512)	output
	, @right		varchar(512)	output
)
as
begin	-- {	

	declare   @substrIndex	int
		, @origstr	varchar(512)

	-- Save the original string as left and right substrings need to be
	-- extracted from it later. This is needed in case this procedure is
	-- to be used in case-insensitive mode.
	--
	select	  @origstr = @str	

	if @casesensitive = 0
	begin
		select	  @str	  = lower(@str)
			, @substr = lower(@substr)
	end
	
	select @substrIndex = charindex(@substr, @str)

	if @substrIndex = 0 or @substrIndex is NULL
	begin
		select	  @left = NULL
			, @right = NULL
		return (1)
	end
	
	select	  @left  = substring(@origstr, 1, @substrIndex -1)
		, @right = substring(@origstr, @substrIndex 
						+ char_length(@substr),
					char_length(@origstr) 
					- (@substrIndex - 1 
					   + char_length(@substr)))
	return (0)	
	
end	-- }	-- }
go

/*
**	SP_SUBSTRING_COUNT
**
**	A utility procedure to count the number of times a given substring
**	occurs in a given string. This can be done in a case sensitive, or 
**	case insensitive mode. By default it would be case sensitive. Can be
**	used by any procedure, although currently called by sp_spaceusage* set
**	of procedures.
**	
**	Paramter
**		@str		- The original string.	
**		@substr		- The substring whose occurance within @str is
**				  to be counted.
**		@casesensitive	- Whether case sensitive mode/not?
**	
**	Returns
**		- The number of times the substring occurs in string.
**
**		0 - if all goes well
**		1 - substring not found
{
*/
create procedure sp_substring_count
(
	  @str			varchar(512)
	, @substr		varchar(512)
	, @casesensitive	bit		= 1
	, @count		int 		output
)
as
begin	-- {	

	declare	  @substrIndex	int
		, @left		varchar(512)
		, @right	varchar(512)
		, @rest		varchar(512)
		, @retVal	int

	if @casesensitive = 0
	begin
		select	  @str	  = lower(@str)
			, @substr = lower(@substr)
	end
	
	select 	  @substrIndex = charindex(@substr, @str)
		, @count = 0
		, @rest = @str

	if @substrIndex = 0 or @substrIndex is NULL
	begin
		return (1)
	end

	while (1 = 1) 
	begin
		exec @retVal = sp_split_string @rest, @substr, 1, @left out
								, @right out
		
		if @right is NULL and @retVal = 1
			break
			
		select    @rest  = @right
			, @count = @count + 1

	end
	return (0)	
	
end	-- }	-- }
go

/*
**	SP_REPLACE_STRING_PLUS
**
**	A utility procedure to compact a given string by replacing all
**	contiguous occurances of a subtring with a sinlge occurance of the given
**	replacement string. Can be used by any procedure, but currently called 
**	by sp_spaceusage* set of procedures.
**	
**	Paramter
**		@str		- The original string.	
**		@substr		- The substring to be replaced.	
**		@rplcsubstr	- The replacement substring.
**		@casesensitive	- Whether case sensitive mode/not?
**	
**	Returns
**		- The resultant subtring replaced string.
**
**		0 - if all goes well
**		1 - if @str is NULL, @substr is NULL
{
*/
create procedure sp_replace_string_plus
(
	  @str		varchar(512)
	, @substr	varchar(512)
	, @rplcsubstr	varchar(512)
	, @casesensitive	bit		= 1
	, @replacedstr	varchar(512) output
)
as
begin	-- {	

	declare	  @l 		varchar(512)
		, @r 		varchar(512)
		, @rest		varchar(512)
		, @n		int
		, @i		int
		, @retval	int
		, @maxsize	int
		, @newsize	int

	select	@maxsize = 512
	
	exec @retval = sp_substring_count @str, @substr, @casesensitive, @n out

	select @newsize = datalength(@str) 
			+ (datalength(@rplcsubstr) - datalength(@substr)) * @n
	
	if @retval = 1 or @n = 0 or @newsize > @maxsize
	begin
		select @replacedstr = @str
		return (1)
	end
	else
	begin
		select	  @rest = @str
			, @replacedstr = NULL
			, @l = NULL
			, @r = NULL
			, @i = @n

		while @i > 0
		begin
			exec sp_split_string @rest, @substr, @casesensitive
							   , @l out, @r out
			if @l is not NULL or @i = @n
			begin
				select @replacedstr = 
						@replacedstr + @l + @rplcsubstr
			end

			select    @rest = @r
				, @i 	= @i - 1

		end

		select @replacedstr = @replacedstr + @rest		
		return (0)		
	end

end	-- }	-- }	
go 

/*
**	SP_VERSIONCRACK
**
**	A utility procedure to parse a version string and extract desired
**	information from it and return it to the caller.
**
**	Parameter
**		@str 	    - the version string to be parsed.
**		@keywordstr - the keyword defining what information is to be
**			      extracted.
**
**	Returns
**		- the desired value/information string.
**		- the desired value int.
**
**		0 - if all goes well.
**		1 - if any error while parsing. 
**
{
*/
create procedure sp_versioncrack
(
	  @str		varchar(255)
	, @keywordstr	varchar(30)
	, @outstr	varchar(30)	OUT
	, @outint	int		OUT
)
as
begin	-- {

	declare	  @esdpattern 		varchar(10)
		, @ebfpattern		varchar(10)
		, @pattern		varchar(30)
		, @esdkeyword		varchar(4)
		, @ebfkeyword		varchar(4)
		, @leftstr		varchar(255)
		, @rightstr		varchar(255)
		, @spaceindex		int
		, @slashindex		int
		, @stopatindex		int
		, @retval		int
	
	select 	  @outstr     = NULL
		, @outint     = -1
		, @esdpattern = "ESD#"
		, @ebfpattern = "EBF "
		, @esdkeyword = "ESD"
		, @ebfkeyword = "EBF"
		, @keywordstr = upper(ltrim(rtrim(@keywordstr)))
		, @spaceindex = 0
		, @slashindex = 0
	
	/*
	** If @str is NULL or @keywordstr is NULL, sp_split_string will return
	** NULL. So, need not handle that case.
	*/

	select @pattern = case @keywordstr
				when @ebfkeyword then @ebfpattern
				when @esdkeyword then @esdpattern
				else NULL
			  end
			  
	if @pattern = NULL	-- Invalid keyword string.	
		return 1

	-- Extract the requested value form @str.
	exec @retval = sp_split_string @str, @pattern, 0, @leftstr out
						        , @rightstr out
							 
	if @retval = 1
	begin
		-- The keyword pattern not found in @str. Or @str is NULL.
		return 1
	end

	select @spaceindex  = charindex(' ', @rightstr) 
	select @slashindex  = charindex('/', @rightstr)

	select @stopatindex = case 
				when @spaceindex = 0 then @slashindex - 1
				when @slashindex = 0 then @spaceindex - 1
				when @spaceindex < @slashindex 
				then @spaceindex - 1
				else @slashindex - 1
			      end
				 
	if @stopatindex <= 0	
	begin
		-- No space, nor slash, found in @rightstr.
		-- At this moment, for ESD or EBF, this can not be so, so return
		-- with error.
		--
		return 1	
	end
		
	select @outstr = substring(@rightstr, 1, @stopatindex)	
	
	if @outstr is not NULL 
	begin

		-- Check if it is an integer value, if so, get the value. The
		-- check for '$' is added because isnumeric will return 1 for
		-- money data type also. 
		--
		if ((isnumeric(@outstr) = 1) and (charindex('$', @outstr) = 0))
		begin
			select @outint = convert(int, @outstr)
		end
	end
	
	return 0
	
end 	-- }	-- }
go
go
exec sp_procxmode 'sp_split_string', 'anymode'
go
grant execute on sp_split_string to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_substring_count', 'anymode'
go
grant execute on sp_substring_count to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_replace_string_plus', 'anymode'
go
grant execute on sp_replace_string_plus to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_versioncrack', 'anymode'
go
grant execute on sp_versioncrack to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_getopts')
begin
	drop procedure sp_getopts
end
go
print "Installing sp_getopts"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:38 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/getopts [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/getopts [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go
exec sp_dbxt_recreate_proc sp_getopts
go

/*
** sp_getopts
**
**	Utility procedure to parse a string arguments with options.
**	Each call to this procedure will extract the 1st (if any) option
**	in @options, move @options past the option just read, and return
** 	the newly found option via @option_item.
**
** Parameters:
**	@options	- Input string containing 0 or more options
**			  separated by a user-specified separator.
**	@opt_sep	- User-specified option separator character.
**	@option_item	- (Out) Option item found, if any.
**	@options_out	- (Out) @options after moving past '@option_item'.
**
** Returns:
**	1	- If a new option was found.
**	0	- Otherwise. (terminates iteration in caller.)
{
*/
create procedure sp_getopts(  @options	varchar(512)
			    , @opt_sep	char(1)	= ','
			    , @option_item	varchar(30)	output
			    , @options_out	varchar(512)	output
) as
begin
	declare @sep_index	int

	-- Signal end of options to process.
	if (@options IS NULL) or (datalength(@options) = 0)
		return 0

	-- Extract each comma-separated print option.
	if (   (charindex(@opt_sep, @options) != 0)
	       or (datalength(@options) > 0) )
	begin
		-- Locate index of option separator, if any.
		select @sep_index = charindex(@opt_sep, @options)

		-- Pull out the 1st option, if there is a separator.
		if (@sep_index > 0)
		begin
			select @option_item = substring(@options,
							1,
							(@sep_index - 1))
			select @option_item = ltrim(rtrim(@option_item))

			-- Move past this print option for next itern.
			select @options_out = 
				substring(@options, (@sep_index + 1),
					  (datalength(@options)
					     - @sep_index))
		end
		else	-- no commas; single print option
		begin
			select @option_item = ltrim(rtrim(@options))
			select @options_out = NULL
		end
	end
	return 1
end
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_getopts', 'anymode'
go
grant execute on sp_getopts to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addalias')
begin
	drop procedure sp_addalias
end
go
print "Installing sp_addalias"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/addalias */

/*
** Messages for "sp_addalias"           17230
**
** 17231, "No login with the specified name exists."
** 17232, "No user with the specified name exists in the current database."
** 17233, "'%1!' is already a user in the current database."
** 17234, "The specified user name is already aliased."
** 17235, "Alias user added."
** 17236, "Setting curwrite label to data_low for inserts into sysalternates
**	   table failed."
** 17240, "'%1!' is not a valid name."
** 17289, "Set your curwrite to the hurdle of current database."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18778, "A login with Login name '%1!' AND login id '%2!' could not be found in syslogins."
** 18795, "Unable to find a user with name '%1!' and login id '%2!' in sysusers."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addalias
@loginame varchar(255),		/* the name of the pretender */
@name_in_db varchar(255)	/* who the pretender wants to pretend to be */
as

declare @suid int		/* the suid of the pretender */
declare @asuid int		/* the suid of the person to impersonate */
declare @msg varchar(1024)
declare @name   varchar(255)
declare @dbname varchar(255)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @dummy int

select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addalias', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

set transaction isolation level 1
if @@trancount = 0
begin
	set chained off
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  If the user has SA role, it's uid will
**  be DBO uid (1).
*/
if ((user_id() != 1) and (charindex("sso_role", show_role()) = 0))
begin
	/* 
	** proc_role() will raise permission errors
	** and send audit records to the audit trail
	*/
	select @dummy = proc_role("sa_role")
	select @dummy = proc_role("sso_role")
	return (1)
end

/* Send apropriate audit records. */
if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")
if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  Make sure that the pretender has an account.
*/
select @suid = suid
	from master.dbo.syslogins
where name = @loginame

if @suid is NULL
begin
	/* 17231, "No login with the specified name exists." */

	raiserror 17231
	return (1)
end

/*
**  Get the suid of the person we want to pretend to be.
*/
select @asuid = suid
from sysusers
where name = @name_in_db
and ((uid >= @@minuserid and uid < @@mingroupid and uid != 0) 
or uid > @@maxgroupid)

/*
**  Does the user to be impersonated exist in the current database?
*/
if @asuid is NULL
begin
	/* 
	** 17232, "No user with the specified name exists in the
	** current database." 
	*/
	
	raiserror 17232
	return (1)
end

/*
**  Does the login to do the impersonating already a user in the current db?
*/
if exists (select *
		from sysusers
			where suid = @suid)
begin
	/* 17233, "'%1!' is already a user in the current database." */
        select @name = name
                from sysusers
                        where suid = @suid
	
		raiserror 17233, @name
        return (1)
end

/*
** Is the person already aliased to a user?
*/
if exists (select *
		from sysalternates
	where suid = @suid)
begin
	/* 17234, "The specified user name is already aliased." */

	raiserror 17234
	return (1)
end



/*
**  Add the alias.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec



	insert into sysalternates (suid, altsuid)
		values (@suid, @asuid)

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_addalias", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end



commit transaction rs_logexec

/* 17235, "Alias user added." */
exec sp_getmessage 17235, @msg out
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
        return (1)

go
exec sp_procxmode 'sp_addalias', 'anymode'
go
grant execute on sp_addalias to public
go
exec sp_procxmode 'sp_addalias', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addgroup')
begin
	drop procedure sp_addgroup
end
go
print "Installing sp_addgroup"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.2	28.1	05/14/90	sproc/src/addgroup */

/*
** Messages for "sp_addgroup"           17240
**
** 17240, "'%1!' is not a valid name."
** 17241, "A user with the specified group name already exists."
** 17242, "A group with the specified name already exists."
** 17243, "New group added."  
** 17244, "All group ids have been assigned. No more groups can be added
**	   at this time."  
** 17336, "Setting curwrite label to data_low for inserts into sysusers
**	   table failed."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17265, "A role with the specified name '%1!' already exists in this Server."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addgroup
@grpname varchar(255)			/* new group name */
as

declare @gid int			/* group id */
declare @msg varchar(1024)
declare @dummy int
declare @dbname varchar(255)
declare @maxlen int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addgroup', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

set transaction isolation level 1
if @@trancount = 0
begin
	set chained off
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  Call proc_role() with the required SA role.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("sso_role", show_role()) = 0)
	begin
		select @dummy = proc_role("sa_role")
		select @dummy = proc_role("sso_role")
		return (1)
	end
end

if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")

if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  Check to see that the @grpname is valid.
*/
if (@grpname is not null)
begin
	select @maxlen = length from syscolumns
	where id = object_id("sysusers") and name = "name"
	
	if valid_name(@grpname, @maxlen) = 0
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/ 
		raiserror 17240,@grpname
		return 1
	end
end

/*
**  Check to see that @grpname is not a role name.
*/
if exists (select srid from master.dbo.syssrvroles
		where name = @grpname)
begin
	/*
	** 17265, "A role with the specified name '%1!' already exists in this
	**	   Server."
	*/
	raiserror 17265, @grpname
	return (1)
end

/*
**  See if the new group name is already being used as a user or group name.
*/
select @gid = uid
	from sysusers
where name = @grpname

/*
**  public group has id = 0
*/
if @gid is not null
begin

	if (@gid != 0) and (@gid < @@mingroupid or @gid > @@maxgroupid)
	begin
		/*
		** 17241, "A user with the specified group name already exists."
		*/
		raiserror 17241
	end
	else
	begin
		/*
		** 17242, "A group with the specified name already exists."
		*/
		raiserror 17242
	end
	return (1)
end

/*
**  Now get the group id for the new group.  It is the current maximum group
**  number + 1.  If this is the first group use the lowest possible group id
**  @@mingroupid.
*/
select @gid = max(uid)+1
	from sysusers where uid=gid and gid <= @@maxgroupid

/*
** No more group ids available
*/
if @gid = @@maxgroupid + 1
begin
	/*
	** 17244, "All group ids have been assigned. No more groups can be 
	** 	added at this time."  
	*/
	raiserror 17244
	return (1)
end
	
/*
**  This is the first group.
*/
if @gid < @@mingroupid or @gid is NULL
	select @gid = @@mingroupid


		

/*
**  Create the group.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec



	insert into sysusers (uid, suid, gid, name, environ)
		values (@gid, -2, @gid, @grpname, "")

	
	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_addgroup", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

commit transaction rs_logexec

/*
** 17243, "New group added."  
*/
exec sp_getmessage 17243,  @msg out
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)

go
exec sp_procxmode 'sp_addgroup', 'anymode'
go
grant execute on sp_addgroup to public
go
exec sp_procxmode 'sp_addgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_exec_SQL')
begin
	drop procedure sp_exec_SQL
end
go
print "Installing sp_exec_SQL"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:38 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/exec_SQL [Total 1]
**
** 19206, "%1!: Execute immediate SQL failed. SQL statement is: %2!"
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/exec_SQL [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go
exec sp_dbxt_recreate_proc sp_exec_SQL
go

/*
** ***************************************************************************
** sp_exec_SQL
**
** Common sproc wrapper to execute immediate a passed-in SQL string. And if
** it fails, raise an error.
**
** Parameters:
**	@sqlstr		- SQL statement to execute.
**	@callerID	- Name of procedure calling us.
**	@nrowsaffected	- # of rows affected (output).
**
** Returns:
**	0	- If no errors occured during execution.
**	<n>	- The @@error value that was received when an error occured.
**		  Client can trap this and do further processing based on
**		  the error number.
{
*/
create procedure sp_exec_SQL (
			  @sqlstr	varchar(4096)
			, @callerID	varchar(30)
			, @nrowsaffected	int = NULL output
			, @trace		tinyint	= 0
) as
begin
	declare @retval 	int
	      , @indent		varchar(32)
	      , @sqlstr_len	int
	      , @print_maxlen	int

	if (@trace IS NOT NULL) and (@trace != 0)
	begin
		select @indent = space(2 * @@nestlevel)
		     , @sqlstr_len	= datalength(@sqlstr)
		     , @print_maxlen	= 1024

		print " "
		print "%1!---- Trace sp_exec_SQL Dry-Run: CallerId='%2!' SQL [length=%3!]:"
			, @indent, @callerID, @sqlstr_len

		print "%1!", @sqlstr

		print " "
	end
	set nocount on

	exec (@sqlstr)
	select @retval = @@error, @nrowsaffected = @@rowcount
	if (@retval != 0)
	begin
		raiserror 19206, @callerID, @sqlstr
		if (@trace != 0)
		begin
			select @sqlstr_len = datalength(@sqlstr)
			print "Length of SQL Stmt is: %1!", @sqlstr_len
			select @sqlstr

			/*
			-- Generate the procedural stack trace to see
			-- where we are coming from. This debugging does
			-- work, but can produce verbose output. Leave it
			-- here to be productized / used on an on-demand basis.
			--
			select @indent = "sp_monitor"
			exec @indent "procstack"
			*/

		end
	end
	set nocount off
	return @retval
end
go	/* } */

if (@@error != 0) select syb_quit()
go
go
exec sp_procxmode 'sp_exec_SQL', 'anymode'
go
grant execute on sp_exec_SQL to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_password')
begin
	drop procedure sp_password
end
go
print "Installing sp_password"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/* 	4.8	1.1	06/14/90	sproc/src/password */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:18 2006 
*/
/*
** raiserror Messages for password [Total 3]
**
** 17260, "Can't run %1! from within a transaction."
** 17720, "Error:  Unable to set the Password."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
*/
/*
** sp_getmessage Messages for password [Total 1]
**
** 17721, "Password correctly set."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_password
@caller_password varchar(255) = NULL,	/* the current password of caller */
@new_password    varchar(256) = NULL,	/* the new password of the target acct*/
					/* a length of 256 is required to test if
					** user entered a passwd > 255 chars.
					*/
@loginame        varchar(255) = NULL,	/* user to change password on */
@immediate	 int = 0		/* if not 0, change the password in
					** all running processes for loginame.
					*/
as

declare @returncode int
declare @msg  varchar(1024)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_password', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_password"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
**  Encrypt and store the input @new_password.
**  @caller_password will be checked against the password of the caller.
**  set_password() builtin will print out nice messages.
*/
select @returncode = set_password(@caller_password, @new_password, @loginame, @immediate)




if (@returncode = 0)
begin
	/*
	** 17720, "Error:  Unable to set the Password."
	*/
	raiserror 17720
	return (1)
end
else
begin
	/*
	** Before we log our system procedure execution instance,
	** re-initialize the '@caller_password' parameter to NULL and the
	** '@new_password' parameter to the encrypted form of the password.
	** This prevents the passwords from being stored in clear text in
	** the transaction log as well as in the Replication Server stable
	** queues.
	**
	** When the ASE RepAgent Thread sends the system procedure
	** execution instance to the Replication Server, the ASE RepAgent
	** will re-name the system procedure from 'sp_password()' to
	** 'sp_password_rep()'.  This will cause the Replication Server to
	** execute, at the target ASE, the system procedure
	** 'sp_password_rep()' which knows how to properly process the
	** encrypted password.
	*/
	select @caller_password = NULL

	if (@loginame is not NULL)
	begin
		select @new_password = password
		from master.dbo.syslogins
		where name = @loginame
	end
	else
	begin
		select @new_password = password
		from master.dbo.syslogins
		where suid = suser_id()
	end

	/*
	** If the 'master' database is marked for replication, the T-SQL
	** built-in 'logexec()' will log for replication the execution
	** instance of this system procedure.  Otherwise, the T-SQL
	** built-in 'logexec()' is a no-op.
	*/
	if (logexec(1) != 1)
	begin
		raiserror 17756, "sp_password", "master"
		return (1)
	end

	/*
	** 17721, "Password correctly set."
	*/
	exec sp_getmessage 17721, @msg output
	print @msg
	return (0)
end

go
exec sp_procxmode 'sp_password', 'anymode'
go
grant execute on sp_password to public
go
exec sp_procxmode 'sp_password', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_gen_login_id')
begin
	drop procedure sp_gen_login_id
end
go
print "Installing sp_gen_login_id"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/gen_login_id */

/*
** The suid generation logic should match the suid generation logic used by
** the "create login" command. This is because rep agent uses the 
** "create login" command to create a login on a replicated master. The suids
** generated should be consistent.
** Modify the suid generation logic in "create login" whenever the suid
** logic in this procedure is changed.
*/
create procedure sp_gen_login_id
@loginame varchar(30),			/* login name of the new user */
@insertsuid int output			/* suid corresponding to
					** insert slot in Syslogins
					*/
as

declare @msg varchar(250),
	@suid   int,                    /* temp variable */
	@retstat  int

/* suid 2 is reserved for 'probe' */
if (@loginame = "probe")
	select @insertsuid = @@probesuid
else
begin

	/* Generate an appropriate suid */
	select @suid = max(suid)
		from master.dbo.syslogins(index syslogins) where suid > @@probesuid

	if @suid is NULL
	begin
		select @insertsuid = @@probesuid + 1
	end
	else if @suid != @@maxsuid
		select @insertsuid = @suid + 1

	else
	begin
		select @suid = min(suid)
			from master.dbo.syslogins(index syslogins) where suid < -2

		if @suid is NULL
		begin
			select @insertsuid = -3
		end
		else if @suid != @@minsuid
			select @insertsuid = @suid - 1

		/* check for holes if we already used up all suids */
		else
		begin
			/* Start looking for holes between @@minsuid and
 			** @@maxsuid. */
                        select @insertsuid = @@minsuid
                        while exists (select * from master.dbo.syslogins
							(index syslogins)
                                        where suid = @insertsuid)
                        begin
                                select @insertsuid = @insertsuid + 1

                                if (@insertsuid = @@invalidsuid)
                                begin
                                        /*
                                        ** Uids -2, -1, 0 and 2 are all invalid
                                        */
                                        select @insertsuid = @insertsuid + 5
                                end

                                if @insertsuid = @@maxsuid
                                begin
                                        /*
                                        ** 17266, "All logins have been
                                        ** assigned. No more logins can be
                                        ** added at this time."
                                        */
                                        raiserror 17266
                                        return (1)
                                end
                        end
	
		end
	end
end

return (0)
go
exec sp_procxmode 'sp_gen_login_id', 'anymode'
go
grant execute on sp_gen_login_id to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addlogin')
begin
	drop procedure sp_addlogin
end
go
print "Installing sp_addlogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/addlogin */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:14 2006 
*/
/*
** raiserror Messages for addlogin [Total 12]
**
** 17201, "'%1!' is not an official language name from syslanguages."
** 17240, "'%1!' is not a valid name."
** 17260, "Can't run %1! from within a transaction."
** 17262, "A user with the specified login name already exists."
** 17263, "Database name not valid -- login not added."
** 17265, "A role with the specified name '%1!' already exists in this Server."
** 17267, "Invalid value specified for %1! option. Login not created."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 18409, "The built-in function %1! failed. Please see the other messages printed along with this message."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."
** 18881, "Unable to generate %1! for HA use. Please Refer to documentation for details."
** 19257, "The authentication mechanism '%1!' is not valid."
** 19822, "A local temporary database is not permitted as the default database for a login."
*/
/*
** sp_getmessage Messages for addlogin [Total 3]
**
** 17262, "A user with the specified login name already exists."
** 17264, "New login created."
** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
** 19446, "A login mapping for the name '%1!' already exists in this Server.
**		Drop an existing mapping before creating a new mapping."
** 19448, "An existing login mapping for user '%1!' allows only '%2!' authentication mechanism to be used."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addlogin
@loginame varchar(255),			/* login name of the new user */
@passwd varchar(256) = NULL,		/* password of the new user */
@defdb varchar(255) = "master",		/* default db for the new user */
@deflanguage varchar(255) = NULL,	/* default language for the new user */
@fullname varchar(255) = NULL,		/* account owner's full name */
@passwdexp int = NULL,			/* value of password expiration */
@minpwdlen int = NULL,			/* value of minimum password 
					** length 
					*/
@maxfailedlogins int = NULL,		/* value of maximum failed 
					** logins
					*/
@auth_mech varchar(30) = "ANY"		/* Authentication mechanism */
as

declare @msg varchar(1024)
declare @dummy int,
	@passeclass int,		/* Class id in Sysattributes */
	@attrib int,			/* attribute id in 
					** Sysatttributes
					*/
	@action int,			/* Insert, update or delete 
					** Sysattributes entry
					*/
	@retstat int,
	@insertsuid int,		/* suid corresponding to 
					** insert slot in Syslogins
					*/
	@HA_CERTIFIED tinyint,		/* Is the SP HA certified ? */
	@authid int,			/* auth mechanism id */
	@config int,			/* Config option for external
					** authentication mechanisms.
					*/
	@status	int,			/* Syslogins status */
	@curname varchar(30),		/* To retrieve name from syslogins */
	@login_class int,		/* To retrieve mapping from
					** sysattributes. 
					*/
	@login_attrib int,		/* To retrieve mapping */
	@map_authid int,		/* sp_maplogin auth mechanism id */
	@map_authnm  varchar(30),	/* sp_maplogin auth mechanism name */

	@maxlen int,
	@log_for_rep int,
	@db_rep_level_all int,
	@db_rep_level_none int,
	@db_rep_level_l1 int,
	@lt_rep_get_failed int

declare sync_cursor cursor for select name from master.dbo.syslogins holdlock for update

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2

select @HA_CERTIFIED = 0	



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addlogin', @HA_CERTIFIED
if (@retstat != 0)
	return (1)


/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_addlogin"
	return (1)
end
else
begin
	set chained off
end
set transaction isolation level 1

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_addlogin"
	return (1)
end

/* check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sso_role") = 0)
	return (1)

declare @returncode	int

/*
**  Check to see that the @loginame is valid.
*/
if (@loginame is not null)
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.syslogins") and name = "name"

	if valid_name(@loginame, @maxlen) = 0
	begin
		/*
		** 17240, "'%1!' is not a valid name." 
		*/
		raiserror 17240, @loginame
		return 1
	end
end

/*
** Check to see that the @fullname is valid.
*/
if (@fullname is not NULL) 
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.syslogins") and name = "fullname"

	if char_length(@fullname) > @maxlen
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @fullname
		return 1
	end
end

if @deflanguage is not null
begin
	select @returncode = 0
	execute @returncode = sp_validlang @deflanguage
	if @returncode != 0
	begin
		/* Us_english is always valid */
		if @deflanguage != "us_english"
		begin
			/*
			** 17201, "'%1!' is not an official language name from Syslanguages." 
			*/
			raiserror 17201, @deflanguage
			return @returncode
		end
	end
end

open sync_cursor
/*
** To serialize concurrent sp_addlogin requests
*/
fetch sync_cursor into @curname

/*
**  Make sure the login doesn't already exist.
*/
if exists (select *
	from master.dbo.syslogins (index ncsyslogins)
	where name = @loginame)
begin
	/*
	** 17262, "A user with the specified login name already exists."
	*/
	raiserror 17262
	return (1)
end

/*
** Make sure role doesn't already exist with this name.
*/
if exists (select * 
	from master.dbo.syssrvroles
	where name = @loginame)
begin
	/*
	** 17265, "A role with the specified name '%1!' already exists in this
	**	   Server."
	*/
	raiserror 17265, @loginame
	return (1)
end

/*
** Make sure a login mapping doesn't already exist for this name.
** Prevent a login from being added if there already exists a 
** mapping that may obscure the login. This helps to avoid
** another way to alias a user within ASE.
*/
select @login_class = 20, @login_attrib = 0

if exists (select 1 from master.dbo.sysattributes where
			class = @login_class and attribute = @login_attrib and 
			object_cinfo = @loginame)
begin	
	/*
	** 19446, "A login mapping for the name '%1!' already exists in this
	**	   Server.  Drop an existing mapping before creating a new 
	**	   mapping."
	*/
	raiserror 19446, @loginame
	return (1)
end

/*
**  Check that the database name is valid.
**  If it was specified as NULL then default it to "master".  Note that this
**  can happen for 'sp_addlogin peter, password, null, null, "peter rabbit"'
**  but not for 'sp_addlogin peter, password, @fullname = "peter rabbit"'.
*/
if @defdb is NULL
begin
	select @defdb = "master"
end

if not exists (select *
	from master.dbo.sysdatabases
	where name = @defdb)
begin
	/*
	** 17263, "Database name not valid -- login not added."
	*/
	raiserror 17263
	return (1)
end

/*
**  Check that the database name is useable on all instances of cluster.
**  If specified default database is a local temporary database then
**  fail the command to avoid problems at connection time.
*/
if db_instanceid(db_id(@defdb)) is not null
begin
	/*
	** 19822, "A local temporary database is not permitted as the 
	** default database for a login."
	*/
	raiserror 19822
	return (1)
end

/* Assign the class number for the 
** PASSWORD_SECURITY class in
** master.dbo.sysattributes
*/
select @passeclass = class from master.dbo.sysattributes 
where object_type = "PS"



exec @retstat = sp_gen_login_id @loginame, @insertsuid output
if (@retstat != 0)
	goto clean_all


  
/*
** delete entries for local mapped logins 
** from sysattributes for this login.  
** This will cleanup the rows having stale object suid 
** equal to this newly generated suid (insertsuid) 
*/
delete from master.dbo.sysattributes
	where object = @insertsuid
	and object_type = "LM"



/* If any of the password options have been
** specified, check for validity & insert
** appropriate entry in Sysattributes
*/
if @passwdexp is not NULL
begin
	select  @attrib = 0,
		@action = 1
	if attrib_valid(@passeclass, @attrib, "PS", @insertsuid, 
		NULL, NULL, NULL, "login", @passwdexp, NULL, NULL, NULL,
		NULL, @action) = 0
	begin
		/*
		** 17267, "Invalid 'password expiration' attribute specified.
		** Login not created."
		*/
		raiserror 17267, "password expiration"
		goto clean_all
	end
	else
	begin
		insert into master.dbo.sysattributes(class, attribute,
			object_type, object_cinfo, object, int_value)
		values
		(@passeclass, @attrib, "PS", "login", @insertsuid, @passwdexp)


	
	end
end

if @minpwdlen is not NULL
begin
        select  @attrib = 1,
		@action = 1
        if attrib_valid(@passeclass, @attrib, "PS", @insertsuid, 
                NULL, NULL, NULL, "login", @minpwdlen, NULL, NULL, NULL,
                NULL, @action) = 0
        begin
		/* 
		** 17267, "Incorrect 'minimum password length' attribute
		** specified. Login not created."
		*/
		raiserror 17267, "minimum password length"
                goto clean_all
        end
        else
	begin
                insert into master.dbo.sysattributes(class, attribute,
                        object_type, object_cinfo, object, int_value)
                values
                (@passeclass, @attrib, "PS", "login", @insertsuid, 
			@minpwdlen)



	end
end


if @maxfailedlogins is not NULL
begin
        select  @attrib = 2,
		@action = 1
        if attrib_valid(@passeclass, @attrib, "PS", @insertsuid, 
                NULL, NULL, NULL, "login", @maxfailedlogins, NULL, NULL, 
                NULL, NULL, @action) = 0
        begin
		/* 
		** 17267, "Incorrect 'maximum failed logins' specified.
		** Login not created."
		*/
		raiserror 17267, "maximum failed logins"
		goto clean_all
        end
        else
	begin
	        insert into master.dbo.sysattributes(class, attribute,
                        object_type, object_cinfo, object, int_value)
                values
                (@passeclass, @attrib, "PS", "login", @insertsuid, 
			@maxfailedlogins)



	end
end

/*
** Check whether authentication mechanism specified is valid or not.
** 'AUTH_DEFAULT' and 'AUTH_MASK' are new values added in spt_values
** used to obtain value of default ('ANY') authmech or authentication
** mask respectively. They are not valid names that the user can specify
** as authentication mechanism.
*/
select  @authid = low, @config = number
from master.dbo.spt_values
where type = 'ua' and name = upper(@auth_mech) and
upper(@auth_mech) not in ('AUTH_DEFAULT', 'AUTH_MASK')

if @@rowcount = 0
begin
	/*
	** 19257, "The authentication mechanism '%1!' is not valid."
	*/
	raiserror 19257, @auth_mech
	goto clean_all
end

/*
** If authmech is 'ANY', then obtain the value of default authmech
** 'ASE_DEFAULT' defined in spt_values.
*/
if (upper(@auth_mech) = "ANY")
begin
	select @authid = low from master.dbo.spt_values
		where type = 'ua' and name = "AUTH_DEFAULT"
end

/*
** Check if the authentication method is enabled.
*/
if (@config != 0) and not exists(select 1
	from master.dbo.syscurconfigs a
	where a.config = @config and a.value != 0)
begin
	/*
	** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
	*/
	exec sp_getmessage 19259, @msg output
	print @msg, @auth_mech
end

/* Set status to LOGIN_LOCKED | Authentication mask */
select @status = 2 | @authid 

/*
**  Create the login.  Lock the account temporarily and
**  Put in a dont-care NULL as password.
*/
insert into master.dbo.syslogins (suid, status, accdate, totcpu, totio,
        spacelimit, timelimit, resultlimit,
        dbname, name, password, language,
        pwdate, audflags, fullname)
values ( @insertsuid, @status, getdate(), 0, 0, 0, 0, 0,
        @defdb, @loginame , NULL, @deflanguage,
        getdate(), 0, @fullname )





/*
**  Encrypt and store the input password
*/
execute @returncode = sp_password NULL, @passwd, @loginame



if (@returncode = 0)
begin
	/*
	** Before we log our system procedure execution instance,
	** re-initialize the '@password' parameter to the encrypted form of
	** the password.  This prevents the password from being stored in
	** clear text in the transaction log as well as in the Replication
	** Server stable queues.
	**
	** When the ASE RepAgent Thread sends the system procedure
	** execution instance to the Replication Server, the ASE RepAgent
	** will re-name the system procedure from 'sp_addlogin()' to
	** 'sp_addlogin_rep()'.  This will cause the Replication Server to
	** execute, at the target ASE, the system procedure
	** 'sp_addlogin_rep()' which knows how to properly process the
	** encrypted password.
	*/
	select @passwd = password
	from master.dbo.syslogins
	where suid = @insertsuid

	/*
	** If the 'master' database is marked for replication, the T-SQL
	** built-in 'logexec()' will log for replication the execution
	** instance of this system procedure.  Otherwise, the T-SQL
	** built-in 'logexec()' is a no-op.
	*/
	if (logexec(1) != 1)
	begin
		raiserror 17756, "sp_addlogin", "master"
		select @returncode = 1
	end
end

if @returncode = 0
begin
	/* UN-lock the account after successful update */
	/* except in case of user sybmail a MAPI requirement. */
	if (@loginame != "sybmail")
	begin
		execute @returncode = sp_locklogin @loginame, "unlock"

	end
end
else
begin
	/*
	** Delete relevant syslogins and sysattribute login information
	** for this login, in order to backout.
	*/
	delete from master.dbo.syslogins where name = @loginame
	delete from master.dbo.sysattributes 
		where class = @passeclass AND object = @insertsuid
		AND object_cinfo = "login"



end

if @returncode = 0
                begin
                        /*
                        ** 17264, "New login created."
                        */
                        exec sp_getmessage 17264, @msg output
                        print @msg
                end

close sync_cursor
deallocate cursor sync_cursor
return (@returncode)

clean_all:

	return (1)
go
exec sp_procxmode 'sp_addlogin', 'anymode'
go
grant execute on sp_addlogin to public
go
exec sp_procxmode 'sp_addlogin', 'rep_master'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addtype')
begin
	drop procedure sp_addtype
end
go
print "Installing sp_addtype"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Messages for "sp_addtype"            17300
**
** 17300, "Usage: sp_addtype name, 'datatype' [,null | nonull | identity]"
** 17301, "'%1!' is not a valid type name."
** 17302, "A type with the specified name already exists."
** 17303, "Physical datatype does not exist."
** 17304, "User-defined datatypes based on the 'timestamp' datatype are not allowed."
** 17305, "Physical datatype does not allow nulls."
** 17306, "Physical type is fixed length. You cannot specify the length."
** 17307, "You must specify a length with this physical type.
** 17308, "Illegal length specified -- must be between 1 and %1!."
** 17309, "Type added."
** 17751, "Illegal precision specified -- must be between 1 and 38."
** 17752, "Illegal scale specified -- must be less than precision and positive."
** 17754, "Illegal precision specified -- must be between 1 and 48."

** 17756, "The execution of the stored procedure '%1!' in database
** 	   '%2!' was aborted because there was an error in writing the
** 	   replication log record."
** 18302, "User '%1!' is not a valid user in the '%2!' database."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18786, "A type with name '%1!' or id '%2!' already exists."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addtype
@typename varchar(255),		/* name of user-defined type */
@phystype varchar(80),		/* physical system type of user-defined type */
@nulltype varchar(8) = "1"	/* default is database 'allow null' default */
as

declare @len int		/* length of user type */
declare @type tinyint		/* typeid of physical type */
declare @tlen int		/* length of physical type */
declare @typeid smallint	/* user typeid of physical type */
declare @var bit		/* is physical type variable length? */
declare @nonull bit		/* default is to allow NO NULLs */
declare @nullegal bit		/* does physical type allow NULLs? */
declare @msg varchar(1024)
declare @prec int		/* precision of the datatype */
declare @scale int		/* scale of the datatype */
declare @tprec tinyint		/* precision of the datatype read from systypes */
declare @tscale tinyint		/* scale of the datatype read from systypes */
declare @u_identity tinyint	/* does user type have identity property? */
declare @hierarchy tinyint	/* hierarchy level of the datatype */
declare @index int		/* index of blank char in the string of datatype*/
declare @rest varchar(80)	/* string that holds the temporay portion of the datatype.*/
declare @nulldefault int	/* 'allow null' database default */
declare @nationalchar int	/* national character type is specified */
declare @logexec int		/* For the logexec call */
declare @saved_phystype varchar(80) /* Saved @phystype parameter. This will be
				    ** restored before logging for replication.
				    ** This is necessary because @phystype is
				    ** modified.
				    */
declare @dbname varchar(255)
declare @uid    int
declare @insert_typeid smallint
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @MAXSYSTYPEID int	/* maximum user type id for a system type */
declare @retstat int
declare @maxlen		int


if @@trancount = 0
begin
	set chained off
end

select @HA_CERTIFIED = 0
select @MAXSYSTYPEID = 100      /* maximum user type id for a system type */




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addtype', @HA_CERTIFIED
if (@retstat != 0)
        return (1)


set transaction isolation level 1
/*
**  Does the user type allow NULLs?  Now, the default is to 
**  use the 'allow null' option setting for the current database.
**  This is the same default the create table statement uses.
*/
if @nulltype = "1"
begin
	/*
	** Get database 'allow null default. @nulldefault = 0
	** means 'not null allowed' is database default.
	**
	** 17069, "allow nulls by default"
	**
	** Make sure not to get the internationalized message
	** by "us_english" parameter, even if client is using
	** an alternative language. This is because spt_values
	** has an us_english message only, even if an alternative
	** language is installed.
	*/

	exec sp_getmessage 17069, @msg output, "us_english"

	select @nulldefault = (a.number & b.status)
	from master.dbo.spt_values a, master.dbo.sysdatabases b
	where a.name = @msg and b.name = db_name()
	if (@nulldefault = 0)
		select @nonull = 1
	else
		select @nonull = 0
	select @u_identity = 0
end
else if lower(@nulltype) = "null" or @nulltype is null
begin
	select @nonull = 0
	select @u_identity = 0
end
else if lower(@nulltype) = "identity"
begin
	select @nonull = 1
	select @u_identity = 1
end
else if lower(@nulltype) in ("not null" , "nonull")
begin
	select @nonull = 1
	select @u_identity = 0
end
else
begin
	/*
	** 17300, "Usage: sp_addtype name, 'datatype' [,null | nonull | identity]"
	*/
	raiserror 17300
	return (1)
end

/*
**  Check to see that the @typename is valid.
*/
select @maxlen = length from syscolumns
	where id = object_id("systypes")
		and name = "name"

if valid_name(@typename,@maxlen) = 0
begin
	/*
	** 17301, "'%1!' is not a valid type name."
	*/
	raiserror 17301, @typename
	return (1)
end

/*
** Check to see if the type already exists. In addition to the 
** types in systypes we need to also check for their capitalized 
** version (for system types) and alternative names for system types
** such as integer for int.
*/
if exists (select *
		from systypes
		where name = @typename or
           	(name = lower(@typename) and usertype < @MAXSYSTYPEID) or
                (lower (@typename) in ('integer', 'character')))

begin
	/*
	** 17302, "A type with the specified name already exists."
	*/
	raiserror 17302
	return (1)
end

/* Save the original value of @phystype. We'll need it if we have
** to log this invocation for replication.
*/
select @saved_phystype = @phystype

/* Make physical typename all lower case to ensure case insensitivity. */
select @phystype = lower(@phystype)

/* initialize the length to be NULL first. */
select @len = NULL
/*
** If precision and scale were given with the type extract them
*/
if @phystype like "_%(_%,_%)"
begin
	select @prec = convert(int, substring(@phystype,
		charindex("(",@phystype) + 1,
		charindex(",",@phystype) - 1 - charindex("(",@phystype)))

	select @scale = convert(int, substring(@phystype,
		charindex(",",@phystype) + 1,
		charindex(")",@phystype) - 1 - charindex(",",@phystype)))
	/*
	** Extract the physical type name 
	*/
	select @phystype = substring(@phystype, 1,
		   charindex("(", @phystype) - 1)
end
else

/*
**  If a length was given with the user datatype, extract it.
**  This could also be the precision, at this time assume it's the length
**  we'll decide later whether it's the length or precision.
**  If the length is not specified, @len will be assigned to NULL by
**  the function convert(). Note that like "_%(%)" can match the string
**  of phystype(length) or phystype(), such as binary(8) or binary().
*/
if @phystype like "_%(%)"
begin
	select @len = convert(int, substring(@phystype,
		charindex("(",@phystype) + 1,
		charindex(")",@phystype) - 1 - charindex("(",@phystype)))

	/*
	** Extract the physical type name 
	*/
	select @phystype = substring(@phystype, 1,
		   charindex("(", @phystype) - 1)
end
else 

/*
** If the type is an unsigned int then we only allow "unsigned int"  
** not the systypes name uint.
*/
if (@phystype in ("uint", "usmallint", "ubigint", "uintn"))
begin
		/*
		** 17303, "Physical datatype does not exist."
		*/
			raiserror 17303
			return (1)
end

/*
** Now, squeezes all consective space characters in the datatype string 
** into one single space character. By doing this, sp_addtype can recognize
** datatype, such as "   national      char    varying".
*/
select @phystype = ltrim(rtrim(@phystype))
select @rest = @phystype
select @phystype = NULL
select @index = charindex(' ', @rest) 
while (@index != 0)
begin
	select @phystype = @phystype + substring(@rest, 1, @index -1) + ' '
	select @rest = ltrim(stuff(@rest, 1, @index, ''))
	select @index = charindex(' ', @rest)
end
select @phystype = rtrim(@phystype + @rest)

/* 
** Assgin value to @nationalchar before do the datatype mapping,
** this value will be used when calculate the actual storage length.
*/

if (@phystype in ("nchar", "nvarchar", "national char", "national character",
	"nchar varying", "national char varying", "national character varying"))
begin
	select @nationalchar = 1
end
else
begin
	select @nationalchar = 0
end

/*
**  Do the following datatypes mapping now.
**  "character"--> "char"; "nchar"--> "char"; 
**  "[national] char[acter] varying"--> "varchar"; "nchar varying"-->"varchar";
**  "dec" ---> "decimal";  "integer"---> "int"; "double precision" --> "float";
**  Map the default length of datatype "char" ,"varchar", "binary", "varbinary"
**  and their various synonyms to 1.
*/
if (@phystype in ("char", "character", "nchar", "national char", 
	"national character"))
begin
	select @phystype = "char"
	/*
	** If len is not specified, supply the default length to be 1.
	*/
	if (@len is NULL) select @len = 1	
end
else
if (@phystype in ("varchar", "nvarchar", "nchar varying", "char varying", 
   "character varying", "national char varying", "national character varying"))
begin
	select @phystype = "varchar"
	/*
	** If len is not specified, supply the default length to be 1.
	*/
	if (@len is NULL) select @len = 1	
end
else
if (@phystype in ("univarchar", "unichar varying", 
   "unicode character varying", "unicode char varying"))
begin
	select @phystype = "univarchar"
	/*
	** If len is not specified, supply the default length to be 1.
	*/
	if (@len is NULL) select @len = 1	
end
else
if (@phystype in ("unichar", "unicode char", "unicode character"))
begin
	select @phystype = "unichar"
	/*
	** If len is not specified, supply the default length to be 1.
	*/
	if (@len is NULL) select @len = 1	
end
else
if ((@phystype in ("binary", "varbinary")) and (@len is NULL))
	/*
	** If len is not specified, supply the default length to be 1.
	*/
	select @len = 1
else
if (@phystype = "unsigned integer") select @phystype = "uint"
else
if (@phystype = "unsigned int") select @phystype = "uint"
else
if (@phystype = "unsigned smallint") select @phystype = "usmallint"
else
if (@phystype = "unsigned bigint") select @phystype = "ubigint"
else
if (@phystype = "integer") select @phystype = "int"
else
if (@phystype = "double precision") select @phystype = "float"
else
if (@phystype = "dec") select @phystype = "decimal"
else
	/*
	** If len for float datatype is specified, then the range must
	** be between 1 to 48. If len specified is <= 15, map the type
	** to real, otherwise map the type to float.
	*/
if (@phystype = "float") and (@len is not NULL)
begin
	if (@len  < 1 or @len > 48)
	begin
		raiserror 17754
		return (1)
	end
	else
	begin
		if (@len < = 15) select @phystype = "real" 		
		select @len = NULL
	end
end

/*
**  Make sure that the physical type exists and get its characteristics.
**  DataServer physical types have a usertype < 100 and are owned by the
**  dbo (userid = 1).
**  Datatypes datetimn, decimaln, floatn, intn, moneyn, numericn, daten
**  bigdatetimen, bigtimen, and timen are not supported to users.
**  Those datatypes must be invisible to users.
*/
select @type = type, @tlen = length, @typeid = usertype,
	@var = variable, @nullegal = allownulls, @tprec = prec,
	@tscale = scale, @hierarchy = hierarchy
from systypes
	where usertype < 100 and name = @phystype and uid = 1
	  and @phystype not in ('datetimn', 'decimaln', 'floatn', 'timen',
				'intn', 'moneyn', 'numericn', 'daten',
				'bigdatetimen', 'bigtimen')

if @type is NULL
begin
	/*
	** 17303, "Physical datatype does not exist."
	*/
	raiserror 17303
	return (1)
end

/*
**  Disallow user-defined datatypes on timestamps.  This is done because
**  a timestamp is not a basic type but is really a binary.  There is,
**  therefore, no way to tell if a user-defined datatype is mapped to
**  a binary or a timestamp.  Timestamps can't have rules or defaults.
*/
if @phystype = "timestamp"
begin
	/*
	** 17304, "User-defined datatypes based on the 'timestamp' datatype are not allowed."
	*/
	raiserror 17304
	return (1)
end

/*
**  Check if the NULL status of the user type is consistent with the NULL status
**  of the physical type.  Here are the possible cases.
**
**		   physical type
**		  NULLs	  NONULLs
**	        -----------------
** user	NULLs	|  ok	|  no
** type NONULLs	|  ok	|  ok
*/
if @nonull = 0 and @nullegal = 0
begin
	/*
	** 17305, "Physical datatype does not allow nulls."
	*/
	raiserror 17305
	return (1)
end

/*
**  We'll use the variable @nullegal when we update the systypes table
**  so we need to set it to reflect if NULLs are allowed (@nonull = 0)
**  or NO NULLs are allowed (@nonull = 1).
*/
if @nonull = 0
begin
	select @nullegal = 1
end
else
begin
	select @nullegal = 0
end

/* Decide about precision, scale, length 
** First check fro NUMERIC, DECIMAL
*/
if (@typeid = 26) or (@typeid = 10) 
begin
	/* Type is NUMERIC or DECIMAL */
	
	if @len > 0
	begin
		/* Length is really the precision 
		** Since no scale is specified then scale
		** is minimum(Default, precision). Default = 4
		*/
		select @prec = @len
		select @scale = 0

	end
	else
	begin
		if (@prec is NULL)
		begin
			select @prec = 18
			select @scale = 0
		end
	end

	

	if (@prec > 38) or (@prec < 1)
	begin
		/*
		** 17751, "Illegal precision specified -- must be between 1 and 38."
		*/
		raiserror 17751
		return (1)
	end

	if (@scale > @prec) or (@scale < 0)
	begin
		/*
		** 17752, "Illegal scale specified -- must be less than precision 
		** 	   and positive."
		*/
		raiserror 17752
		return (1)
	end
	
	/* Compute length from precision */
	if (@prec <= 2)	
		select @len = 2
	
	if (@prec > 2) and (@prec <= 4)
		select @len = 3

	if (@prec > 4) and (@prec <= 7)
		select @len = 4

	if (@prec > 7) and (@prec <= 9)
		select @len = 5

	if (@prec > 9) and (@prec <= 12)
		select @len = 6

	if (@prec > 12) and (@prec <= 14)
		select @len = 7

	if (@prec > 14) and (@prec <= 16)
		select @len = 8

	if (@prec > 16) and (@prec <= 19)
		select @len = 9

	if (@prec > 19) and (@prec <= 21)
		select @len = 10

	if (@prec > 21) and (@prec <= 24)
		select @len = 11

	if (@prec > 24) and (@prec <= 26)
		select @len = 12

	if (@prec > 26) and (@prec <= 28)
		select @len = 13

	if (@prec > 28) and (@prec <= 31)
		select @len = 14

	if (@prec > 31) and (@prec <= 33)
		select @len = 15

	if (@prec > 33) and (@prec <= 36)
		select @len = 16

	if (@prec > 36) and (@prec <= 38)
		select @len = 17
end
else
begin
/*
**  Typeids 1 (char), 2 (varchar), 3 (binary), 4 (varbinary) 
**  24 (nchar), 25 (nvarchar), 34 (unichar), and 35 (univarchar)
**  only ones which allow a length to be specified.
*/
if @typeid > 4 and @typeid not in (24, 25, 34, 35) 
begin
	/*
	**  We can't use a length and we got one.
	*/
	if @len > 0
	begin
		/*
		** 17306, "Physical type is fixed length. You cannot specify the length."
		*/
		raiserror 17306
	   	return (1)
	end

	/*
	**  Use the fixed length of the physical type.
	*/
	select @len = @tlen
end
else
begin
	/*
	**  We need a length and we didn't get one.
	*/
	if @len is NULL
	begin
		/*
		** 17307, "You must specify a length with this physical type. 
		*/
		raiserror 17307
		return (1)
	end

	/*
	** If "nchar" or "nvarchar" is specified, caluculate the real length
	*/

	if @nationalchar = 1
		select @len = @len * @@ncharsize

	/*
	** If "unichar" or "univarchar", perform additinal checks
	*/
	if (@phystype in ("unichar", "univarchar"))
	begin
		select @len = @len * @@unicharsize

		if (@len <= 0 or @len > @@maxpagesize)
		begin
			/*
			** 17308, "Illegal length specified -- must be between 1 and %1!."
			*/
			select @len = @@maxpagesize / @@unicharsize
			raiserror 17308, @len
			return (1)
		end
	end
	else if @len <= 0 or @len > @@maxpagesize
	begin
		/*
		** 17308, "Illegal length specified -- must be between 1 and %1!."
		*/
		raiserror 17308, @@maxpagesize
		return (1)
	end

end
end

/* 
** Check to make sure only numeric(x,0), integer, smallint and tinyint
** types have identity property.
*/
if @u_identity = 1
begin
	if (@phystype = "numeric" and @scale != 0) or
	   (@phystype not in ("int", "smallint", "tinyint", 
		"bigint", "ubigint", "uint", "usmallint", "numeric"))
	begin
		/*
		** 17755, "User types with the identity property must be integer,
		**         smallint, tinyint or numeric with a scale of 0."
		*/
		raiserror 17755
		return(1)
	end
end


/*
**  Finally, get the maximum existing user type so we use it + 1 for this
**  new type.
*/
/*  Attention:
**	Please change the corresponding HA section when type ID generating
**	logic is changed here.
*/
select @typeid = max(usertype)
	from systypes

/*
**  There are no user defined types yet so use the first number (101).
*/
if @typeid < 100
	select @typeid = 100
else if (@typeid = 32767)
begin
	print "All usertype ids have been used up"
	return (1)
end

select @insert_typeid = @typeid + 1

select @uid = user_id()



/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction	
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec



insert systypes (uid, variable, type, length, tdefault,
	domain, name, usertype, allownulls, prec, scale, ident,
	hierarchy, accessrule)
select @uid, @var, @type, @len, 0, 0, @typename, @insert_typeid, @nullegal,
@prec, @scale, @u_identity, @hierarchy, 0



/*
** The phystype parameter was changed so restore it's original value and
** write the log record to replicate this invocation.
*/
select @phystype = @saved_phystype

if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	** 	   database '%2!' was aborted because there was an
	** 	   error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_addtype", @dbname
	
	rollback transaction rs_logexec
	return(1)
end



commit transaction rs_logexec

/*
** 17309, "Type added."
*/
exec sp_getmessage 17309, @msg output
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)

go
exec sp_procxmode 'sp_addtype', 'anymode'
go
grant execute on sp_addtype to public
go
exec sp_procxmode 'sp_addtype', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addumpdevice')
begin
	drop procedure sp_addumpdevice
end
go
print "Installing sp_addumpdevice"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/addumpdevice */

/*
** Messages for "sp_addumpdevice"       17310
**
** 17260, "Can't run %1! from within a transaction." 
** 17240, "'" + @logicalname + "' is not a valid name." 
** 17310, "Unknown device type.  Use 'disk' or 'tape'."
** 17311, "@logicalname may not be NULL."
** 17312, "@physicalname may not be NULL."
** 17314, "Device with same logical name already exists."
** 17317, "Please specify media capacity in megabytes (1 MB minimum)."
** 17318, "WARNING: specified size parameter is not used for the disk device type."
** 17319, "'Disk' device added."
** 17320, "'Tape' device added."
** 17321, "WARNING: physical device name '%1!' is not unique." 
** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
** 18388, "You must be in the master database to run %1!"
*/
create procedure sp_addumpdevice
@devtype	varchar(30),		/* disk, tape, or special */
@logicalname	varchar(255),		/* logical name of the device */
@physicalname	varchar(128),		/* physical name of the device */
@tapesize	int = NULL		/* capacity of tape in MB */

as

declare @status smallint		/* status bits for device */
declare @msg varchar(1024)
declare @tapeblocksize int
declare @cntrltype smallint
declare @maxlen int
declare @maxphylen int

/* check the lenghts of the input parameters */
select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.sysdevices") and name = "name"

if char_length(@logicalname) > @maxlen
begin
	/*
	** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters." 
	*/
	raiserror 17325, @logicalname, @maxlen
	return (1)
end
select @maxphylen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.sysdevices") and name = "phyname"

if char_length(@physicalname) > @maxphylen 
begin
        /*
        ** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
        */
        raiserror 17325, @physicalname, @maxphylen
        return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_addumpdevice"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
** Check to see that the @logicalname is valid.
*/
if valid_name(@logicalname, @maxlen) = 0
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @logicalname
	return (1)
end

/*
**  The rules for updating sysdevices are as follows:
**	devtype - may be 'disk', 'tape' or 'archive database'.
**		If 'disk' then cntrltype will be 2,
**		If 'tape' then 3.  
**		cntrltype is not used for 'archive database'.
**	logicalname - may be any identifier but must be unique
**	physicalname - may be anything and doesn't have to be unique
**		If it contains illegal id characters, e.g., '/', then
**		it must be in quotes.
**	tapesize - for a tape device, this is the tape capacity in MB.  It
**		is ignored on VMS.
*/


/*
**  Check out the @devtype.
*/
select @devtype = lower(@devtype)

if (@devtype = "tape")
begin
	select @cntrltype = 3
end
else if (@devtype = "disk")
begin
	select @cntrltype = 2
end
else if (@devtype != "archive database")
begin
	/*
	** 17310, "Unknown device type.  Use 'disk' or 'tape'."
	*/
	raiserror 17310
	return (1)
end

/*
**  Check the args are not NULL.
*/
if @logicalname is NULL
begin
	/*
	** 17311, "@logicalname may not be NULL."
	*/
	raiserror 17311, @logicalname
	return (1)
end


if @physicalname is NULL
begin
	/*
	** 17312, "@physicalname may not be NULL."
	*/
	raiserror 17312, @physicalname
	return (1)
end

/*
**  Make sure that a device with @logicalname doesn't already exist.
*/
if exists (select *
		from master.dbo.sysdevices
			where name = @logicalname)
begin
	/*
	** 17314, "Device with same logical name already exists."
	*/
	raiserror 17314
	return (1)
end

/*
**  Always turn on the dump status bit.
*/
select @status = 16

/*
**  If @devtype is a tape then check to see if devstatus is 'skip'.
*/
if @devtype = "tape"
begin
	/*
	**  If this is not VMS, then @tapesize is required.
	*/
	if not exists (select *
			from master.dbo.spt_values
				where type = "E"
					and name = "vms")
	begin
		if @tapesize is NULL or @tapesize < 1
		begin
			/*
			** 17317, "Please specify media capacity in megabytes (1 MB minimum)."
			*/
			raiserror 17317
			return (1)
		end

                select @tapeblocksize = 32768

                select  @tapesize =
                        convert(int, ((@tapesize * 1048576.)
                                + @tapeblocksize -1) / @tapeblocksize)
	end
	else
	begin
		select @tapesize = 0
	end
end
else 
begin
	if @tapesize is not NULL
	begin
		/*
		** 17318, "WARNING: specified size parameter is not used for the disk device type."
		*/
		raiserror 17318
	end
	select @tapesize = 0
end

if @devtype = "archive database"
begin

	/*
	** If we're not in the master database, the do not allow the adding 
	** of archive database devices.
	*/
	if db_name() != "master"
	begin
        	/*
        	** 18388, "You must be in the master database in order to run %1!
        	*/
        	raiserror 18388, "sp_addumpdevice 'archive database'"
        	return (1)
	end
	disk reinit name=@logicalname, physname=@physicalname, adb

	if (@@error != 0)
		return (1)
end
else
begin
	/* Tell the server about the device by inserting into sysdevices */
	insert into master.dbo.sysdevices (vdevno, low, high, status, status2, cntrltype, name, phyname)
		values (0, 0, @tapesize, @status, 0, @cntrltype, @logicalname, @physicalname)
end

if @devtype = "disk" or @devtype = "archive database"
	/*
	** 17319, "'Disk' device added."
	*/
	exec sp_getmessage 17319, @msg output
else
	/*
	** 17320, "'Tape' device added."
	*/
	exec sp_getmessage 17320, @msg output

print @msg

/*
**  Warn about duplicate physical names.
*/
if (select count(*)
	from master.dbo.sysdevices
		where phyname = @physicalname) > 1
begin
	/*
	** 17321, "WARNING: physical device name '%1!' is not unique."   
	*/
	exec sp_getmessage 17321, @msg output
	print @msg, @physicalname
end

return (0)
go
exec sp_procxmode 'sp_addumpdevice', 'anymode'
go
grant execute on sp_addumpdevice to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addthreshold')
begin
	drop procedure sp_addthreshold
end
go
print "Installing sp_addthreshold"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_addthreshold"               17870
**
** 17240, "'%1!' is not a valid name."
** 17870, "Table '%1!' does not exist in database '%2!' -- cannot add
**	  thresholds."
** 17871, "There is no segment named '%1!'."
** 17872, "This threshold is too close to one or more existing thresholds. 
** 		Thresholds must be no closer than 128 pages to each other."
** 17873, "Adding threshold for segment '%1!' at '%2!' pages."
** 17874, "A threshold at %1! pages is logically impossible for segment '%2!'.
**		Choose a value between %3! and %4! pages."
** 17875, "Only the DBO of database '%1!' or a user with System Administrator
**	   (SA) authorization may add, delete, or modify thresholds in that
**	   database."
** 17289, "Set your curwrite to the hurdle of current database."
** 18084, "A threshold at %1! pages for segment '%2!' is too close to the 
**	   maximum size of the database. Because of this, the threshold will 
**	   not fire more than once per SQL server re-boot. Modify the value 
**	   using sp_modifythreshold to be between %3! and %4! pages."
** 17876, "Warning: The specified threshold level is greater than the 
**         existing number of free pages on this segment."
** 17879, "Only Users that have System Administrator (SA) authorization 
**	   granted directly may add, or modify thresholds in that 
**	   database."
*/

create procedure sp_addthreshold
@dbname		varchar(255),	/* current database name */
@segname	varchar(255),	/* segment name		*/
@free_space	int,		/* threshold level	*/
@proc_name	varchar(255)	/* threshold procedure	*/
as

declare	@segno			int,
	@segmap			int,
	@pagect			int,
	@curr_free_space	int,
	@hyst			int,
	@maxthpgct		int,
	@msg			varchar(1024),
	@notdbo			int,
	@sarole			int,
	@maxseg 		int,
	@retval			int

/*
** If we are under a user defined xact, disallow this since we may
** leave the dbtable's threshold cache out-of-sync if the end user
** rollbacks its xact.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_addthreshold"
	return (1)
end

set transaction isolation level 1    
set chained off

/*
** Make sure we are in the right database
*/
if (@dbname != db_name())
begin
	/*
	** 18031, "You are in the wrong database.  Say 'USE %1!', then run
	**         this procedure again."
	*/
	raiserror 18031, @dbname
	return (5)
end

/*
** Make sure our database is recent enough to contain Systhresholds
*/
if (select name from sysobjects
	where	name = 'systhresholds'
	  and	type = 'S')
   is NULL
begin
	/*
	** 17870, "Table '%1!' does not exist in database '%2!' -- cannot
	**	  add thresholds."
	*/
	raiserror 17870, "systhresholds", @dbname
	return (1)
end

/*
** Check to see if we are actually the DBO of this database without
** sa_role
*/
if exists (select * from sysusers where uid = 1 and suid = suser_id())
begin
	select @notdbo = 0
end
else
begin
	/*
        ** Check to see if we are the DBO alias of this database
        ** without sa_role
        */
        if exists (select * from sysalternates
                where suid = suser_id() and
                        altsuid = (select suid from sysusers
                                where uid = 1))
        begin
                select @notdbo = 0
        end
        else
        begin
                select @notdbo = 1
        end
end

select @sarole = 0

/*
** Check to see if we need to do auditing for sa_role.
*/
if (charindex("sa_role", show_role()) > 0)
begin
	select @sarole = proc_role("sa_role")
end

/*
** Make sure the user (is the DBO) or (has "sa_role" directly granted to them)
*/
if (@notdbo = 1 and @sarole != 1)
begin
	if (@sarole = 2)
	begin
		/* User has sa_role indirectly therefore deny this attempt.
		** This behavior is due to bug 131764, the inability to handle
		** all system defined roles acquired through UDR roles. 
		*/
		/*
		** Only Users that have System Administrator (SA) authorization 
		** granted directly may add, or modify thresholds in that 
		** database.
		*/	
		raiserror 17879
	end
	else
	begin
		/*
		** 17875, "Only the DBO of database %1! or a user with System
		** Administrator (SA) authorization may add, delete, or modify
		** thresholds in that database."
		*/
		raiserror 17875, @dbname
	end

	return (1)
end



/*
** Make sure the segment name is valid.
*/
select @segno = segment from syssegments where name = @segname
if @segno is NULL
begin
	/*
	** 17871, "There is no segment named '%1!'."
	*/
	raiserror 17871, @segname
	return (2)
end

/*
** Make sure the threshold fits within the segment
*/
select @maxseg = low
	from 	master.dbo.spt_values
	where 	type = "E"
	and 	number = 2

if (@segno < 31)
	select @segmap = power(2, @segno)
else
	select @segmap = @maxseg

select @pagect = sum(size) from master..sysusages
where	dbid = db_id()
  and	segmap & @segmap = @segmap
if (@free_space < 0) or (@free_space > @pagect)
begin
	/*
	** 17874, "A threshold at %1! pages is logically impossible for
	** segment '%2!'.  Choose a value between %3! and %4! pages."
	*/
	raiserror 17874, @free_space, @segname, 0, @pagect
	return (4)
end

/*
** Make sure there is no existing threshold too close to this new one
*/
select @hyst = (2 * @@thresh_hysteresis) - 1
if exists (select free_space from systhresholds
	   where	segment = @segno
	     and	free_space between (@free_space - @hyst) and
					   (@free_space + @hyst))
begin
	/*
	** 17872, "This threshold is too close to one or more existing
	**	  thresholds.  Thresholds must be no closer than 128 pages
	**	  to each other."
	*/
	raiserror 17872

	select @segname as 'segment_name', free_space into #systhresholds1
	from systhresholds
	where	segment = @segno
	  and	free_space between (@free_space - @hyst) and
				   (@free_space + @hyst)
	order by free_space

	exec @retval = sp_autoformat #systhresholds1
	drop table #systhresholds1
	if (@retval != 0)
		return 1

	return (3)
end

/*
** Make sure that the threshold is not too close to the maximum size of
** the database segment. If threshold value + @@thresh_hysteresis greater
** than maximum size of the database segment then the threshold will fire
** only once.
*/
select @maxthpgct = @pagect - @@thresh_hysteresis - 1
if (@pagect <= (@free_space + @@thresh_hysteresis))
begin
	/*
	** 18084, "A threshold at %1! pages for segment '%2!' is too 
	** close to the maximum size of the database. Because of this,
	** the threshold will not fire more than once per SQL server 
	** re-boot. Modify the value using sp_modifythreshold to be 
	** between %3! and %4! pages."
	*/
	exec sp_getmessage 18084, @msg output
	print @msg, @free_space, @segname, 0, @maxthpgct

	/* This is not an error, so raise a message and continue.  */
	
end

/*
** We do not validate the procedure name, since it might be in a different
** database or even in a remote server.  Thus, we have done all the tests
** we can.  Add the threshold.
*/

/*
** 17873, "Adding threshold for segment '%1!' at '%2!' pages."
*/
exec sp_getmessage 17873, @msg output
print @msg, @segname, @free_space

begin transaction insert_threshold



insert systhresholds values(@segno, @free_space, 0, @proc_name,
			    suser_id(), current_roles())


if @@error != 0
begin
	rollback transaction
	/*
	 ** 17877, "Insert of systhresholds row failed. "
	 */
  raiserror 17877
	return (1)
end

/*
** Last, rebuild the database threshold table
*/
dbcc dbrepair(@dbname, "newthreshold", @segname)

if @@error != 0
begin
	rollback transaction
	/*
	 ** 17878, "Rebuild of the database threshold table failed.
	 */
  raiserror 17878
	return (1)
end
/*
** If the specified threshold level(@free_space) is greater than the
** the existing number of free pages on the segment, the user should 
** be warned about this
*/

 if (@segmap = 4)
	select @curr_free_space = lct_admin("logsegment_freepages", db_id())
 else
	select @curr_free_space = sum(curunreservedpgs(dbid, lstart, unreservedpgs)) 
		from master.dbo.sysusages u, syssegments s
			where u.dbid = db_id()
				and (u.segmap & case when s.segment < 31
						then power( 2, s.segment )
						else @maxseg
						end) != 0
				and s.name = @segname
 if (@curr_free_space < @free_space )
 begin
	/* 17876, "Warning: The specified threshold level is greater 
	** than the existing number of free pages on this segment."   
        */
	exec sp_getmessage 17876, @msg output
	print @msg

	/* This is a warning, not an error. Hence raise a message
	   and continue. */
      
 end

commit transaction
return (0)
go
exec sp_procxmode 'sp_addthreshold', 'anymode'
go
grant execute on sp_addthreshold to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_modifythreshold')
begin
	drop procedure sp_modifythreshold
end
go
print "Installing sp_modifythreshold"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_modifythreshold"            17870
**
** 17870, "Table '%1!' does not exist in database '%2!' -- cannot add
**	  thresholds."
** 17871, "There is no segment named '%1!'."
** 17872, "This threshold is too close to one or more existing thresholds.
**	   Thresholds must be no closer than 128 pages to each other."
** 17874, "A threshold at %1! pages is logically impossible for
**	   segment '%2!'.  Choose a value between %3! and %4! pages."
** 17875, "Only the DBO of database '%1!' or a user with System Administrator
**	   (SA) authorization may add, delete, or modify thresholds in that
**	   database."
** 17904, "Segment '%1!' does not have a threshold at '%2!' pages."
** 18031, "This procedure can only affect thresholds in the current database.
**	   Say 'USE %1!', then run this procedure again."
** 18032, "You may not alter the free space or segment name of the
**	   log's last-chance threshold."
** 17289, "Set your curwrite to the hurdle of current database."
** 18084, "A threshold at %1! pages for segment '%2!' is too close to the 
**	   maximum size of the database. Because of this, the threshold will 
**	   not fire more than once per SQL server re-boot. Modify the value 
**	   using sp_modifythreshold to be between %3! and %4! pages."
** 17879, "Only Users that have System Administrator (SA) authorization 
**	   granted directly may add, or modify thresholds in that 
**	   database."
*/

create procedure sp_modifythreshold
@dbname 	varchar(255),		/* this database	*/
@segname	varchar(255),		/* segment name		*/
@free_space	int,			/* threshold level	*/
@new_proc_name	varchar(255)=NULL,	/* threshold procedure	*/
@new_free_space	int = NULL,		/* new threshold level	*/
@new_segname	varchar(255) = NULL	/* new segment name	*/
as

declare	@segno	int,
	@segmap	int,
	@pagect	int,
	@status	int,
	@proxim	int,
	@newsegno int,
	@maxthpgct	int,
	@suid	int,
	@roles	varbinary(255),
	@proc	varchar(255),
	@msg	varchar(1024),
	@notdbo	int,
	@sarole	int

/*
** If we are under a user defined xact, disallow this since we may 
** leave the dbtable's threshold cache out-of-sync if the end user 
** rollbacks its xact.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_modifythreshold"
	return (1)

end

set transaction isolation level 1
set chained off

/*
** Make sure we are in the right database
*/
if (@dbname != db_name())
begin
	/*
	** 18031, "You are in the wrong database.  Say 'USE %1!', then run
	**	   this procedure again."
	*/
	raiserror 18031, @dbname
	return (1)

end

/*
** Make sure our database is recent enough to contain Systhresholds
*/
if (select name from sysobjects
	where	name = 'systhresholds'
	  and	type = 'S')
   is NULL
begin
	/*
	** 17870, "Table '%1!' does not exist in database '%2!' -- cannot add
	**	  thresholds."
	*/
	raiserror 17870, "systhresholds", @dbname
	return (1)
end

/*
** Check to see if we are actually the DBO of this database without
** sa_role
*/
if exists (select * from sysusers where uid = 1 and suid = suser_id())
begin
	select @notdbo = 0
end
else
begin
	/*
        ** Check to see if we are the DBO alias of this database
        ** without sa_role
        */
        if exists (select * from sysalternates
                where suid = suser_id() and
                        altsuid = (select suid from sysusers
                                where uid = 1))
        begin
                select @notdbo = 0
        end
        else
        begin
                select @notdbo = 1
        end

end

select @sarole = 0

/*
** Check to see if we need to do auditing for sa_role.
*/
if (charindex("sa_role", show_role()) > 0)
begin
	select @sarole = proc_role("sa_role")
end

/*
** Make sure the user (is the DBO) or (has "sa_role" directly granted to them)
*/
if (@notdbo = 1 and @sarole != 1)
begin
	if (@sarole = 2)
	begin
		/* User has sa_role indirectly therefore deny this attempt.
		** This behavior is due to bug 131764, the inability to handle
		** all system defined roles acquired through UDR roles. 
		*/
		/*
		** Only Users that have System Administrator (SA) authorization 
		** granted directly may add, or modify thresholds in that 
		** database.
		*/	
		raiserror 17879
	end
	else
	begin
		/*
		** 17875, "Only the DBO of database '%1!' or a user with System
		** Administrator (SA) authorization may add, delete, or modify
		** thresholds in that database."
		*/
		raiserror 17875, @dbname
	end

	return (1)
end



/*
** Make sure the segment name is valid.
*/
select @segno = segment from syssegments where name = @segname
if @segno is NULL
begin
	/*
	** 17871, "There is no segment named '%1!'."
	*/
	raiserror 17871, @segname
	return (2)
end

/*
** Make sure the threshold exists
*/
select @proc = proc_name, @status = status
from	systhresholds
where	segment = @segno
  and	free_space = @free_space
if (@proc is null)
begin
	/*
	** 17904, "Segment '%1!' does not have a threshold at '%2!' pages."
	*/
	raiserror 17904, @segname, @free_space
	select	segment_name=@segname, free_space
	from	systhresholds
	where	segment = @segno

	return (1)
end

/*
** Establish values for new threshold items
*/
if (@new_free_space is NULL)
	select @new_free_space = @free_space
if (@new_segname is NULL)
	select @new_segname = @segname
if (@new_proc_name is NULL)
	select @new_proc_name = @proc
select @suid = suser_id()
select @roles = current_roles()

/*
** May not alter free space and segment name on the logsegment
** last-chance threshold
*/
if ((@segno = 2) and
    ((@status & 1) = 1) and
    ((@new_free_space != @free_space) or
     (@new_segname != @segname)))
begin
	/*
	** 18032, "You may not alter the free space or segment name of the
	**	   log's last-chance threshold."
	*/
	raiserror 18032
	return (1)
end

/* If the user provided a new segment name ... */
if @new_segname != @segname
begin
	/* ... then make sure that it is a valid one ... */
	select @newsegno = segment from syssegments where name = @new_segname
	if @newsegno is NULL
	begin
		/*
		** 17871, "There is no segment named '%1!'."
		*/
		raiserror 17871, @new_segname
		return (2)
	end
end
else
begin
	/* 
	** ... otherwise, do the threshold freespace size 
	** validation tests using the original segment.
	*/
	select @newsegno = @segno
end

/*
** Make sure the threshold fits within the segment
*/
if (@newsegno < 31)
	select @segmap = power(2, @newsegno)
else
	select @segmap = low
		from master.dbo.spt_values
		where type = "E"
		and number = 2

select @pagect = sum(size) from master..sysusages
where	dbid = db_id()
  and	segmap & @segmap = @segmap
if (@new_free_space < 0) or (@new_free_space > @pagect)
begin
	/*
	** 17874, "A threshold at %1! pages is logically impossible for
	** segment '%2!'.  Choose a value between %3! and %4! pages."
	*/
	raiserror 17874, @new_free_space, @new_segname, 0, @pagect
	return (1)
end

/*
** Make sure there is no existing threshold too close to this new one
*/
select @proxim = (2 * @@thresh_hysteresis) - 1
if exists (select free_space from systhresholds
	where	segment = @newsegno
	  and	free_space between  (@new_free_space - @proxim)
				and (@new_free_space + @proxim)
	  and	free_space != @free_space)
begin
	/*
	** 17872, "This threshold is too close to one or more existing
	**	  thresholds.  Thresholds must be no closer than 128 pages
	**	  to each other."
	*/
	raiserror 17872
	select segment_name=@new_segname, free_space
	from systhresholds
	where	segment = @newsegno
	  and	free_space between (@new_free_space - @proxim)
				and (@new_free_space + @proxim)
	  and	free_space != @free_space

	return (1)
end

/*
** Make sure that the threshold is not too close to the maximum size of
** the database segment. If threshold value + @@thresh_hysteresis greater
** than maximum size of the database segment then threshold will fire only
** once.  Signal this condition to the user.
*/
select @maxthpgct = @pagect - @@thresh_hysteresis - 1
if (@pagect <= (@new_free_space + @@thresh_hysteresis))
begin
        /*
        ** 18084, "A threshold at %1! pages for segment '%2!' is too
        ** close to the maximum size of the database. Because of this,
        ** the threshold will not fire more than once per SQL server re-boot.
        ** Modify the value using sp_modifythreshold to be
        ** between %3! and %4! pages."
        */
        exec sp_getmessage 18084, @msg output
        print @msg, @new_free_space, @new_segname, 0, @maxthpgct

	/* This is not an error, so raise a message and continue.  */
end

/*
** We do not validate the procedure name, since it might be in a different
** database or even in a remote server.  Thus, we have done all the tests
** we can.  Modify the threshold.
*/

/*
** 17906, "Dropping threshold for segment '%1!' at '%2!' pages."
*/
exec sp_getmessage 17906, @msg output
print @msg, @segname, @free_space


begin transaction modify_threshold

delete systhresholds
where	segment = @segno
  and	free_space = @free_space

if (@@error != 0)
begin
	rollback transaction
	/*
	** 17907, "Delete of systhresholds row failed."
	*/
	raiserror 17907
	return (1)
end

/*
** 17873, "Adding threshold for segment '%1!' at '%2!' pages."
*/
exec sp_getmessage 17873, @msg output
print @msg, @new_segname, @new_free_space




insert systhresholds values(@newsegno, @new_free_space, @status, 
			    @new_proc_name, @suid, @roles)


if (@@error != 0)
begin
	rollback transaction
	/*
	** 17877, "Insert of systhresholds row failed."
	*/
	raiserror 17877
	return (1)
end


/*
** Last, rebuild the database threshold table
*/
dbcc dbrepair(@dbname, "newthreshold", @segname, 0, @new_segname)

if (@@error != 0)
begin
  rollback transaction
  /*
  ** 17878, "Rebuild of the database threshold table failed."
  */
	raiserror 17878
	return (1)
end

commit transaction

return (0)
go
exec sp_procxmode 'sp_modifythreshold', 'anymode'
go
grant execute on sp_modifythreshold to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_adduser')
begin
	drop procedure sp_adduser
end
go
print "Installing sp_adduser"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/adduser */

/*
** Messages for "sp_adduser"            17330
**
** 17240, "'" + @name_in_db + "' is not a valid name." 
** 17231, "No login with the specified name exists." 
** 17330, "A user with the same name already exists in the database."
** 17331, "User already has a login under a different name."
** 17332, "User already has alias access to the database."
** 17333, "No group with the specified name exists." 
** 17334, "All user ids have been assigned."
** 17335, "New user added."
** 17336, "Setting curwrite label to data_low for inserts into sysusers
**	   table failed."
** 17289, "Set your curwrite to the hurdle of current database."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17265, "A role with the specified name '%1!' already exists in this Server."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '% 1!' on the companion server '%2!'"
** 18778, "A login with Login name '%1!' AND login id '%2!' could not be found in syslogins."
** 18796, "A user with name '%1!' or login id '%2!' already exists in sysusers."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_adduser
@loginame varchar(255),			/* user's login name in syslogins */
@name_in_db varchar(255) = NULL,	/* user's name to add to current db */ 
@grpname varchar(255) = NULL		/* group to put new user in */
as

declare @suid int			/* user's system id */
declare @grpid int			/* group id of group to put user in */
declare @uid int			/* new user's id */
declare @msg varchar(1024)
declare @dummy int
declare @dbname varchar(255)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @maxlen	  int

select @uid = NULL
select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_adduser', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  Call proc_role() with the required SA role.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("sso_role", show_role()) = 0)
	begin
		select @dummy = proc_role("sa_role")
		select @dummy = proc_role("sso_role")
		return (1)
	end
end

if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")
if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  If no new user name is given, use the login name.
*/
if @name_in_db is NULL
	select @name_in_db = @loginame

/*
**  Check to see that the @name_in_db is valid.
*/
if (@name_in_db is not null)
begin
	select @maxlen = length from syscolumns
	where id = object_id("sysusers") and name = "name"

	if valid_name(@name_in_db, @maxlen) = 0
	begin
		/*
		** 17240, "'" + @name_in_db + "' is not a valid name." 
		*/
		raiserror 17240, @name_in_db
		return (1)
	end
end

/*
**  The name guest is a special case.  If it doesn't have a login it
**  can still be a valid user.  We'll catch it here and special case it.
*/
if @loginame = "guest" and not exists
	(select name
		from master.dbo.syslogins (index ncsyslogins)
			where name = @loginame)
begin
	if exists (select *
			from sysusers (index ncsysusers1)
		   where name = @loginame)
	begin
		/*
		** 17330, "A user with the same name already exists in the database."
		*/
		raiserror 17330
		return (1)
	end



	/*
	**  Add the guest user and return.
	*/

	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/

	begin transaction rs_logexec



		insert into sysusers (uid, suid, gid, name)
			values (@@guestuserid, -1, 0, "guest")



		/*
		** Write the log record to replicate this invocation 
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**	    because there was an error in writing
			**	    the replication log record."
			*/
			select @dbname = db_name()
			raiserror 17756, "sp_adduser", @dbname
					
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction rs_logexec

	return (0)
end

/*
**  Check to see that the user has a login name.
**  We'll also initialize @grpid to 0 while we're here.
*/
select @suid = suid, @grpid = 0
	from master.dbo.syslogins (index ncsyslogins)
where name = @loginame

if @suid is NULL
begin
	/*
	** 17231, "No login with the specified name exists." 
	*/
	raiserror 17231
	return (1)
end

/*
**  Now check to see if the user already exists in the database.
**  This will also check if there is a role or group with @name_in_db
**  already in this database.
*/
if exists (select *
		   from sysusers (index ncsysusers1)
	   where name = @name_in_db)
begin
	/*
	** 17330, "A user with the same name already exists in the database."
	*/
	raiserror 17330
	return (1)
end

/*
**  See if the user already has an account under a different name.
**  That is, is the user's suid already in the sysusers table.
*/
if exists (select *
	   from sysusers (index sysusers)
	   where suid = @suid)
begin
	/*
	** 17331, "User already has a login under a different name."
	*/
	raiserror 17331
	return (1)
end

/*
**  See if the user is known in the database already with an alias.
**  That is, does the user's suid appear in the sysalternates table.
*/
if exists (select *
	   from sysalternates
	   where suid = @suid)
begin
	/*
	** 17332, "User already has alias access to the database."
	*/
	raiserror 17332
	return (1)
end

/*
** Make sure a role does not already exist with name.
*/
if exists (select *
	from master.dbo.syssrvroles
	where name = @name_in_db)
begin
	/*
	** 17265, "A role with the specified name '%1!' already exists in this
	**	   Server."
	*/
	raiserror 17265, @name_in_db
	return (1)
end

/*
**  If a group name is given, check to see that it is valid.
**  public group has id = 0
*/
if @grpname is not NULL
begin
	select @grpid = -1
	select @grpid = gid from sysusers
	  where name = @grpname 
		and ( (uid = 0) or 
		      (uid between @@mingroupid and @@maxgroupid))
		and not exists (select name from master.dbo.syssrvroles 
				  where name = @grpname)


	if @grpid = -1
	begin
		/*
		** 17333, "No group with the specified name exists." 
		*/
		raiserror 17333
		return (1)
	end
end

/*
**  Add the user to the sysusers table.
**  Check to see if the special user 'guest' (uid = 2) has already
**  been added.  If not, then the uid to use is 3, otherwise max(uid) + 1.
**  uid can go upto (@@mingroupid - 1) and then there will be a discontinuity 
**  in the range @@mingroupid to @@maxgroupid which are reserved for groups.  
**  We can continue assigning uids from (@@maxgroupid + 1) upto @@maxuserid.  
**  After reaching @@maxuserid, we can wrap around to the -ve space and 
**  assign uid in the range (@@invaliduserid - 1) to @@minuserid.   
*/
/* 
**  HA NOTE: Whenever the logic of uid generation is changed, please also
**	  change it same way to the @uid_hacmp
*/
select @uid = max(uid) from sysusers
where (uid > @@guestuserid and uid < @@mingroupid) 
or (uid > @@maxgroupid and uid <= @@maxuserid)

if @uid  is NULL
/* The first regular user has uid = 3 */
	select @uid = @@guestuserid + 1
else
begin
	if @uid = @@mingroupid - 1	
		/* If we step into group range, skip group values */
		select @uid = @@maxgroupid + 1	
	else
	begin
		if @uid <> @@maxuserid 
			select @uid = @uid + 1
		else
		begin
			/* @@maxuserid has been used up, check the -ve space */
			select @uid = min(uid) from sysusers
			where uid < @@invaliduserid AND uid >= @@minuserid
		
			if @uid is NULL
			/* the first negative uid is -2 */
				select @uid = @@invaliduserid - 1
			else
			begin
				if @uid <> @@minuserid
					select @uid = @uid - 1
				else
				begin
					/* 17334, All uids have been assigned */
					raiserror 17334
					return(1)
				end
			end
		end
	end
end



/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec



	insert into sysusers (uid, suid, gid, name)
		values (@uid, @suid, @grpid, @name_in_db)


	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_adduser", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

commit transaction rs_logexec

/*
** 17335, "New user added."
*/
exec sp_getmessage 17335, @msg output
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)
go
exec sp_procxmode 'sp_adduser', 'anymode'
go
grant execute on sp_adduser to public
go
exec sp_procxmode 'sp_adduser', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addremotelogin')
begin
	drop procedure sp_addremotelogin
end
go
print "Installing sp_addremotelogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/addremotelogin */
/*
** Messages for "sp_addremotelogin"     17270
**
** 17240, "'%1!' is not a valid name."
** 17260, "Can't run %1! from within a transaction." 
** 17270, "There is not a server named '%1!'."
** 17271, "'%1!' is the local server - remote login not applicable."               
** 17272, "There is already a default-name mapping of a remote login from remote server '%1!'."
** 17273, "New remote login created."
** 17274, "'%1!' isn't a local user -- remote login denied."
** 17275, "There is already a remote user named '%1!' for remote server '%2!'."
** 17276  "Usage: sp_addremotelogin remoteserver [, loginame [,remotename]]"
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18780, "Synchronization will not occur because server '%1!' is the companion server."
** 18782, "Unable to find a server with name '%1!' and id '%2!'."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addremotelogin
@remoteserver	varchar(255),		/* name of remote server */
@loginame varchar(255) = NULL,		/* user's remote name */
@remotename varchar(255) = NULL		/* user's local user name */
as

declare	@msg	varchar(1024)
declare @name   varchar(255)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @maxlen	 int
declare @retstat  int
declare @dummy  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addremotelogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_addremotelogin"
	return (1)
end
else
begin
	set chained off
end
set transaction isolation level 1

/* check if user has sa role or sso role. proc_role also generates an 
** audit record and prints an error message for sa role if both sa role 
** and sso role are not present.
*/


if ( (charindex("sa_role", show_role()) = 0) AND (charindex("sso_role", show_role()) = 0) )
begin
        select @dummy = proc_role("sa_role") /* to perform auditing if sa_role fails */
        raiserror 17888, "addremotelogin"
        return (1)
end

/*
**  Check that the server name is valid.
*/
if not exists (select *
			from master.dbo.sysservers
		where srvname = @remoteserver)
begin
	/*
	** 17270, "There is not a server named '%1!'."
	*/
	raiserror 17270, @remoteserver
	return (1)
end

/*
**  If it's the local server don't bother.
*/
if exists (select *
		from master.dbo.sysservers
			where srvname = @remoteserver
				and srvid = 0)
begin
	/*
	** 17271, "'%1!' is the local server - remote login not applicable."        
	*/
	raiserror 17271, @remoteserver
	return (1)
end



/*
**  There are three cases to handle.
**
**	1) if only @remoteserver is given then a entry is made in
**		sysremotelogins that means anyone that doesn't have
**		an exact of mapped match in sysremotelogins will use
**		their remotename as their local name and it will be looked
**		up in syslogins.
**
**	2) if @remotename is omitted then it means that anyone from the
**		remote server logging in that doesn't have a complete
**		match in sysremotelogins will be mapped to @loginame.
**
**	3) if @remotename and @loginame are given then it is a straight
**		remote login for sysremotelogins.
*/

/*
**  Case 1:  Only @remoteserver given.
*/
if @loginame is null and @remotename is null
begin
	/*
	**  Check that there is not already an entry for local mapping.
	*/
	if exists (select *
		from master.dbo.sysremotelogins l, master.dbo.sysservers s
			where l.remoteserverid = s.srvid
				and s.srvname = @remoteserver
				and l.remoteusername is null)
	begin
		/*
		** 17272, "There is already a default-name mapping of a remote login from remote server '%1!'."
		*/
		raiserror 17272, @remoteserver
		goto clean_all
	end



	/*
	**  Add the entry.
	*/
	insert into master.dbo.sysremotelogins 
		(remoteserverid, remoteusername, suid, status)
	select srvid, null, -1, 0
		from master.dbo.sysservers
			where srvname = @remoteserver



	/*
	** 17273, "New remote login created."
	*/
	exec sp_getmessage 17273, @msg output
	print @msg

	goto ha_syn
end

/*
**  Check that the @loginame is valid.  These is needed for both
**  case 2 and 3.
*/
if not exists (select *
		from master.dbo.syslogins
			where name = @loginame)
begin
	/*
	** 17274, "'%1!' isn't a local user -- remote login denied."
	*/
	raiserror 17274, @loginame
	goto clean_all
end

/*
**  Check to make sure that there is not already a @remotename for 
**  the @remoteserver.
*/
if (@remotename is not null)
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.sysremotelogins") and 
				name = "remoteusername"

	if char_length(@remotename) > @maxlen
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @remotename
		return 1
	end
end

if exists (select *
		from master.dbo.sysremotelogins l, master.dbo.sysservers s
			where l.remoteserverid = s.srvid
				and s.srvname = @remoteserver
				and l.remoteusername = @remotename)
begin
	/*
	** 17275, "There is already a remote user named '%1!' for remote server '%2!'."
	*/
	select @name = isnull(@remotename, "NULL")
	raiserror 17275, @name, @remoteserver
	goto clean_all
end
	


/*
**  Case 2: We want to make an entry into sysremotelogins that will map
**	any non-exact matches to a particular local user.
*/
if @remotename is null
begin
	/*
	**  Check that there is not already an entry for local mapping.
	*/
	if exists (select *
		from master.dbo.sysremotelogins l, master.dbo.sysservers s
			where l.remoteserverid = s.srvid
				and s.srvname = @remoteserver
				and l.remoteusername is null)
	begin
		/*
		** 17272, "There is already a default-name mapping of a remote login from remote server '%1!'."
		*/
		raiserror 17272, @remoteserver
		goto clean_all
	end




	/*
	**  Go ahead and make the entry.
	*/
	insert into master.dbo.sysremotelogins
		(remoteserverid, remoteusername, suid, status)
	select srvid, null, suser_id(@loginame), 0
		from master.dbo.sysservers
				where srvname = @remoteserver


	/*
	** 17273, "New remote login created."
	*/
	exec sp_getmessage 17273, @msg output
	print @msg

	goto ha_syn
end

/*
**  Case 3:  All the parameters have been supplied.  All we need to check
**	is that the entry isn't already in sysremotelogins.
**	We've verified the @remoteserver and @loginame above.
*/
if @loginame is not null and @remotename is not null
begin
	/*
	**  Make sure that the @loginame and @remotename are a
	**  unique combination.
	*/
	if exists (select *
		from master.dbo.sysremotelogins l, master.dbo.sysservers s
			where l.remoteusername = @remotename
				and l.remoteserverid = s.srvid
				and s.srvname = @remoteserver
				and l.suid = suser_id(@loginame))
	begin
		/*
		** 17275, "There is already a remote user named '%1!' for remote server '%2!'."
		*/
		raiserror 17275, @remotename, @remoteserver
		goto clean_all
	end



	/*
	**  Go ahead and do the insert.
	*/
	insert into master.dbo.sysremotelogins
		(remoteserverid, remoteusername, suid, status)
	select srvid, @remotename, suser_id(@loginame), 0
		from master.dbo.sysservers
			where srvname = @remoteserver


	
	/*
	** 17273, "New remote login created."
	*/
	exec sp_getmessage 17273, @msg output
	print @msg

	goto ha_syn
end

/*
**  We got here because the syntax was incorrect.
*/

raiserror 17276

clean_all:



	return (1)

ha_syn:



return (0)

go
exec sp_procxmode 'sp_addremotelogin', 'anymode'
go
grant execute on sp_addremotelogin to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addsegment')
begin
	drop procedure sp_addsegment
end
go
print "Installing sp_addsegment"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */
/*	4.1	1.1	06/14/90	sproc/src/addsegment */
/*
** Messages for "sp_addsegment"         17280
**
** 17260, "Can't run %1! from within a transaction." 
** 17280, "No such device exists -- run sp_helpdb to list the
** 	  devices for the current database."
** 17281, "The specified device is not used by the database."
** 17282, "The specified device is not a database device."
** 17283, "'%1!' is reserved exclusively as a log device."
** 17284, "'%1!' is not a valid identifier."
** 17285, "There is already a segment named '%1!'."
** 17286, "The maximum number of segments for the current database are already defined."
** 17287, "Segment created."
** 17288, "You must execute this procedure from the database 
** 	  in which you wish to %1! a segment.  Please execute 
**	  'use %2!' and try again."
** 17590, "The specified database does not exist." 
** 17289, "Set your curwrite to the hurdle of current database."
** 18072, "Setting curwrite to data_low for updating syssegments failed."
** 19572, "A segment with a virtually hashed table exists on device %1!."
*/
create procedure sp_addsegment
@segname	varchar(255),	/* segment name */
@dbname		varchar(255),	/* database name */
@devname	varchar(255)	/* device name to put segment on */
as

declare @segbit	int		/* this is the bit to turn on in sysusages */
declare	@msg	varchar(1024)
declare @returncode int
declare @name varchar(255)
declare @procval int
declare @maxlen  int
declare @isamaster      int
declare @dbid           smallint
declare @segmap	int		/* segment map of device */
declare @tmp_segmap	int
declare @segid	int		/* id of the segment */

select @procval = 0
select @dbid = db_id(@dbname)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	select @name = "sp_addsegment"
	raiserror 17260, @name
	return (1)
end
else
begin
	set chained off
end
set transaction isolation level 1

select @isamaster = 0
if (   (@dbid = db_id("master"))
    or (@dbid = db_id("master_companion")))
begin
	select @isamaster = 1
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  if user  had SA role he would be the dbo hence check only
**  whether user is DBO.
**  Call proc_role() with the required SA role.
*/
if (user_id() = 1)
begin
	/* If user has sa role audit this as a successful sa
	** command execution.
	** If in the future we add new role with "sa" as 
	** substring or allow roles to be added the following could
	** result in an incorrect (extra) audit record being sent.
	*/
	if charindex("sa_role",show_role()) > 0
		select @procval = proc_role("sa_role")
end
else 
begin
	/* user_id() is not DBO hence user does not have SA role
	** audit this as a failed sa command execution.
	*/
	select @procval = proc_role("sa_role")
	return (1)
end

/*
**  Make sure the database exists
*/
if not exists ( select * from master.dbo.sysdatabases
		where name = @dbname )
begin
	/* 17590, "The specified database does not exist." */
	raiserror 17590
	return (1)
end

/*
**  Make sure that we are in the database specified
**  by @dbname. 
*/
if @dbname != db_name()
begin
	/* 
	** 13231, "add"
	** 17288, "You must execute this procedure from the database 
	** 	  in which you wish to %1! a segment.  Please execute 
	**	  'use %2!' and try again."
	*/
	declare @action varchar(30)
	select @action = description
	from master.dbo.sysmessages
	where error = 13231 and langid = @@langid
	if @action is null
		select @action = description
		from master.dbo.sysmessages
		where error = 13231 and langid is null
	if @action is null select @action = "add"
	raiserror 17288, @action, @dbname
	return (1)
end

/*
**  See if the device exists.
*/
if not exists (select *
		from master.dbo.sysdevices
			where name like @devname)
begin
	/*
	** 17280, "No such device exists -- run sp_helpdb to list the
	** 	  devices for the current database."
	*/
	raiserror 17280
	return (1)
end

/*
**  Check to see if the device is marked as a log device.
**  If so, raiserror.
*/
if exists (select *
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = db_id(@dbname)
				and segmap = 4)
begin
	/*
	** 17283, "'%1!' is reserved exclusively as a log device."
	*/
	raiserror 17283, @devname
	return (1)
end

/*
**  Now see if the @devname is a proper database device
*/
if not exists (select *
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and d.cntrltype = 0)
begin
	/*
	** 17282, "The specified device is not a database device."
	*/
	raiserror 17282
	return (1)
end

select @segmap=segmap
	from master.dbo.sysusages u, master.dbo.sysdevices d
		where d.name = @devname
			and u.vstart between d.low and d.high
			and u.dbid = db_id(@dbname)
			and u.vdevno = d.vdevno
if @segmap > 0
begin
	select @tmp_segmap=@segmap - 1
	select @tmp_segmap=@segmap & @tmp_segmap
	if @tmp_segmap = 0
	begin
		/*
		** Only one bit is set in segmap.
		** Thus, there is only one segment
		** existing on device. Now we need 
		** to check if it has vhash table.
		** As if it has a vhash table it
		** will be an exclusive segment and
		** another segment cannot be created
		** on this device.
		*/
		select @segid=log(@segmap)/log(2)
		if exists (select * from syssegments
				where segment=@segid and 2 = status & 2)
		begin
			/*
			** 19572, "A segment with a virtually hashed table
			** exists on device %1!."
			*/
			raiserror 19572, @devname
			return (1)
		end
	end
end
/*
**  Now see if the @dbname uses the @devname
*/
if not exists (select *
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = db_id(@dbname))
begin
	/*
	** 17281, "The specified device is not used by the database."
	*/
	raiserror 17281
	return (1)
end

/*
** Check for valid identifier.
*/
select @maxlen = length from syscolumns
	where id = object_id("syssegments") and name = "name"

if valid_name(@segname, @maxlen) = 0
begin
	/*
	** 17284, "'%1!' is not a valid identifier."
	*/
	raiserror 17284, @segname
	return (1)
end

/*
**  Now go ahead and define the new segment and add it to the segmap
**  of sysusages.
**  NOTE: Don't update master..sysusages and syssegments as a xact since
**  	it could cause problems for recovery.
*/

/*
**  Check that @segname doesn't already exist.
*/
if exists (select *
		from syssegments holdlock
			where name = @segname)
begin
	/*
	** 17285, "There is already a segment named '%1!'."
	*/
	raiserror 17285, @segname
	return (1)
end

/*
**  Figure out the next segment number to use.
**  Segment number may be 0-31.
*/
select @segbit = 3
while @segbit < 32
begin
	/*
	**  Did we find one?
	*/
	if exists (select *
			from syssegments
				where segment = @segbit)
	begin
		select @segbit = @segbit + 1
	end

	/*
	**  We found an opening so break out.
	*/
	else break

end

if @segbit >= 32
begin
	/*
	** 17286, "The maximum number of segments for the current database are already defined."
	*/
	raiserror 17286
	return (1)
end



/*
**  Add the new segment.
*/
insert into syssegments (segment, name, status)
	values (@segbit, @segname, 0)



/*
**  Now set the segments on @devname sysusages.
*/
if (@segbit < 31)
	select @segbit = power(2, @segbit)
else
	/*
	**  Since this is segment 31, power(2, 31) will overflow
	**  since segmap is an int.  We'll grab the machine-dependent
	**  bit mask from spt_values to set the right bit.
	*/
	select @segbit = low
		from master.dbo.spt_values
			where type = "E"
				and number = 2

/* Encapsulate sysusages/anchor update in a transaction */
if (@isamaster = 1)
	begin tran sysusg_upd

update master.dbo.sysusages
	set segmap = segmap | @segbit
		from master.dbo.sysusages u,
			master.dbo.sysdevices d
		where d.name = @devname
			and u.vdevno = d.vdevno
			and u.dbid = db_id( @dbname)
if (@isamaster = 1)
begin
	if (@@error != 0)
	begin
		rollback transaction sysusg_upd
		return (1)
	end

	dbcc dbrepair(@dbname, "upd_usg")

	if (@@error != 0)
	begin
		rollback transaction sysusg_upd
		return (1)
	end

	commit transaction sysusg_upd
end

/*
**  Now we need to activate the new segment map.
*/
dbcc dbrepair (@dbname, remap, NULL, -1, @segname)
/*
** 17287, "Segment created."
*/
exec sp_getmessage 17287, @msg output
print @msg
return (0)
go
exec sp_procxmode 'sp_addsegment', 'anymode'
go
grant execute on sp_addsegment to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addserver')
begin
	drop procedure sp_addserver
end
go
print "Installing sp_addserver"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/addserver */

/*
** Messages for "sp_addserver"          17290
**
** 17260, "Can't run %1! from within a transaction." 
** 17240, "'" + @lname + "' is not a valid name." 
** 17290, "There is already a server named '%1!', physical name '%2!'."
** 17291, "Usage: sp_addserver servername [, 'local | NULL'] [, physical_name]"
** 17292, "There is already a local server."
** 17293, "Server added."
** 17294, "Changing physical name of server '%1!' from '%2!' to '%3!'"
** 17295, "Adding server '%1!', physical name '%2!'"
** 17296, "Unknown server class '%1!'."
** 17297, "Changing server class of server '%1!' from '%2!' to '%3!'"
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18784, "HA warning:Server is currently configured. Any changes to SYB_HACMP or companion server can be serious."
** 18799, "Unable to find a server with name '%1!', id '%2!', and netname '%3!' in sysservers."
** 18800, "A server with name '%1!' and id '%2!' already exists in sysservers."
** 18820, "You cannot change the physical name of server %1! because it is configured as a node of HA cluster."
** 18881, "Unable to generate %1! for HA use. Please Refer to documentation for details."
** 18887, "Cannot have more than one physical or logical server entry for the 
** ASEJB class."
** 19971, "You cannot change the server class of existing server '%1!' from '%2!' to '%3!'."
** 19972, "Local server must use the cluster name as the server name."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addserver
@lname	varchar(255),		/* server logical name */
@class	varchar(15) = "ASEnterprise",	/* server class */
@pname	varchar(255) = NULL	/* server physical name */

as
declare	@msg		varchar(1024),
	@netname	varchar(255),
	@dflt_status	smallint,
	@dflt_status2   unsigned int

declare @srvclass	smallint,
	@newclass	smallint,
	@srvid		smallint,
	@remotesrvid	smallint,
	@srvcost	smallint,
	@oldclass	varchar(255),
	@dupsrvclass	smallint,
	@outstr		varchar(255),	/* for SDC dbcc set_scope */
	@scope		varchar(16)	/* for SDC dbcc set_scope */

declare @maxlen		int
declare @end_code	int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @backupejbflag	int
declare @isrtds		int	/* server class is rtds */
declare @insysattributes int	/* There is row about the changed rtds server in sysattributes */
declare @leavertds	int 	/* server class is changed from rtds to non-rtds */

declare	@bs_name	varchar(255)	/* BS name to be checked in sysservers table */
declare	@bs_flag	int		/* Indicate BS entries in sysservers table */
select @HA_CERTIFIED = 0
select @backupejbflag = 0
select @isrtds = 0
select @insysattributes = 0
select @leavertds = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addserver', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_addserver"
	return (1)
end
else
begin
	set chained off
end
set transaction isolation level 1

/* check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sso_role") = 0)
	return (1)


/*
**  Check to see that the @lname is valid.
*/
if (@lname is not null)
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.sysservers") and name = "srvname"

	if valid_name(@lname, @maxlen) = 0
	begin
		/*
		** 17240, "'" + @lname + "' is not a valid name." 
		*/
		raiserror 17240, @lname
		return (1)
	end
end

/*
**  Check to see that the @lname is valid name.
*/
if (@lname is not null)
begin
	if (@lname = "cluster" or @lname = "CLUSTER")
	begin
		/*
		** 17240, "'" + @lname + "' is not a valid name." 
		*/
		raiserror 17240, @lname
		return (1)
	end
end

/*
** OMNI: See if we have a valid server class. If null, default to 'sql_server'.
*/
if @class is null
	select @class = "ASEnterprise"

select	@newclass = number
from	master.dbo.spt_values
where	type = 'X' and lower(name) = lower(@class)
if @@rowcount = 0
begin
	/*
        ** 17296, "Unknown server class '%1!'" 
        */
	raiserror 17296, @class
	return(1)
end

/*
** to check if the server is a rtds provider
*/
if @newclass in (12, 13, 14, 15)
	select @isrtds = 1
else
	select @isrtds = 0

/*
**  Check to see that the @pname is valid.
*/
if (@pname is NULL)
	select @pname = @lname
else
/*
** If the netname contains a colon, it's ok to use, as it may be in the form:
**
** 	"hostname.domain.com:12345"	or
**	"hostname:12345"		or
**	"255.255.255.255:12345"
**
** which is format for netname now supported by ctlib's CS_SERVERADDR connection 
** property. Note that Omni converts colon to space before calling ct_con_props().
**
** Note, IBM_MQ names (class == 13) don't have colons (:), but they have
** parenthesis (()), so bypass the valid name check.
*/

select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.sysservers") and name = "srvnetname"

/*
** If the name is SYB_BACKUP and netname is $dedicated or $roundrobin which is
** Backup server policy to enable Multiple Backup server feature,
** check for all Backup server entries in sysservers table.
*/
if ((@lname = "SYB_BACKUP") and ((lower(@pname) = "$dedicated") or (lower(@pname) = "$roundrobin")))
begin	
	select @bs_flag = 0
	
	declare instancenames cursor for
	select srvname from master..sysservers where srvstatus2 = 4

	open instancenames

	fetch instancenames into @bs_name
	
	while (@@sqlstatus = 0)
	begin
		select @bs_name = @bs_name + "_BS"
		if not exists(select * from master..sysservers where srvname = @bs_name)
		begin
			/*
			** 19968, "Backup Server '%1!' is not configured in sysservers."
			*/
			raiserror 19968, @bs_name
			select @bs_flag = 1
		end	
		fetch instancenames into @bs_name
	end
	close instancenames	

	if (@bs_flag = 1)
	begin
		/*
		** 19969, "Multiple Backup Server in Cluster can not be enabled."
		*/
		raiserror 19969
		return(1)
	end	
end

/*
** If the name is SYB_BACKUP and netname is $dedicated or $roundrobin which is
** Backup server policy to enable Multiple Backup server feature,
** allow the netname as specified keywords skipping valid_name() check.
*/
if (not ((@lname = "SYB_BACKUP") and ((lower(@pname) = "$dedicated") or (lower(@pname) = "$roundrobin"))))
begin	
if charindex(":", @pname) = 0 and valid_name(@pname, @maxlen) = 0 and @newclass != 13
begin
	/*
	** 17240, "'" + @pname + "' is not a valid name." 
	*/
	raiserror 17240, @pname
	return (1)
end
end

/*
** If the server is rtds provider, check if it is registered in sysattributes
*/
if (@isrtds = 1)
	and (exists (select * from master.dbo.sysattributes
			where class = 21 and attribute = 10
				and object_type = 'PR'
				and object_cinfo = @lname))
	select @insysattributes = 1
else
	select @insysattributes = 0

/*
**  Server names must be unique so check.  If a server already exists with
**  this logical _and_ physical name, the server already exists, so there's
**  no work to do.  However, if the logical name exists but the physical
**  names differ, this will be an update to the table to change the physical
**  name.
*/
if exists (select *
		from master.dbo.sysservers
			where srvname = @lname)
begin
	if (@isrtds = 0) or (@insysattributes = 0)
	begin
	 select @srvclass = srvclass,
		@srvid = srvid,
	 	@netname = isnull(srvnetname, @lname)
		from master.dbo.sysservers
			where srvname = @lname
	end
	else
	begin
		select 	@srvclass = int_value,
			@srvid = object,
			@netname = isnull(char_value, @lname)
			from master.dbo.sysattributes
			where class = 21 and attribute = 10
				and object_type = 'PR'
				and object_cinfo = @lname
	end
		
	/*
	** 17290, "There is already a server named '%1!', physical name '%2!'."
	*/
	if (@netname = @pname AND @srvclass = @newclass)
	begin
		raiserror 17290, @lname, @pname
		return (1)
	end

	if (@isrtds = 0) and (@srvclass in (12, 13, 14, 15))
	 	select @leavertds = 1
	else
		select @leavertds = 0



	if (@isrtds = 1) or (@leavertds = 1)
		begin tran rtds_dyn

	if (@leavertds = 1)
	begin
		delete from master.dbo.sysattributes
		where class = 21 and attribute = 10
			and object_type = 'PR' and object_cinfo = @lname
		if (@@error != 0)
			goto clean_all
	end

	if (@isrtds = 1)
	begin
		if (@insysattributes = 1)
			update master.dbo.sysattributes
			set char_value = @pname, int_value = @newclass 
			where class = 21 and attribute = 10
				and object_type = 'PR'
				and object_cinfo = @lname
                else
			insert master.dbo.sysattributes
			(class, attribute, object_type, object_cinfo,
				object, int_value, char_value)
			values (21, 10, 'PR', @lname, @srvid, @newclass,
				@pname)
		if (@@error != 0)
			goto clean_all
	end



	/*
	** 17294, "Changing physical name of server '%1!' from '%2!' to '%3!'"
	*/
	if (@netname != @pname)
	begin
		update master.dbo.sysservers
		set srvnetname = @pname
		where srvname = @lname

		if (@@error != 0) 
		begin
			if (@isrtds = 1) or (@leavertds = 1)
				goto clean_all

		end



		/* Suppress the Msg only for SYB_HACMP changes for netname */
		if @lname != "SYB_HACMP"
		begin	
			exec sp_getmessage 17294, @msg output
			print @msg, @lname, @netname, @pname
		end
	end

	/*
	** 17297, Changing server class of server '%1!' from '%2!' to '%3!'
	*/
	if (@srvclass != @newclass)
	begin
		select	@oldclass = name
		from	master.dbo.spt_values
		where	type = 'X' and number = @srvclass
		if @@rowcount = 0
		begin
			select @oldclass = "unknown"
		end

		if lower(@class) = "local"
		begin
			/*
			** 19971, "You cannot change the server class of
			** existing server '%1!' from '%2!' to '%3!'."
			*/
			raiserror 19971, @lname, @oldclass, @class
			return (1)
		end

		update master.dbo.sysservers
			set srvclass = @newclass
			where srvname = @lname

		if (@@error != 0)
		begin
			if (@isrtds = 1) or (@leavertds = 1)
				goto clean_all

		end


                exec sp_getmessage 17297, @msg output
		print @msg, @lname, @oldclass, @class
	end

	if (@isrtds = 1) or (@leavertds = 1)
		commit tran rtds_dyn
	/*
	** For SDC, update cluster-wide in-memory SRVDES with data from
	** just-updated SYSSERVERS table. Before dbcc cis, the dbcc
	** command scope needs to be set to cluster.
	*/
	if (@@clustermode = "shared disk cluster")
	begin
		select @scope = NULL
		select @outstr = "dbcc set_scope_in_cluster('scope')"
		if (charindex("instance", @outstr) != 0)
		begin
			/* save the scope to be restored later */
			select @scope = "instance"
			dbcc set_scope_in_cluster('cluster')
		end
	end
	
	dbcc cis ("srvdes", @srvid)

	/* restore dbcc command scope */
	if (@@clustermode = "shared disk cluster")
	begin
		if (@scope = "instance")
		begin
			dbcc set_scope_in_cluster('instance')
		end
	end



	return(0)
end

/*
** Check to see that the server class is unique for the EJB class
*/
select @dupsrvclass = srvclass
from   master.dbo.sysservers
where srvclass = 10 and @class = "ASEJB"

if @@rowcount >= 1
begin
	/*
	** 18887, "Cannot have more than one physical or logical server 
	** entry for the ASEJB class."
	*/
	raiserror 18887
        return(1)
end

/* 
** If the server is of the class ASEJB, set the default status to 1024 which
** indicates that the 'external engine auto start option would be enabled
** for such class of servers
*/
if @class = "ASEJB"
begin
	select @dflt_status = number from master.dbo.spt_values
	where type = "A" and name = "external engine auto start"
	select @dflt_status = @dflt_status + number from master.dbo.spt_values
		where type = "A" and name = "no timeouts"
end
else
begin
	/*
	** retrieve the value of the default security setting, namely
	** RPC security model A
	*/
	select @dflt_status = number from master.dbo.spt_values
		where type = "A" and name = "rpc security model A"

	select @dflt_status = @dflt_status + number from master.dbo.spt_values
		where type = "A" and name = "no timeouts"
end

/*
** Default is for non-relocateable joins
*/
select @dflt_status2 = 0

/*
** Default values for srvstatus2 
**
**		OPTION			VALUE	BIT
**		~~~~~~			~~~~~	~~~
**	enable login redirection	ON	0x00000002
**	cluster instance 		OFF	0x00000004
*/
select @dflt_status2 = 2

/*
**  If this is not the local server, then its srvid = max(srvid) + 1.
*/
if lower(@class) != "local"
begin	

	/*
	** 17295, "Adding server '%1!', physical name '%2!'"
	*/
	exec sp_getmessage 17295, @msg output
	print @msg, @lname, @pname




	select @srvid = isnull(max(srvid), 0) + 1
	from master.dbo.sysservers where srvid != 999

	/*
	** Set the default cost for remote servers
	*/
	select @srvcost = 1000
	

if (@isrtds = 1)
	begin tran rtds_dyn
if (@backupejbflag = 1)
begin
	insert into master.dbo.sysservers 
		(srvid, srvstatus, srvname, srvnetname ,srvclass, srvcost, srvstatus2)
		values (@remotesrvid, @dflt_status, @lname, @pname, @newclass, @srvcost, @dflt_status2)
end
else
begin
	insert into master.dbo.sysservers 
		(srvid, srvstatus, srvname, srvnetname ,srvclass, srvcost, srvstatus2)
		values (@srvid, @dflt_status, @lname, @pname, @newclass, @srvcost, @dflt_status2)
	if (@@error != 0)
		goto clean_all
	if (@isrtds = 1)
	begin
		if (@insysattributes = 1)
		begin
			update master.dbo.sysattributes
			set int_value = @newclass, char_value = @pname, 
				object = @srvid
			where class = 21 and attribute = 10
				and object_type = 'PR'
				and object_cinfo = @lname
		end
		else
		begin
			insert master.dbo.sysattributes
			(class, attribute, object_type, object_cinfo,
				object, int_value, char_value)
			values (21, 10, 'PR', @lname, @srvid, @newclass, @pname)
		end
		if (@@error !=0 )
			goto clean_all
		commit tran rtds_dyn
	end
end


	

end

/*
**  If @class = "local" then this is the local server and it's
**  srvid = 0.

*/
else
begin
	if lower(@class) != "local"
	begin
		/*
		** 17291, "Usage: sp_addserver servername [, 'local | NULL'],
		**	   [, physical_name]"
		*/
		raiserror 17291
		return (1)
	end

	if exists (select *
			from master.dbo.sysservers
				where srvid = 0)
	begin
		/*
		** 17292, "There is already a local server."
		*/
		raiserror 17292
		return (1)
	end

	if (@@clustermode = "shared disk cluster")
	begin
		if @lname != @@clustername
		begin
			/*
			** 19972, "Local server must use the cluster name as the server name."
			*/
			raiserror 19972
			return (1)
		end
	end

	/*
	** 17295, "Adding server '%1!', physical name '%2!'"
	*/
	exec sp_getmessage 17295, @msg output
	print @msg, @lname, @pname



	insert into master.dbo.sysservers 
		(srvid, srvstatus, srvname, srvnetname, srvclass, srvcost, srvstatus2)
			values (0, @dflt_status, @lname, @pname, 0, 0, @dflt_status2)

end

/*
** 17293, "Server added."
*/
exec sp_getmessage 17293, @msg output
print @msg
return (0)


clean_all:
	if (@isrtds = 1) or (@leavertds = 1)
		rollback tran rtds_dyn

	return(1)
go
exec sp_procxmode 'sp_addserver', 'anymode'
go
grant execute on sp_addserver to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addlanguage')
begin
	drop procedure sp_addlanguage
end
go
print "Installing sp_addlanguage"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/addlanguage */

/*
** Messages for "sp_addlanguage"        17250
**
** 17240, "'%1!' is not a valid name."
** 17250, "'%1!' already exists in Syslanguages."
** 17251, "'%1!' is not a valid date order."
** 17252, "'%1!' is not a valid first day."
** 17253, "'%1!' alias already exists in Syslanguages."
** 17254, "Language not inserted."
** 17255, "New language inserted."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18774, "Languange name '%1!', alias '%2!', and/or language id '% 3!' already exists in Syslanguages."
** 18881, "Unable to generate %1! for HA use. Please Refer to documentation for details."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addlanguage 
@language varchar(255),
@alias varchar(255) = NULL,
@months varchar(251),
@shortmons varchar(119),
@days varchar(216),
@datefmt char(3),
@datefirst tinyint
as

declare @msg varchar(1024)
declare @nextlangid smallint
declare @returncode	int 
declare @convdate char(3)
declare @maxlen int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addlanguage', @HA_CERTIFIED
if (@retstat != 0)
        return (1)


/*
** NOTE:
** We should check here to see if we're in a transaction, and return
** with a 17260 error ("Can't run %1! from within a transaction.") if
** we are in a transaction.  However, the langinstall utility currently
** calls sp_addlanguage from within a transaction.  Until this behavior
** is changed we'll allow ourselves to be called from within a xact.
*/

/* 
** check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)


/* Check to see if the language name is valid */
if (@language is not null)
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.syslanguages") and name = "name"

	if (char_length(@language) > @maxlen) 
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @language
		return 1
	end
end

/*  Check to see if the language exists. */
select @returncode = 0
execute @returncode = sp_validlang @language
if @returncode = 0
begin
	/*
	**  17250, "'%1!' already exists in Syslanguages."
	*/
	raiserror 17250, @language
	return 1
end

/* Check to see that the list of full month names is valid. */
execute @returncode = sp_chklangparam @months, "full month", 12, 20
if @returncode != 0
	return 1

/* Check to see that the list of short month names is valid. */
execute @returncode = sp_chklangparam @shortmons, "short month", 12, 9
if @returncode != 0
	return 1

/* Check to see that the list of day names is valid. */
execute @returncode = sp_chklangparam @days, "day", 7, 30
if @returncode != 0
	return 1

/* Check to see that the @datefmt is valid. */
if (@datefmt != 'mdy' and @datefmt != 'dmy' and @datefmt != 'ymd' and @datefmt != 'ydm'
	and @datefmt != 'myd' and @datefmt != 'dym')
begin
	/*
	** 17251, "'%1!' is not a valid date order."
	*/
	raiserror 17251, @datefmt
	return 1
end

/*
**  Check to see that the @datefirst is valid.
*/
if (@datefirst < 1 or @datefirst > 7)
begin
	/*
	** 17252, "'%1!' is not a valid first day."
	*/
	select @convdate = convert(char(3), @datefirst)
	raiserror 17252, @convdate
	return 1
end

/* Check if @alias is valid */
if (@alias is not null)
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.syslanguages") and name = "alias"

	if (char_length(@alias) > @maxlen) 
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @alias
		return 1
	end
end

/*
**  If the user didn't specify the alias name, the alias name is same as 
**  the official name.
*/
if @alias is null
begin
	select @alias =  @language
end

		
		
/*  Check to see if the alias exists. */
select @returncode = 0
execute @returncode = sp_validaltlang @alias
if @returncode = 0
begin

	/*
	** 17253, "'%1!' alias already exists in Syslanguages."
	*/
	raiserror 17253, @alias
	return 1
end

if @language = 'us_english'
begin
	


	/*  The language id of us_english is 0. */
	insert master.dbo.syslanguages (langid, dateformat, datefirst, upgrade, 
		name, alias, months, shortmonths, days)
	select 0, @datefmt, @datefirst, 0, 
		@language, @alias, @months, @shortmons, @days
end
else
begin
	/* 
	** Attention:
	** 	if this ID generating algorithm is changed, please 
	**	change the corresponding part in HA section too.
	*/
	if (select max(langid) from master.dbo.syslanguages) is null
	begin
		select @nextlangid = 1
	end
	else
	begin
		select @nextlangid = (select max(langid)+1 
		from master.dbo.syslanguages)
	end



	insert master.dbo.syslanguages (langid, dateformat, datefirst, upgrade, 
		name, alias, months, shortmonths, days)
	     select @nextlangid, @datefmt, @datefirst, 0, 
		@language, @alias, @months, @shortmons, @days
end


/* If the insert failed, say so. */
if @@error != 0
begin
	/*
	** 17254, "Language not inserted."
	*/
	raiserror 17254
	goto clean_all
end



/*
** 17255, "New language inserted."
*/
exec sp_getmessage 17255, @msg output
print @msg
return (0)

clean_all:



	return (1)
    
go
exec sp_procxmode 'sp_addlanguage', 'anymode'
go
grant execute on sp_addlanguage to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_defaultlanguage')
begin
	drop procedure sp_defaultlanguage
end
go
print "Installing sp_defaultlanguage"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:15 2006 
*/
/*
** raiserror Messages for defaultlanguage [Total 7]
**
** 17201, "'%1!' is not an official language name from syslanguages."
** 17260, "Can't run %1! from within a transaction."
** 17451, "This user does not exist.  Run sp_addlogin to add this user in."
** 17453, "Error in changing the default language."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 18388, "You must be in the master database in order to run '%1!'."
** 18409, "The built-in function %1! failed. Please see the other messages printed along with this message."
*/
/*
** sp_getmessage Messages for defaultlanguage [Total 3]
**
** 17452, "%1!'s default language has been changed to %2!."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_defaultlanguage
@loginame varchar(30),			/* login name of the user */
@language varchar(30) = NULL		/* default language for the new user */
as

declare @msg varchar(1024)
declare @returncode int
declare @suid int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @dummy int
declare @sa_role int	/* has sa role */
declare @sso_role int	/* has sso_role */

declare @log_for_rep int
declare @db_rep_level_all int
declare @db_rep_level_none int
declare @db_rep_level_l1 int
declare @lt_rep_get_failed int 

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2

select @HA_CERTIFIED = 0

select @sa_role = charindex("sa_role", show_role()),
	@sso_role = charindex ("sso_role", show_role())



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_defaultlanguage', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_defaultlanguage"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_defaultlanguage"
	return (1)
end

/* 
**  Check to see that the @language is valid.
*/
if @language is not null
begin
	select @returncode = 0
	execute @returncode = sp_validlang @language
	if @returncode != 0
	begin
		if @language != "us_english"
		begin
			/*
			** 17201, "'%1!' is not a valid official language name." **
			*/
			raiserror 17201, @language
			return @returncode
		end
	end
end

/*
**  Make sure the login already exist.
*/
if not exists (select *
	from master.dbo.syslogins
	where name = @loginame)
begin
	/*
	** 17451, "This user does not exist.  Run sp_addlogin to add this user in."
	*/
	raiserror 17451
	return 1
end

/*
**  Only the Account Owner or
**  Accounts with SA role or SSO role can execute it.
**  proc_role will also do auditing if required and
**  will also print error message if required.
**
*/
if ((suser_id() != suser_id(@loginame)) and
		(@sa_role = 0) and (@sso_role = 0))
begin
	select @dummy = proc_role("sa_role")
	select @dummy = proc_role("sso_role")
	return(1)
end
else
begin
	if (@sa_role > 0)
	begin
		select @dummy = proc_role("sa_role")
	end
	if (@sso_role > 0)
	begin
		select @dummy = proc_role("sso_role")
	end
end


	
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



/*
**  Set the default language for this user.
*/

update master.dbo.syslogins 
	set language = @language
 	where name = @loginame

if (@@rowcount = 1)
begin



	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_defaultlanguage", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec

	/*
	** 17452, "%1!'s default language has been changed to %2!."
	*/
	exec sp_getmessage 17452, @msg output
	print @msg, @loginame, @language
	select @returncode = 0
end
else
begin
	/*
	** 17453, "Error in changing the default language."
	*/

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		rollback tran rs_logexec

	raiserror 17453
	select @returncode = 1
end
return (@returncode)

clean_all:
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		rollback tran rs_logexec
        return (1)

go
exec sp_procxmode 'sp_defaultlanguage', 'anymode'
go
grant execute on sp_defaultlanguage to public
go
exec sp_procxmode 'sp_defaultlanguage', 'rep_master'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helplanguage')
begin
	drop procedure sp_helplanguage
end
go
print "Installing sp_helplanguage"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
** Messages for "sp_helplanguage"       17670
**
** 17201, "'%1!' is not an official language name from Syslanguages."
** 17670, "No alternate languages are available."
** 17671, "us_english is always available, even though it is not in
**	master.dbo.syslanguages."
*/
create procedure sp_helplanguage 
@language varchar(255) = NULL
as

declare @msg varchar(1024)
declare @retval int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Print all languages if the user didn't give the language name. */
if @language is null
begin
	if exists (select * from master.dbo.syslanguages)
	begin
		select * into #syslanguages1 from master.dbo.syslanguages
		exec @retval = sp_autoformat #syslanguages1
		drop table #syslanguages1
		if (@retval ! = 0)
			return 1
	end
	else
	begin
		/* 17670, "No alternate languages are available." */
		exec sp_getmessage 17670, @msg out
		print @msg
	end

	/* Find out whether us_english is there or not. */
	if not exists (select * from master.dbo.syslanguages   
			where name = 'us_english') 
	begin
		/* 
		** 17671, "us_english is always available, even though it
		** is not in master.dbo.syslanguages."
		*/
		exec sp_getmessage 17671, @msg out
		print @msg
	end
	return 0
end

/*  Report information on this language. */
if exists (select * from master.dbo.syslanguages   
                where name = @language) 
begin
        select * into #syslanguages2 from master.dbo.syslanguages
                where name = @language
	exec @retval = sp_autoformat #syslanguages2
	drop table #syslanguages2
	if (@retval ! = 0)
		return 1

        return 0
end 

if exists (select * from master.dbo.syslanguages
		where alias = @language)
begin
	select * into #syslanguages3 from master.dbo.syslanguages 
		where alias = @language
	exec @retval = sp_autoformat #syslanguages3
	drop table #syslanguages3
	if (@retval ! = 0)
		return 1

	return 0
end

/* Couldn't find this language. */
if @language = 'us_english'
begin
	/* 
	** 17671, "us_english is always available, even though it is not in
	** 	master.dbo.syslanguages." 
	*/
	exec sp_getmessage 17671, @msg out
	print @msg
	return 0
end
else
begin
	/* 17201, "'%1!' is not an official language name from Syslanguages." */
	raiserror 17201, @language
	return 1
end
go
exec sp_procxmode 'sp_helplanguage', 'anymode'
go
grant execute on sp_helplanguage to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_droplanguage')
begin
	drop procedure sp_droplanguage
end
go
print "Installing sp_droplanguage"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_droplanguage"       17505
**
** 17201, "'%1!' is not an official language name from Syslanguages." 
** 17260, "Can't run %1! from within a transaction."
** 17505, "Can't drop '%1!' because there are associated entries in master.dbo.sysmessages.  Run sp_droplanguage with the 'dropmessages' flag."
** 17506, "The only legal value for @dropmessages is 'dropmessages'."
** 17507, "Language deleted."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '% 1!' on the companion server '%2!'"
** 18775, "Unable to find a language entry with language name '%1!' and language id '%2!'"
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_droplanguage 
@language varchar(30),
@dropmessages varchar(30) = NULL
as

declare @msg varchar(1024)
declare @langid smallint
declare @dropmsgs int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_droplanguage', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_locklogin"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*  Check to see if the language exists. */
declare @returncode	int 
select @returncode = 0
execute @returncode = sp_validlang @language
if @returncode != 0
begin
	/*
	** 17201, "'%1!' is not an official language name from Syslanguages." 
	*/
	raiserror 17201, @language
	return 1
end

/* Get language id from syslanguages. */
select @langid = (select langid 
			from master.dbo.syslanguages 
				where name = @language)

/*  Check to see if "dropmessages" is requested. */
select @dropmsgs = 0
if @dropmessages is null
begin
	if exists (select * from master.dbo.sysmessages 
			where langid = @langid)
	begin
		/* 
		**  Cannot drop a language if the language has associated
		**  entries in the master.dbo.sysmessages.
		*/

		/*
		** 17505, "Can't drop '%1!' because there are associated entries in master.dbo.sysmessages.  Run sp_droplanguage with the 'dropmessages' flag."
		*/
		raiserror 17505, @language
		return 1
	end
end
else
begin
	if @dropmessages != "dropmessages"
	begin
		/*
		** 17506, "The only legal value for @dropmessages is 'dropmessages'."
		*/
		raiserror 17506
		return 1
	end

	select @dropmsgs = 1
end



/* 
**  Drop the language and delete messages from Sysmessages if there is any.
*/
if @dropmsgs = 1
begin
	delete master.dbo.sysmessages
		where langid = @langid



end

delete master.dbo.syslanguages 
	where langid = @langid



/*
** 17507, "Language deleted."
*/
exec sp_getmessage 17507, @msg output
print @msg
return (0)

clean_all:


	return (1)
go
exec sp_procxmode 'sp_droplanguage', 'anymode'
go
grant execute on sp_droplanguage to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setlangalias')
begin
	drop procedure sp_setlangalias
end
go
print "Installing sp_setlangalias"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */

/*
** Messages for "sp_setlangalias"       17810
**
** 17201, "'%1!' is not an official language name from Syslanguages."
** 17240, "'" + @alias + "' is not a valid name." 
** 17260, "Can't run %1! from within a transaction."
** 17253, "'%1!' alias already exists in Syslanguages."
** 17810, "Language alias not changed."
** 17811, "Language alias reset."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18775, "Unable to find a language entry with language name '%1!' and language id '%2!'."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_setlangalias 
@language varchar(255),
@alias varchar(255)
as

declare @msg varchar(1024)

declare @returncode	int 
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @maxlen	  	int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_setlangalias', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  Check to see that the @alias is valid.
*/
select @maxlen = length from syscolumns
	where id = object_id("syslanguages") and name = "alias"

if (char_length(@alias) > @maxlen)
begin
     	/*
        ** 17240, "'" + @alias + "' is not a valid name."
	*/
        raiserror 17240, @alias
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
	raiserror 17260, "sp_setlangalias"
        return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*  Check to see if the language exists. */
select @returncode = 0
execute @returncode = sp_validlang @language
if @returncode != 0
begin
	/*
	** 17201, "'%1!' is not an official language name from Syslanguages."
	*/
	raiserror 17201, @language
	return 1
end

/*  Check to see if the alias exists. */
select @returncode = 0
execute @returncode = sp_validaltlang @alias
if @returncode = 0
begin
	/*
	** 17253, "'%1!' alias already exists in Syslanguages."
	*/
	raiserror 17253, @alias
	return 1
end



/* Reset the alternate language name. */
update master.dbo.syslanguages 
	set alias = @alias
		where name = @language

/* If the update failed, say so. */
if (@@error != 0)
begin
	/*
	** 17810, "Language alias not changed."
	*/
	raiserror 17810
	goto clean_all
end



/*
** 17811, "Language alias reset."
*/
exec sp_getmessage 17811, @msg output
print @msg
return (0)

clean_all:

	return (1)

go
exec sp_procxmode 'sp_setlangalias', 'anymode'
go
grant execute on sp_setlangalias to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_bindefault')
begin
	drop procedure sp_bindefault
end
go
print "Installing sp_bindefault"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/bindefault */

/*
** Messages for "sp_bindefault"         17340
**
** 17340, "Default and table or usertype must be in 'current' database."
** 17341, "Usage: bindefault defaultname, objectname [, 'futureonly']"
** 17342, "No such default exists.  You must create the default first."
** 17343, "You can't bind a default to a timestamp datatype column."
** 17344, "You do not own a column of that name."
** 17345, "Default bound to column."
** 17346, "You do not own a datatype of that name."
** 17347, "Default bound to datatype."
** 17348, "The new default has been bound to columns(s) of the specified user datatype."
** 17349, "You cannot bind a declared default. The default must be created using create default."
** 17753, "The column already has a default. Bind disallowed."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
** 19358, "You cannot bind a default to a computed column."
*/ 

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_bindefault
@defname varchar(767),			/* name of the default */
@objname varchar(511),			/* table or usertype name */
@futureonly varchar(15) = NULL		/* flag to indicate extent of binding */
as

declare @futurevalue varchar(15)	/* the value of @futureonly that causes
					** the binding to be limited */
declare @msg   varchar(1024)
declare @returncode int                 /* return from ad_hoc_audit builtin */
declare	@eventnum int		/* event number for bind default auditing */
declare	@mod_ok int		/* successful bind default auditing  */
declare	@mod_fail int		/* failure bind default auditing  */
declare @maxobjlen	int		/* get the length of sysobject.name from syscolumns */
declare @maxuserlen	int		/* get the length of sysusers.name from syscolumns */
declare @maxtotlen	int		/* get the Total length of sysobjects.name + sysusers.name*/


declare @rows_selected int
declare @tmp int

select	@eventnum = 6		/* event number for unbind default */
select	@mod_ok = 1		
select	@mod_fail = 2		
declare @dbname varchar(255)



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

select @futurevalue = "futureonly"	/* initialize @futurevalue */

/*
**  When a default or rule is bound to a user-defined datatype, it is also
**  bound, by default, to any columns of the user datatype that are currently
**  using the existing default or rule as their default or rule.  This default
**  action may be overridden by setting @futureonly = @futurevalue when the
**  procedure is invoked.  In this case existing columns with the user
**  datatype won't have their existing default or rule changed.
*/

/*
**  Check to see that the object names are local to the current database.
*/
if (@objname like "%.%.%")
   or
   (@defname like "%.%.%" and
	substring(@defname, 1, charindex(".", @defname) - 1) != db_name())
begin
	/*
	** 17340, "Default and table or usertype must be in 'current' database."
	*/
	raiserror 17340	
	return (1)
end

/*
**  Check that the @futureonly argument, if supplied, is correct.
*/
if (@futureonly is not null)
begin
	if (@futureonly != @futurevalue)
	begin
		/*
		** 17341, "Usage: bindefault defaultname, objectname [, 'futureonly']"
		*/
		raiserror 17341
		return (1)
	end
end

/*
**  Check to see that the default exists and get it's id.
*/
if not exists (select id
		from sysobjects
	where id = object_id(@defname)
		and sysstat & 7 = 6)		/* default object */
begin
	/*
	** 17342, "No such default exists.  You must create the default first."
	*/
	raiserror 17342
	return (1)
end

/*
** Check to see that the default is not of declared type
*/

if exists (select * from sysprocedures
		where id = object_id(@defname)
		and sequence = 0
		and status & 4096 = 4096)
begin
	/*
	** 17349, "You cannot bind a declared default. The default must be created \
using create default."
	*/
	raiserror 17349
	return (1)
end

/*
**  If @objname is of the form tab.col then we are binding to a column.
**  Otherwise its a datatype.  In the column case, we need to extract
**  and verify the table and column names and make sure the user owns
**  the table that is getting the default bound.
*/
if @objname like "%.%"
begin
	declare @tabname varchar(255)		/* name of table */
	declare @colname varchar(255)		/* name of column */
	select @maxobjlen = length from syscolumns
	where id = object_id("sysobjects") and name = "name"
	select @maxuserlen = length from syscolumns
	where id = object_id("sysusers") and name = "name"
	select @maxtotlen = (@maxobjlen + @maxuserlen) + 1


	/*
	**  Get the table name out.
	*/
	select @tabname = substring(@objname, 1, charindex(".", @objname) - 1)
	select @colname = substring(@objname, charindex(".", @objname) + 1, @maxtotlen)

	/*
	**  If the column type is timestamp, disallow the bind.
	**  Defaults can't be bound to timestamp columns.
	*/
	if exists (select *
			from sysobjects o, syscolumns c
		where c.id = object_id(@tabname)
			and c.name = @colname
			and c.name = @colname
			and o.id = object_id(@tabname)
			and o.sysstat & 7 = 3
			and c.usertype = 80)
	begin
		/*
		** 17343, "You can't bind a default to a timestamp datatype column."
		*/
		raiserror 17343
		return (1)
	end

	/* 
	** Disallow binding defaults on computed columns
	*/
	if exists(select 1 from syscolumns c
			where c.id = object_id(@tabname)
			and c.name = @colname	
			and c.status2 & 16 = 16)
	begin
		/*
		** 19358, "You cannot bind a default to a computed column."
		*/
		raiserror 19358
		return (1)
	end

	/*
	** If the column already has a default, then disallow the bind
	*/
	if exists (select * from syscolumns c
			where c.id = object_id(@tabname)
			and c.name = @colname
			and c.cdefault != 0)
	begin
		/*
		** 17753, "The column already has a default. Bind disallowed."
		*/
		raiserror 17753
		return (1)
	end

	begin transaction
	update syscolumns
		set cdefault = object_id(@defname)
			from syscolumns, sysobjects
		where syscolumns.id = object_id(@tabname)
			and syscolumns.name = @colname
			and sysobjects.id = object_id(@tabname)
			and uid = user_id()
			and sysobjects.sysstat & 7 = 3      /* user table */

	/*
	**  Did the bind happen?
	*/
	if @@rowcount != 1
	begin
		/*
		** 17344, "You do not own a column of that name."
		*/
		/* Audit the failure to bind a default */

		rollback transaction

        	select @returncode =
        	ad_hoc_audit (@eventnum , @mod_fail, @defname, db_name(), 
			@tabname, user_name(), 0, object_id(@tabname)

			)
		raiserror 17344
		return (1)
	end

	/* Audit the successful permission to bind a default */
        select @returncode =
        ad_hoc_audit (@eventnum, @mod_ok, @defname, db_name(), 
			@tabname, user_name(), 0, object_id(@tabname)

			)
	if (@returncode != 0)
	begin
		rollback transaction
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
		raiserror 18293, @eventnum 
		return (1)
	end
		
	commit transaction
	/*
	**  Since binding a default is a schema change, update schema count
	**  for the object in the sysobjects table.
	*/

	/* 
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	if (schema_inc(object_id(@tabname), 0) != 1)
	begin
		/*
		** 17763, "The execution of the stored procedure '%1!'
		**         in database '%2!' was aborted because there
		**         was an error in updating the column
		**         schemacnt in sysobjects."
		*/
		select @dbname = db_name()
		raiserror 17763, "sp_bindefault", @dbname
		rollback transaction rs_logexec
		return(1)
	end

	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_bindefault", @dbname
		
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17345, "Default bound to column."
	*/
	exec sp_getmessage 17345, @msg output
	print @msg
end
else
begin
	/*
	**  We're binding to a user type.  In this case, the @objname
	**  is really the name of the user datatype.
	**  When we bind to a user type, any existing columns get changed
	**  to the new binding unless they set the
	**  @futureonly parameter to @futurevalue.
	*/
	/*
	**  Get the current default for the datatype.
	*/
	if not exists (select tdefault
			from systypes
			where name = @objname
				and uid = user_id() and usertype > 100)
	begin
		/*
		** 17346, "You do not own a datatype of that name."
		*/

		/* Audit the failure to bind a default */
        	select @returncode =
        	ad_hoc_audit (@eventnum, @mod_fail, @defname, db_name(), 
			@objname, user_name(), 0, object_id(@objname)

			)
		raiserror 17346
		return (1)
	end

	/* Audit the successful permission to bind a default */
        select @returncode =
        ad_hoc_audit (@eventnum, @mod_ok, @defname, db_name(), 
		@objname, user_name(), 0, object_id(@objname)

		)
	if (@returncode != 0)
	begin
		/* 	AUDIT_CHANGE	
		**	Bind auditing has failed due to internal error contact 
		**	your SSO 
		*/
		print "Bind auditing has failed due to internal error contact SSO user"
		return (1)
	end

	/* 
	** This transaction also writes a log record for
	** replicating the invocation of this procedure. If
	** logexec() fails, the transaction is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and
	**  is used by Replication Server.
	*/
	begin transaction rs_logexec

	update systypes
		set tdefault = object_id(@defname)
			from systypes
		where name = @objname
			and uid = user_id()
			and usertype > 100


	/*
	** 17347, "Default bound to datatype."
	*/
	exec sp_getmessage 17347, @msg output
	print @msg

	/*
	**  Now see if there are any columns with the usertype that
	**  need the new binding.
	*/

	select @rows_selected = 0
	if isnull(@futureonly, "") != @futurevalue
	begin
		select @rows_selected = count(distinct syscolumns.id)
				from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
		if (@rows_selected > 0)
		begin
			/*
			**  Update the table schema to indicate that something
			**  has changed in the table's schema.
			*/
			select @tmp = sum(schema_inc(s.id, 0))
				from sysobjects s
				where exists 
					(select 1 
					from syscolumns, systypes
					where syscolumns.usertype = systypes.usertype
					and syscolumns.id = s.id
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id())

			if (@rows_selected != @tmp)
			begin
				/*
				** 17763, "The execution of the stored procedure '%1!'
				**         in database '%2!' was aborted because there
				**         was an error in updating the column
				**         schemacnt in sysobjects."
				*/
				select @dbname = db_name()
				raiserror 17763, "sp_bindefault", @dbname
				rollback transaction rs_logexec
				return(1)
			end
 
			/*
			**  Update syscolumns with new binding.
			*/
			update syscolumns
				set cdefault = systypes.tdefault
				from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
				and systypes.name = @objname
				and systypes.usertype > 100
				and systypes.uid = user_id()
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure
		**         '%1!' in database '%2!' was aborted
		**	    because there was an error in writing
		**	    the replication log record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_bindefault", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17348, "The new default has been bound to columns(s) of the specified user datatype."
	*/
	exec sp_getmessage 17348, @msg output
	print @msg

end

return (0)
go
exec sp_procxmode 'sp_bindefault', 'anymode'
go
grant execute on sp_bindefault to public
go
exec sp_procxmode 'sp_bindefault', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_bindrule')
begin
	drop procedure sp_bindrule
end
go
print "Installing sp_bindrule"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/bindrule */

/*
** Messages for "sp_bindrule"           17350
**
** 17344, "You do not own a column of that name." 
** 17346, "You do not own a datatype of that name." 
** 17350, "Rule and table or usertype must be in 'current' database."
** 17351, "Usage: bindrule rulename, objectname [, 'futureonly']"
** 17352, "No such rule exists.  You must create the rule first."
** 17353, "You can't bind a rule to a text, image, unitext, off-row Java clas, or timestamp datatype column."
** 17354, "Rule bound to table column."
** 17355, "You can't bind a rule to a text, image, unitext, or timestamp datatype."
** 17356, "Rule bound to datatype."
** 17357, "The new rule has been bound to column(s) of the specified user datatype."
** 17358, "You cannot bind a declared constraint. The rule must be created using create rule."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
** 17359, "You cannot bind a rule to a virtual computed column."
** 19359, "You cannot bind a rule to a function-based index key."
*/


/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_bindrule
@rulename varchar(767),			/* name of the rule */
@objname varchar(511),			/* table or usertype name */
@futureonly varchar(15) = NULL		/* column name */
as

declare @futurevalue varchar(15)	/* the value of @futureonly that causes
					** the binding to be limited */
declare @status tinyint			/* column status */
declare @colid smallint			/* column id */
declare @msg varchar(1024)
declare @returncode int                 /* return from ad_hoc_audit builtin */
declare	@eventnum int		/* event number for bind default auditing */
declare	@mod_ok int		/* successful bind default auditing  */
declare	@mod_fail int		/* failure bind default auditing  */
declare @maxobjlen	int		/* get the length of sysobject.name from syscolumns */
declare @maxuserlen	int		/* get the length of sysusers.name from syscolumns */
declare @maxtotlen	int		/* get the Total length of sysobjects.name + sysusers.name*/

select	@eventnum = 8		/* event number for bind rule */
select	@mod_ok = 1		
select	@mod_fail = 2		
declare @dbname varchar(255)
declare @tmp int
declare @rows_selected int

declare	@new_binding	int	/* 0 - new rule was not bound to columns of 
				**     user's datatype.
				** 1 - new rule was bound to columns of the
				**     user's datatype.
				*/
declare @access_rule	int	/* 0        - not an access rule.
				** 16777216 - is an access rule. This is
				** the bit in sysobjects.sysstat2 that
				** marks an access_rule.
				*/
declare @dbcc_dbid	int	/* Database id of updated objects */
declare @obj_id		int	/* Object id of updated objects */

select @new_binding = 0

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

select @futurevalue = "futureonly"	/* initialize @futurevalue */

/*
**  When a default or rule is bound to a user-defined datatype, it is also
**  bound, by default, to any columns of the user datatype that are currently
**  using the existing default or rule as their default or rule.  This default
**  action may be overridden by setting @futureonly = @futurevalue when the
**  procedure is invoked.  In this case existing columns with the user
**  datatype won't have their existing default or rule changed.
*/

/*
**  Check to see that the object names are local to the current database.
*/
if (@objname like "%.%.%")
   or
   (@rulename like "%.%.%" and
	substring(@rulename, 1, charindex(".", @rulename) - 1) != db_name())
begin
	/*
	** 17350, "Rule and table or usertype must be in 'current' database."
	*/
	raiserror 17350
	return (1)
end

/*
**  Check that the @futureonly argument, if supplied, is correct.
*/
if (@futureonly is not null)
begin
	if (@futureonly != @futurevalue)
	begin
		/*
		** 17351, "Usage: bindrule rulename, objectname [, 'futureonly']"
		*/
		raiserror 17351
		return (1)
	end
end

/*
**  Check to see that the rule exists and get it's id.
*/
if not exists (select id
	from sysobjects
where id = object_id(@rulename)
	and sysstat & 7 = 7)		/* rule object */

begin
	/*
	** 17352, "No such rule exists.  You must create the rule first."
	*/
	raiserror 17352
	return (1)
end

/* Check for access-rule: status bit 0x01000000 (16777216)  is set */
select @access_rule = sysstat2 & 16777216
	from sysobjects
where id = object_id(@rulename)
	and sysstat & 7 = 7		/* rule object */

/*
** Check to see that the rule is not of declared type
*/

if exists (select * from sysprocedures
		where id = object_id(@rulename)
		and sequence = 0
		and status & 4096 = 4096)
begin
	/*
	** 17358, "You cannot bind a declared constraint. The rule must be created \
using create rule."
	*/
	raiserror 17358
	return (1)
end

/*
**  If @objname is of the form tab.col then we are binding to a column.
**  Otherwise its a datatype.  In the column case, we need to extract
**  and verify the table and column names and make sure the user owns
**  the table that is getting the rule bound.
*/
if @objname like "%.%"
begin
	declare @tabname varchar(255)		/* name of table */
	declare @colname varchar(255)		/* name of column */
	select @maxobjlen = length from syscolumns
	where id = object_id("sysobjects") and name = "name"
	select @maxuserlen = length from syscolumns
	where id = object_id("sysusers") and name = "name"
	select @maxtotlen = (@maxobjlen + @maxuserlen) + 1

	/*
	**  Get the table name out.
	*/
	select @tabname = substring(@objname, 1, charindex(".", @objname) - 1)
	select @colname = substring(@objname, charindex(".", @objname) + 1, @maxtotlen)

	/*
	**  If the column type is image, text, unitext, off-row Java class,
	**  or timestamp, disallow the bind. Rules can't be bound to image, 
	**  text, unitext, off-row Java class, or timestamp columns.
	**  The qualification to check for types is a little strange because
	**  text and image are real, basic data types while timestamp is not.
	**  Timestamp is really a binary.  The types are checked in case
	**  there is a user-defined datatype that is an image or text.
	**  User-defined datatypes mapping to timestamp are not allowed
	**  by sp_addtype.
	*/
	if exists (select *
			from sysobjects o, syscolumns c
		where c.id = object_id(@tabname)
			and c.name = @colname
			and c.name = @colname
			and o.id = object_id(@tabname)
			and o.sysstat & 7 = 3
			and (c.type in (35, 34, 174) or c.usertype = 80
			     or (c.type = 36 and c.xstatus & 1 != 1)))
	begin
		/*
		** 17353, "You can't bind a rule to a text, image, unitext, off-row Java class, or timestamp datatype column."
		*/
		raiserror 17353
		return (1)
	end

	/*
	** Cannot bind a rule to a virtual computed column. 
	*/
	if exists (select 1 from syscolumns c 
			where c.id = object_id(@tabname)
			and c.name = @colname
			and c.status2 & 16 = 16
			and c.status2 & 32 != 32)
	begin
		/*
		** 17359, "You cannot bind a rule to a virtual computed column."
		*/
		raiserror 17359
		return (1)
	end

	/*
	** Cannot bind a rule to a function-based index key
	*/
	if exists (select 1 from syscolumns c 
			where c.id = object_id(@tabname)
			and c.name = @colname
			and c.status3 & 1 = 1) 
	begin
		/*
		** 19359, "You cannot bind a rule to a function-based index key."
		*/
		raiserror 19359
		return (1)
	end

	/*
	** If status of the column does not reflect having more than one
	** check constraint (declared rule), then update the status if
	** it has additional constraint(s).
	*/

	select @status = status, @colid = colid from syscolumns, sysobjects
		where syscolumns.id = object_id(@tabname)
			and syscolumns.name = @colname
			and sysobjects.id = object_id(@tabname)
			and uid = user_id()
			and sysobjects.sysstat & 7 = 3      /* user table */

	/*
	**  Did the bind happen?
	*/
	if @@rowcount != 1
	begin
		/*
		** 17344, "You do not own a column of that name." 
		*/
		/* Audit the failure to bind a rule */
        	select @returncode =
        	ad_hoc_audit (@eventnum, @mod_fail, @rulename, db_name(), 
			@tabname, user_name(), 0, object_id(@tabname)
			)
		raiserror 17344
		return (1)
	end

/* get the security label of the object */

	/* Audit the succesful permission to bind a rule */
	select @returncode =
	ad_hoc_audit (@eventnum, @mod_ok, @rulename, db_name(), 
		@tabname, user_name(), 0, object_id(@tabname)
		)
	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
       	raiserror 18293, @eventnum
		return (1)
	end

	if (@access_rule > 0)
	begin
		update syscolumns
		       set accessrule = object_id(@rulename)
			       from syscolumns, sysobjects
		       where syscolumns.id = object_id(@tabname)
			     and syscolumns.name = @colname
			     and sysobjects.id = object_id(@tabname)
			     and uid = user_id()
			     and sysobjects.sysstat & 7 = 3      /* user table */
	end
	else
	begin
		if @status & 16 = 0 and
		   exists (select * from sysconstraints c, sysobjects o
				where c.tableid = object_id(@tabname)
					and c.colid = @colid
					and o.id = c.constrid
					and o.sysstat & 7 = 7)
		begin
			update syscolumns
			       set domain = object_id(@rulename),
			       status = syscolumns.status | 16
				       from syscolumns, sysobjects
			       where syscolumns.id = object_id(@tabname)
				     and syscolumns.name = @colname
				     and sysobjects.id = object_id(@tabname)
				     and uid = user_id()
				     and sysobjects.sysstat & 7 = 3 /* user table */
		end
		else
		begin
			update syscolumns
			       set domain = object_id(@rulename)
				       from syscolumns, sysobjects
			       where syscolumns.id = object_id(@tabname)
				     and syscolumns.name = @colname
				     and sysobjects.id = object_id(@tabname)
				     and uid = user_id()
				     and sysobjects.sysstat & 7 = 3      /* user table */
		end
	end
	/*
	**  Since binding a rule is a schema change, update schema count
	**  for the object in the sysobjects table.
	*/

	/* 
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	if (schema_inc(object_id(@tabname), 0) != 1)
	begin
		/*
		** 17763, "The execution of the stored procedure '%1!'
		**         in database '%2!' was aborted because there
		**         was an error in updating the column
		**         schemacnt in sysobjects."
		*/
		select @dbname = db_name()
		raiserror 17763, "sp_bindrule", @dbname
		rollback transaction rs_logexec
		return(1)
	end

	update sysobjects
	set sysstat2 = sysstat2 | @access_rule
	from sysobjects
	where id = object_id(@tabname)
	and uid = user_id()

	/*
	** If we bound an access rule to the column, we must make sure
	** that the DES is updated in the cache 
	*/
	if @access_rule > 0
	begin
		select @tmp = set_accessrule(object_id(@tabname), 1)
		if (@tmp = -1)
		begin
			rollback transaction rs_logexec
/* FGAC_RESOLVE: Add a message */
			return 1
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_bindrule", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17354, "Rule bound to table column."
	*/
	exec sp_getmessage 17354, @msg output
	print @msg

end
else
begin
	/*
	**  We're binding to a user type.  In this case, the @objname
	**  is really the name of the user datatype.
	**  When we bind to a user type, any existing columns get changed
	**  to the new binding unless their current binding is not equal
	**  to the current binding for the usertype or if they set the
	**  @futureonly parameter to @futurevalue.
	*/
	declare @oldrule int			/* current rule for type */

	/*
	**  If the column type is image, text, unitext, or timestamp, 
	**  disallow the bind.
	**  Rules can't be bound to image, unitext or text columns.
	*/
	if exists (select *
			from systypes
			where name = @objname
			and (type in (35, 34, 174) or usertype = 80))
	begin
		/*
		** 17355, "You can't bind a rule to a text, unitext, image, or timestamp datatype."
		*/
		raiserror 17355
		return (1)
	end

        if  not exists (select * from systypes
			where name = @objname
			and uid = user_id()
			and usertype > 100 )
        begin
                /*
                ** 17346, "You do not own a datatype of that name."
                */
                /* Audit the failure to bind a rule */
                select @returncode =
                       ad_hoc_audit (@eventnum, @mod_fail, @rulename,
                       db_name(), @objname, user_name(), 0,
                       object_id(@objname)
                        )
                        raiserror 17346
                        return (1)
        end


	/*
	**  Get the current rule for the datatype.
	*/
	if (@access_rule = 0)
	begin
		select @oldrule = domain
		       from systypes
		       where name = @objname
		       and uid = user_id()
		       and usertype > 100
	end
	else
	begin
		select @oldrule = accessrule
			from systypes
			where name = @objname
			and uid = user_id()
			and usertype > 100
	end

/* get the security label of the object */
	/* Audit the successful permission to bind a rule */
	select @returncode =
	ad_hoc_audit ( @eventnum, @mod_ok, @rulename, db_name(), 
		@objname, user_name(), 0, object_id(@objname)
		)
	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
       	raiserror 18293, @eventnum
		return (1)
	end

	/*
	** This transaction also writes a log record for
	** replicating the invocation of this procedure. If
	** logexec() fails, the transaction is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is
	** used by Replication Server.
	*/
	begin transaction rs_logexec

	if (@access_rule > 0)
	begin
		update systypes
		       set accessrule = object_id(@rulename)
			   from systypes
		       where name = @objname
			     and uid = user_id()
			     and usertype > 100
	end
	else
	begin
		update systypes
		       set domain = object_id(@rulename)
			   from systypes
		       where name = @objname
			     and uid = user_id()
			     and usertype > 100
        end

	/*
	** 17356, "Rule bound to datatype."
	*/
	exec sp_getmessage 17356, @msg output
	print @msg


	/*
	**  Now see if there are any columns with the usertype that
	**  need the new binding.
	*/

	select @rows_selected = 0
	if isnull(@futureonly, "") != @futurevalue
	begin
		select @rows_selected = count(distinct syscolumns.id)
			from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and ((syscolumns.domain = @oldrule
						or  syscolumns.domain = 0 )
                                          or (syscolumns.accessrule = @oldrule
						or syscolumns.accessrule is NULL
						or syscolumns.accessrule = 0))
			

		if (@rows_selected > 0)
		begin
			/*
			**  Update the table schema to indicate that something
			**  has changed in the table's schema.
			*/

                	select @tmp = sum(schema_inc(s.id, 0))
                                from sysobjects s
                                where exists
                                        (select 1
					 from syscolumns, systypes
					 where s.id = syscolumns.id
					 and syscolumns.usertype = systypes.usertype
					 and systypes.name = @objname
					 and systypes.usertype > 100
					 and systypes.uid = user_id()
					 and ((syscolumns.domain = @oldrule
						or  syscolumns.domain = 0 )
                                          or (syscolumns.accessrule = @oldrule
						or syscolumns.accessrule is NULL
						or syscolumns.accessrule = 0)))
			

			if (@rows_selected != @tmp)
			begin
				/*
				** 17763, "The execution of the stored procedure '%1!'
				**         in database '%2!' was aborted because there
				**         was an error in updating the column
				**         schemacnt in sysobjects."
				*/
				select @dbname = db_name()
				raiserror 17763, "sp_bindrule", @dbname
				rollback transaction rs_logexec
				return(1)
			end

			if (@access_rule > 0)
			begin
				update sysobjects
			       	set sysstat2 = sysstat2 | @access_rule
					from sysobjects s
					where exists
					(select 1
					 from syscolumns, systypes
			       		 where s.id = syscolumns.id
				    	 and syscolumns.usertype = systypes.usertype
				    	 and systypes.name = @objname
				    	 and systypes.usertype > 100
				    	 and systypes.uid = user_id()
				    	 and (syscolumns.accessrule = @oldrule
				    	 or syscolumns.accessrule = 0 
				    	 or syscolumns.accessrule is NULL))

				/*
				**  Update syscolumns with new binding.
				*/
				update syscolumns
			       	set accessrule = systypes.accessrule
				       	from syscolumns, systypes
			       	where syscolumns.usertype = systypes.usertype
				     	and systypes.name = @objname
				     	and systypes.usertype > 100
				     	and systypes.uid = user_id()
				     	and (syscolumns.accessrule = @oldrule
				     	or  syscolumns.accessrule = 0 
				     	or  syscolumns.accessrule is NULL )
			end
			else
			begin
				update sysobjects
			       	set sysstat2 = sysstat2 | @access_rule
					from sysobjects s
					where exists
					(select 1
					 from syscolumns, systypes
			       		 where s.id = syscolumns.id
				    	 and syscolumns.usertype = systypes.usertype
				    	 and systypes.name = @objname
				    	 and systypes.usertype > 100
				    	 and systypes.uid = user_id()
				    	 and (syscolumns.domain = @oldrule
				    	 or syscolumns.domain = 0))

				/*
				**  Update syscolumns with new binding.
				*/
				update syscolumns
			       	set domain = systypes.domain
				       	from syscolumns, systypes
			       	where syscolumns.usertype = systypes.usertype
				     	and systypes.name = @objname
				     	and systypes.usertype > 100
				     	and systypes.uid = user_id()
				     	and (syscolumns.domain = @oldrule
				     	or  syscolumns.domain = 0)
			end

			/*
			** Note that new binding has occurred.
			*/
			select @new_binding = 1

			/*
			** If we bound an access rule to a column of one or 
			** more tables, we must make sure that the DESs for these
			** tables flushed from the cache and re-read to pick up
			** the new sysstat2 value.
			*/
			if @access_rule > 0
			begin
				select @dbcc_dbid = db_id()

				declare tab_cursor cursor for
			    	select distinct sysobjects.id 
			    	from sysobjects, syscolumns
			    	where sysobjects.id = syscolumns.id
			    	and syscolumns.accessrule = object_id(@rulename)

				open tab_cursor
	
				fetch tab_cursor into @obj_id

				while (@@sqlstatus = 0)
				begin
					select @tmp = set_accessrule(@obj_id, 1)
/* FGAC RESOLVE -- Add a new messsage */
					if (@tmp = -1)
					begin
						rollback transaction rs_logexec
						close tab_cursor
						deallocate cursor tab_cursor
						return (1)
					end
							
					fetch tab_cursor into @obj_id
				end

				close tab_cursor
				deallocate cursor tab_cursor
			end
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure
		**         '%1!' in database '%2!' was aborted
		**	    because there was an error in writing
		**	    the replication log record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_bindrule", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** If a new binding has occurred, display message 17357.
	*/
	if (@new_binding = 1)
	begin
		/*
		** 17357, "The new rule has been bound to column(s) of the
		**	   specified user datatype."
		*/
		exec sp_getmessage 17357, @msg output
		print @msg
	end
end

return (0)

go
exec sp_procxmode 'sp_bindrule', 'anymode'
go
grant execute on sp_bindrule to public
go
exec sp_procxmode 'sp_bindrule', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_changedbowner')
begin
	drop procedure sp_changedbowner
end
go
print "Installing sp_changedbowner"
go

/*
** Generated by spgenmsgs.pl on Mon Nov  6 11:22:17 2006 
*/
/*
** raiserror Messages for changedbowner [Total 5]
**
** 17231, "No login with the specified name exists."
** 17361, "Can't change the owner of the master, model, tempdb or sybsystemprocs database."
** 17362, "The proposed new db owner already is a user in the database or owns the database."
** 17363, "The proposed new db owner already is aliased in the database."
** 17368, "Your curwrite label needs to be set correctly before you attempt to change the database owner."

*/
/*
** sp_getmessage Messages for changedbowner [Total 5]
**
** 17364, "The dependent aliases were mapped to the new dbo."
** 17365, "The dependent aliases were dropped."
** 17366, "Database owner changed."
** 17431, "true"
** 19575, "Warning: The stored procedure '%1!' may not execute; check database owner's threshold authorization."
*/
/*
** End spgenmsgs.pl output.
*/
/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/changedbowner */
 
/*
** Messages for "sp_changedbowner"      17360
**
** 17231, "No login with the specified name exists."
** 17361, "Can't change the owner of the master, model, tempdb or sybsystemprocs  database."
** 17362, "The proposed new db owner already is a user in the database or owns the database."
** 17363, "The proposed new db owner already is aliased in the database."
** 17364, "The dependent aliases were mapped to the new dbo."
** 17365, "The dependent aliases were dropped."
** 17366, "Database owner changed."
** 17431, "true"
** 17368, "Your curwrite label needs to be set correctly before you attempt to change the database owner."
** 19857, "Can't change the owner of the master, model, sybsystemprocs, tempdb or local system temporary databases."
*/

create procedure sp_changedbowner --{
@loginame varchar(30),         /* login to become dbo */
@map      varchar(10) = NULL   /* True to map aliases, else drop  */
as

declare @suid		int
declare @oldsuid	int
declare @msg		varchar(1024)
declare @true		varchar(10)
declare @dbname		varchar(255)
declare @HA_CERTIFIED	tinyint   /* Is the SP HA certified ? */
declare @retstat	int

declare @currauth	varbinary(255)
declare @proc_name	varchar(255)
declare @count		int
declare @coord_override	int

select @HA_CERTIFIED = 0


/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_changedbowner', @HA_CERTIFIED
if (@retstat != 0)
	return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
**  Can't change the owner of the master, model, tempdb or sybsystemprocs  database.
*/
if db_name() in ( "master", "tempdb", "model", "sybsystemprocs" ) 
begin
	if @@clustermode = "shared disk cluster"
	begin
		/*
		** 19857, "Can't change the owner of the master, model, 
		** sybsystemprocs, tempdb or local system temporary 
		** databases."
		*/
		raiserror 19857 
	end

	else
	begin
		/*
		** 17361, "Can't change the owner of the master, model, 
		** tempdb or sybsystemprocs  database."
		*/
		raiserror 17361
	end

	return(1)
end

/*
** In SDC, can't change the owner of the local system tempdb either.
*/
if @@clustermode = "shared disk cluster"  
begin
	declare @localsystempdbbit int
	select @localsystempdbbit = number
		from master.dbo.spt_values
		where type = "D3" and name = "local system temp db"

   	if exists (select 1 from master.dbo.sysdatabases 
			where dbid = db_id() and 
		(status3 & @localsystempdbbit) = @localsystempdbbit)
	begin
		/*
		** 19857, "Can't change the owner of the master, model, 
		** sybsystemprocs, tempdb or local system temporary 
		** databases."
		*/
		raiserror 19857 
		return(1)
	end
end

/*
**  Make sure that @loginame exists and has a login.
*/
select @suid = suid
	from master.dbo.syslogins
		where name = @loginame

if @suid is NULL
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return(1)
end

/*
**  Make sure that @loginame isn't already a user or alias in the database.
*/
if exists (select *
		from sysusers
			where suid = @suid)
begin
	/*
	** 17362, "The proposed new db owner already is a user in the database or owns the database."
	*/
	raiserror 17362
	return(1)
end
if exists (select *
		from sysalternates
			where suid = @suid)
begin
	/*
	** 17363, "The proposed new db owner already is aliased in the database."
	*/
	raiserror 17363
	return(1)
end

/* 
** find old (current) dbo's suid
*/
select @oldsuid = suid
	from sysusers
		where uid = 1

/*
** Allow IMDB/RDDB to be the coordinator of a multi-db transaction.
** We need this override because we are about to update current database
** and the master database in the same transaction.
*/
select @coord_override = 0
if exists (select * from master.dbo.sysdatabases
			where dbid = db_id()
			and durability != 1)
begin
	/* 
	** If the switch is not turned ON in session or serverwide, 
	** turn it ON and remember that we turned it ON here
	*/
	if (switchprop("allow_nondurable_db_as_coorddb") = 0)
	begin
		select @coord_override = 1
		set switch on allow_nondurable_db_as_coorddb 
			with override, no_info
	end
end

begin transaction

/*
**  Now change the suid of the owner of the database to the suid of @loginame.
*/
update sysusers
	set suid = @suid
		where uid = 1

/*
** if the user requested that aliases be mapped to new dbo, do that.
*/
/* 17431, "true" */
exec sp_getmessage 17431, @true out
if lower(@map) in ("true", @true)
begin

	if exists (select *
			from sysalternates
				where altsuid = @oldsuid)
	begin
		update sysalternates
			set altsuid = @suid
				where altsuid = @oldsuid

		/*
		** 17364, "The dependent aliases were mapped to the new dbo."
		*/
		exec sp_getmessage 17364, @msg output
		print @msg
	end
end
/* else drop the aliases to the old dbo */
else
begin

	if exists (select *
			from sysalternates
				where altsuid = @oldsuid)
	begin
		delete from sysalternates
			where altsuid = @oldsuid

		/*
		** 17365, "The dependent aliases were dropped."
		*/
		exec sp_getmessage 17365, @msg output
		print @msg
	end
end

/*
**  Reflect the new owner of the database in master.dbo.sysdatabases.
*/
update master.dbo.sysdatabases
	set suid = @suid
		where dbid = db_id()

/* Update owner of the associated thresholds in systhreshods table */
begin
         if exists (select * 
                         from systhresholds
                              where suid = @oldsuid)
         begin 
                 update systhresholds
                       set suid = @suid
                           where suid = @oldsuid
         end
end
	
commit transaction

/* Disable the override if we enabled it earlier */
if (@coord_override = 1)
begin
	select @coord_override = 0
	set switch off allow_nondurable_db_as_coorddb with no_info
end

/* 
** To check if the new owner has all the roles the "currauth" 
** specifies. If he does not have all the roles required, 
** this change may cause the stored procedure UN-EXECUTABLE 
** later when the threshold is crossed. So we raise a 
** warning error.
*/
begin
         declare auth_procname cursor
             for select currauth, proc_name from systhresholds
                  where suid = @suid
             for read only
         
         open auth_procname
         
         fetch auth_procname into @currauth, @proc_name
         while @@sqlstatus <> 2
		begin
			select @count = count(*)
			from master..syssrvroles a,
                           systhresholds b,
                           master.dbo.spt_values c
			where c.type = "P"
                           and c.number = a.srid
                           and c.low <= datalength(b.currauth)
                           and convert(tinyint, 
				substring(currauth, c.low, 1)) 
				& c.high != 0
                           and a.srid not in 
                                  ( select srid
                                    from master..sysloginroles
                                    where suid = @suid)

			/*
			** If the new dbo does not have all the 
			** roles specified in the current 
			** authorization bitmask "currauth",
			** we print an warning message 
			*/

			if @count > 0
			begin		
				/* 
				** 19575, "Warning: The stored 
				** procedure '%1!' may not execute; 
				** check database owner's threshold 
				** authorization."
				*/
				exec sp_getmessage 19575, @msg output
				print @msg, @proc_name
			end
			fetch  auth_procname into @currauth, @proc_name
		end
	close auth_procname
	deallocate cursor auth_procname
end

/*
** Update the dbinfo and dbtable uid fields for this database.
*/
select @dbname = db_name()
dbcc dbrepair(@dbname, "updowner")

/*
** 17366, "Database owner changed."
*/
exec sp_getmessage 17366, @msg output
print @msg

return (0)

--} /* End of create stored proc. */
go
exec sp_procxmode 'sp_changedbowner', 'anymode'
go
grant execute on sp_changedbowner to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_expandbitmap')
begin
	drop procedure syb_aux_expandbitmap
end
go
print "Installing syb_aux_expandbitmap"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */


create procedure syb_aux_expandbitmap
@colcount     smallint,			/* no of columns in the table */
@expandmap    varbinary(133) output      /* expanded column map with all 1's */
as

declare @colleft smallint  /* tracks number of columns left in the bit map */


/* 
** if the number of columns are less than 8, it is a special case because
** bit 0 is treated differently in the column bit map
*/
if (@colcount < 8)
begin
      if (@colcount = 1)
 	   select @expandmap = 0x02
      else if (@colcount = 2)
           select @expandmap = 0x06
      else if (@colcount = 3)
	   select @expandmap = 0x0e
      else if (@colcount = 4)
	   select @expandmap = 0x1e
      else if (@colcount = 5)
	   select @expandmap = 0x3e
      else if (@colcount = 6)
	   select @expandmap = 0x7e
      else if (@colcount = 7)
	   select @expandmap = 0xfe
      return
end

/*
** column count was more than 7, thus set up the bit map for the first byte
** and set the column left variable
*/
select @expandmap = 0xfe
select @colleft = @colcount - 7

/* 
** for chunk of 8 columns, set the bit map to all 1s for that byte
*/
while (@colleft >= 8)
begin
     select @expandmap = @expandmap + 0xff
     select @colleft = @colleft - 8
end

/*
** if no column left, return 
*/
if (@colleft = 0)
    return

/* 
** now the number of left columns has to be between 1 and 7. So setup
** the bit map for the last byte
*/
if (@colleft = 1)
     select @expandmap = @expandmap + 0x01
else if (@colleft = 2)
     select @expandmap = @expandmap + 0x03
else if (@colleft = 3)
     select @expandmap = @expandmap + 0x07
else if (@colleft = 4)
     select @expandmap = @expandmap + 0x0f
else if (@colleft = 5)
     select @expandmap = @expandmap + 0x1f
else if (@colleft = 6)
     select @expandmap = @expandmap + 0x3f
else if (@colleft = 7)
     select @expandmap = @expandmap + 0x7f

go
exec sp_procxmode 'syb_aux_expandbitmap', 'anymode'
go
grant execute on syb_aux_expandbitmap to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_privexor')
begin
	drop procedure syb_aux_privexor
end
go
print "Installing syb_aux_privexor"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */


create procedure syb_aux_privexor
@left_binary	varbinary (133),	       /* left operand for the subtract */
@right_binary	varbinary (133),        /* right operand for the subtract */	
@col_count	smallint,	       /* number of columns in the table */
@result_binary	varbinary (133) output  /* result of the subtract operation */
as

declare @loop_count tinyint        /* loop count for all 133 bytes in the varbinary */
declare @left_opr   tinyint	   /* integer representation of the left operand */
declare @right_opr  tinyint	   /* integer representation of the right operand */
declare @result_opr tinyint	   /* result of subtract operation */
declare @left_bin   varbinary (133) /* expanded with 1's left operand */
declare @loop_bound tinyint 	   /* stores the loop upper bound */
/*
** initialize the loop_count
*/
select @loop_count = 1

/* 
** initialize loop_bound
*/
select @loop_bound = @col_count/8 + 1

/* 
** check for boundary condition. If right operand is 0, there is nothing to subtract
*/
if (@right_binary = 0x00)
begin
      select @result_binary = @left_binary
      return
end

/*
** check for boundary condition. If both oerands are equal, the result has to be 0
*/
if ((@left_binary = 0x01) and (@right_binary = 0x01))
begin
      select @result_binary = 0x00
      return
end

/* 
** if the left oeprand is 0x01, the right operand can't be 0x01. Now we need to expand
** the left opernad in order to subtract correctly
*/
if (@left_binary = 0x01)
     exec sybsystemprocs.dbo.syb_aux_expandbitmap @col_count, @left_bin output
else
    select @left_bin = @left_binary

/*
** loop for all relevant bytes in the var binary operand 
*/
while (@loop_count <= @loop_bound)
begin
      select @left_opr = convert (tinyint, substring (@left_bin, @loop_count, 1))
      select @right_opr = convert (tinyint, substring (@right_binary, @loop_count, 1))

      /* do the binary operation */
      select @result_opr = @left_opr ^ @right_opr
      if (@loop_count = 1)
      begin
	   select @result_binary = convert (binary (1), @result_opr)
      end
      else
      begin
	   select @result_binary = @result_binary + convert (binary (1), @result_opr)
      end

      select @loop_count = @loop_count + 1
end
go
exec sp_procxmode 'syb_aux_privexor', 'anymode'
go
grant execute on syb_aux_privexor to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_privnots')
begin
	drop procedure syb_aux_privnots
end
go
print "Installing syb_aux_privnots"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */


create procedure syb_aux_privnots
@left_binary	varbinary (133),   	/* operand for the complement */
@col_count	smallint,  	  	/* number of columns in the table */
@result_binary	varbinary (133) output	/* result of the complement */
as

declare @loop_count tinyint		/* loop counter for 133 bytes in varbinary */
declare @left_opr   tinyint		/* integer represenation of a byte in left operand */
declare @right_opr  tinyint		/* integer representation of a byte in right opr */
declare @result_opr tinyint		/* result integer byte */
declare @expand_bin varbinary (133)	/* expanded bit map with all 1s */	
declare @temp_resbin varbinary (133)	/* transient value store for the result */
declare @loop_bound tinyint 	   /* stores the loop upper bound */


/*
** initialize the loop_count
*/

select @loop_count = 1

/* 
** initialize loop_bound
*/
select @loop_bound = @col_count/8 + 1

/* 
** boundary condition. If left operand is 0, then the NOT of that is all 1s
*/
if (@left_binary = 0x00) 
begin
      select @result_binary = 0x01
      return
end

/*
** if left operand is all 1s, then NOT of of it is all 0s
*/
if (@left_binary = 0x01)
begin
      select @result_binary = 0x00
      return
end

/*
** loop for each byte of 133 bytes varbinary operand
*/
while (@loop_count <= @loop_bound)
begin
      select @left_opr = convert (tinyint, substring (@left_binary, @loop_count, 1))
      
      select @result_opr = ~@left_opr /* complement the byte */


      /*
      ** first byte is treated differently as there is nothing to concatenate
      */
      if (@loop_count = 1)
      begin
	   select @result_opr = @result_opr & 0xfe  /* do this as bit 0 has a special
						       meaning. make it 0 */
	   select @temp_resbin = convert (binary (1), @result_opr)
      end
      else
      begin
	   select @temp_resbin = @temp_resbin + convert (binary (1), @result_opr)
      end

      select @loop_count = @loop_count + 1
end


/* need to zero out the unnecessary one's  */
exec sybsystemprocs.dbo.syb_aux_expandbitmap @col_count, @expand_bin output

select @loop_count = 1

/*
** the temp_resbin has 1's beyond number of columns. We need to zero them out
*/
while (@loop_count <= @loop_bound)
begin
      select @left_opr = convert (tinyint, substring (@temp_resbin, @loop_count, 1))
      select @right_opr = convert (tinyint, substring (@expand_bin, @loop_count, 1))
      select @result_opr = @left_opr & @right_opr

      if (@loop_count = 1)
      begin
	   select @result_binary = convert (binary (1), @result_opr)
      end
      else
      begin
	   select @result_binary = @result_binary + convert (binary (1), @result_opr)
      end

      select @loop_count = @loop_count + 1
end
go
exec sp_procxmode 'syb_aux_privnots', 'anymode'
go
grant execute on syb_aux_privnots to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_privsand')
begin
	drop procedure syb_aux_privsand
end
go
print "Installing syb_aux_privsand"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */


create procedure syb_aux_privsand
@left_binary	varbinary (32),	      /* left operand of AND */
@right_binary	varbinary (32),       /* right operand of AND */
@col_count	smallint,	      /* number of columns in the table */
@result_binary	varbinary (32) output /* result of ANDing */
as

declare @loop_count tinyint   	   /* loop counter for the 32 bytes in varbinary operand */
declare @left_opr   tinyint	   /* integer represenation of a byte in left opr */
declare @right_opr  tinyint	   /* integer represenation of a byte in right opr */
declare @result_opr tinyint	   /* result byte */
declare @left_bin   varbinary (32) /* expanded bit map of left operand */
declare @right_bin  varbinary (32) /* expanded bit map of right operand */
declare @loop_bound tinyint 	   /* stores the loop upper bound */

/*
** initialize the loop count
*/
select @loop_count = 1

/* 
** initialize loop_bound
*/
select @loop_bound = @col_count/8 + 1

/*
** boundary condition. If any of the operand is 0, the result will be zero 
*/
if ((@right_binary = 0x00) or (@left_binary = 0x00))
begin
      select @result_binary = 0x00
      return
end

/*
** boundary condition. If both operands are all 1's, return all 1's
*/

if ((@left_binary = 0x01) and (@right_binary = 0x01))
begin
      select @result_binary = 0x01
      return
end

/* 
** if left operand was all 1's, expand it into appropriate number of columns 
*/
if (@left_binary = 0x01)
     exec sybsystemprocs.dbo.syb_aux_expandbitmap @col_count, @left_bin output
else
     select @left_bin = @left_binary

/*
** if right operand was all 1's, expand it into appropriate number of columns 
*/

if (@right_binary = 0x01)
     exec sybsystemprocs.dbo.syb_aux_expandbitmap @col_count, @right_bin output
else
     select @right_bin = @right_binary


/*
** loop for each byte in the varbinary operand
*/
while (@loop_count <= @loop_bound)
begin
      select @left_opr = convert (tinyint, substring (@left_bin, @loop_count, 1))
      select @right_opr = convert (tinyint, substring (@right_bin, @loop_count, 1))

      /* bit wise ANDing. Note atmost only one of the operands might have been
         expanded to full 32 bytes. The extra 1s will ge zeroed out in the operation */

      select @result_opr = @left_opr & @right_opr

      /*
      ** first byte is treated differently as there is nothing to be appended 
      */
      if (@loop_count = 1)
      begin
	   select @result_binary = convert (binary (1), @result_opr)
      end
      else
      begin
	   select @result_binary = @result_binary + convert (binary (1), @result_opr)
      end

      select @loop_count = @loop_count + 1
end
go
exec sp_procxmode 'syb_aux_privsand', 'anymode'
go
grant execute on syb_aux_privsand to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_privunion')
begin
	drop procedure syb_aux_privunion
end
go
print "Installing syb_aux_privunion"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */


create procedure syb_aux_privunion
@left_binary	varbinary (133),        /* left operand of UNION operation */
@right_binary	varbinary (133),        /* right operand of UNION operation */
@col_count	smallint,  	  	/* number of columns in the table */
@result_binary	varbinary (133) output  /* operand to return the result into */
as

declare @loop_count tinyint   /* loop count for all 133 bytes in varbinary */
declare @left_opr   tinyint   /* integer representation of a byte in left operand */
declare @right_opr  tinyint   /* integer representation of a byte in right operand */
declare @result_opr tinyint   /* result of anding two bytes */
declare @loop_bound tinyint 	   /* stores the loop upper bound */

/* 
** initialize the loop count 
*/
select @loop_count = 1

/* 
** initialize loop_bound
*/
select @loop_bound = @col_count/8 + 1

/*
** check for boundary conditions. If any of the operand is all one's, the result
** will also be all ones
*/
if ((@left_binary = 0x01) or (@right_binary = 0x01))
begin
      select @result_binary = 0x01
      return
end
/*
** loop through all the bytes in the operand and compute the UNION (i.e OR) byte
** by byte 
*/

While (@loop_count <= @loop_bound)
begin
      select @left_opr = convert (tinyint, substring (@left_binary, @loop_count, 1))
      select @right_opr = convert (tinyint, substring (@right_binary, @loop_count, 1))
      select @result_opr = @left_opr | @right_opr

  
      if (@loop_count = 1)
      Begin
	   /* first bytes is treated differently, as there is nothing to 
           ** be concatenated 
	   */
	   select @result_binary = convert (binary (1), @result_opr)
      end
      else
      begin
	   /* 
	   ** concatenate the result from byte 2 onwards 
	   */
	   select @result_binary = @result_binary + convert (binary (1), @result_opr)
      end

      select @loop_count = @loop_count + 1
end
go
exec sp_procxmode 'syb_aux_privunion', 'anymode'
go
grant execute on syb_aux_privunion to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_colbit')
begin
	drop procedure syb_aux_colbit
end
go
print "Installing syb_aux_colbit"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure syb_aux_colbit (
@col_pos	smallint,
@columns	varbinary (133),
@result		tinyint output )
as

declare @which_byte	tinyint
declare @bit_offset	tinyint
declare @bitmap_byte	tinyint

/*
** check to see if the bit 0 is 1. If it is, then the privilege is 
** available on all columns 
*/

if (@columns = 0x01)
begin
	select @result = 1
	return 
end

select @result = 0
select @which_byte = (@col_pos)/8 
select @bit_offset = @col_pos - @which_byte * 8



/* get the byte of the bit map we are interested in */
select @bitmap_byte = convert (tinyint, substring (@columns, @which_byte + 1, 1))

if (@bit_offset = 0)
	select @result = @bitmap_byte & 0x01
else if (@bit_offset = 1)
	select @result = @bitmap_byte & 0x02
else if (@bit_offset = 2)
	select @result = @bitmap_byte & 0x04
else if (@bit_offset = 3)
	select @result = @bitmap_byte & 0x08
else if (@bit_offset = 4)
	select @result = @bitmap_byte & 0x10
else if (@bit_offset = 5)
	select @result = @bitmap_byte & 0x20
else if (@bit_offset = 6)
	select @result = @bitmap_byte & 0x40
else if (@bit_offset = 7)
	select @result = @bitmap_byte & 0x80

go
exec sp_procxmode 'syb_aux_colbit', 'anymode'
go
grant execute on syb_aux_colbit to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'syb_aux_printprivs')
begin
	drop procedure syb_aux_printprivs
end
go
print "Installing syb_aux_printprivs"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
**  syb_aux_printprivs
**
**  Parameters:
**	calledfrom_colpriv	- Is call made to print column privileges
**				  (or table privileges)
**	col_pos			- Id of column to print privileges for.
**	tab_priv		- Are there privileges on any table in column?
**	tab_priv_g		- Are there any grantable privileges?
**	col_priv		- Bit map of column privileges.
**	col_priv_g		- Bit map of grantable column privileges.
**	colprivileges		- Are column level privileges being processed?
**	grantable [output]	- "YES" if grantable privileges, "NO" otherwise.
**	is_printable [output]	- Is the privilege printable?
*/
create procedure syb_aux_printprivs (
	@calledfrom_colpriv	tinyint,
	@col_pos		smallint,
	@tab_priv		tinyint,
	@tab_priv_g		tinyint,
	@col_priv		varbinary (133),
	@col_priv_g		varbinary (133),
	@colprivileges		tinyint,
	@grantable		varchar (3) output,
        @is_printable		tinyint output)
as
     declare @bitset		tinyint
     declare @bitset_g		tinyint

     select @grantable = 'NO'
     select @is_printable = 0
     /* 
     ** check if the privilege info is to be computed for a table level privilege
     ** i.e. for insert or delete
     */
     if (@colprivileges = 0)
     begin
	   begin
		if ((@tab_priv = 0) and (@tab_priv_g = 0))
		/* no privileges on any column of this table */
			return (0)

		if (@tab_priv_g <> 0x00)
			select @grantable = 'YES'

	   end		
	   select @is_printable = 1
	   return (0)
     end


     /*
     ** The privilege information is to be printed for column level
     ** i.e. select, update, reference
     */

     if ((@col_priv = 0x00) and (@col_priv_g = 0x00))
	  /* empty bit map..so nothing to be printed */
	  return (0)

     if (@calledfrom_colpriv = 0)
     /* we are printing privileges for sp_table_privilege procedure call. Thus
	if any of the bit is one, the privilege is printable */

     begin
	  if (@col_priv_g <>  0x00)
	 	select @grantable = 'YES'

	  select @is_printable = 1
	  return (0)
     end

     /* 
     ** we are called from sp_column_privileges . Need to check if the colbit specified
     ** by the @col_pos is set or not
     */
     exec sybsystemprocs.dbo.syb_aux_colbit @col_pos, @col_priv_g, @bitset_g output

     if (@bitset_g > 0)
	   select @grantable = 'YES'

     exec sybsystemprocs.dbo.syb_aux_colbit @col_pos, @col_priv, @bitset output

     /*
     ** if none of the bits are set, return
     */
     if ((@bitset = 0) and (@bitset_g = 0))
	  return (0)

     /*
     ** the privilege is printable
     */

     select @is_printable = 1
     return (0)

go
exec sp_procxmode 'syb_aux_printprivs', 'anymode'
go
grant execute on syb_aux_printprivs to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_computeprivs')
begin
	drop procedure sp_aux_computeprivs
end
go
print "Installing sp_aux_computeprivs"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Results Table needs to be created so that sp_aux_computeprivs has a temp
** table to reference when the procedure is compiled.  Otherwise, the calling
** stored procedure will create the temp table for sp_aux_computeprivs.
*/
create table #results_table
	(table_qualifier	varchar (32),
	 table_owner		varchar (32),
	 table_name		varchar (257),
	 column_name		varchar (257) NULL,
	 grantor		varchar (32),
	 grantee 		varchar (32),
	 privilege		varchar (32),
	 is_grantable		varchar (3))
go

create procedure sp_aux_computeprivs ( 
                        @table_name  	 	varchar(257),
                        @table_owner 	 	varchar(32),
                        @table_qualifier 	varchar(32), 
			@column_name	 	varchar(257),
			@calledfrom_colpriv	tinyint,
			@tab_id		 	int)

as        

    declare @grantor_name	varchar (32)    /* the ascii name of grantor. used for output */
    declare @grantee_name	varchar (32)    /* the ascii name of grantee. used for output */
    declare @col_count		smallint        /* number of columns in @table_name */
    declare @grantee    	int		/* id of the grantee */
    declare @action 		smallint 	/* action refers to select, update...*/
    declare @columns		varbinary (133)	/* bit map of column privilegs */
    declare @protecttype 	tinyint		/* grant/revoke or grant with grant option */
    declare @grantor    	int		/* id of the grantor of the privilege */
    declare @grp_id		int		/* the group a user belongs to */
    declare @grant_type		tinyint		/* used as a constant */
    declare @revoke_type	tinyint		/* used as a constant */
    declare @select_action	smallint	/* used as a constant */
    declare @update_action	smallint	/* used as a constant */
    declare @reference_action	smallint	/* used as a constant */
    declare @insert_action	smallint	/* used as a constant */
    declare @delete_action	smallint	/* used as a constant */
    declare @public_select	varbinary (133)  /* stores select column bit map for public */
    declare @public_reference	varbinary (133)	/* stores reference column bit map for public */
    declare @public_update	varbinary (133)	/* stores update column bit map for public */
    declare @public_insert	tinyint		/* stores if insert has been granted to public */
    declare @public_delete	tinyint		/* store if delete has been granted to public */
    declare @grp_select		varbinary (133)  /* stores select column bit map for group */
    declare @grp_update		varbinary (133)  /* stores update column bit map for group */
    declare @grp_reference	varbinary (133)  /* stores reference column bit map for group */
    declare @grp_delete		tinyint		/* if group hs been granted delete privilege */
    declare @grp_insert		tinyint		/* if group has been granted insert privilege */
    declare @inherit_select	varbinary (133)	/* stores select column bit map for 
						   inherited privs*/
    declare @inherit_update	varbinary (133)  /* stores update column bit map for 
						   inherited privs */
    declare @inherit_reference	varbinary (133)  /* stores reference column bit map for 
						   inherited privs */
    declare @inherit_insert	tinyint		/* inherited insert priv */
    declare @inherit_delete	tinyint		/* inherited delete priv */
    declare @select_go		varbinary (133)	/* user column bit map of select with grant */
    declare @update_go		varbinary (133)	/* user column bit map of update with grant */
    declare @reference_go	varbinary (133)	/* user column bitmap of reference with grant */
    declare @insert_go		tinyint		/* user insert priv with grant option */
    declare @delete_go		tinyint		/* user delete priv with grant option  */
    declare @prev_grantor	int		/* Has the grantor changed ? */
    declare @col_pos		smallint	/* col_pos of the column we are interested in. It
						   is used to find the col-bit in the bitmap */
    declare @owner_id		int		/* owner id of the table */
    declare @dbid		smallint	/* dbid for the table */
    declare @grantable		varchar (3) 	/* 'YES' or 'NO' if the privilege is grantable or
						   not */
    declare @is_printable	tinyint		/* 1, if the privilege info is to be outputted */

/* 
** Initialize all constants to be used in this procedure
*/

    select @grant_type = 1

    select @revoke_type = 2
   
    select @select_action = 193

    select @reference_action = 151

    select @update_action = 197

    select @delete_action = 196

    select @insert_action = 195


    select @dbid = db_id()

/* 
** compute the table owner id
*/

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id

/*
** create a temporary sysprotects table that only has grant/revoke tuples
** for the requested table. This is done as an optimization as the sysprotects
** table may need to be traversed several times
*/

    create table #sysprotects
	(uid		int,
	 action		smallint,
	 protecttype	tinyint,
	 columns	varbinary (133) NULL,
	 grantor	int)

/*
** This table contains all the groups including PUBLIC that users, who
** have been granted privilege on this table, belong to. Also it includes
** groups that have been explicitly granted privileges on the table object
*/
    create table #useful_groups
	(grp_id		int)

/*
** create a table that contains the list of grantors for the object requested.
** We will do a cartesian product of this table with sysusers in the
** current database to capture all grantor/grantee tuples
*/

    create table #distinct_grantors
	(grantor	int)

/*
** We need to create a table which will contain a row for every object
** privilege to be returned to the client.  
*/

    create table #column_privileges 
	(grantee_gid	int,
	 grantor	int,
	 grantee	int,
	 insertpriv	tinyint,
	 insert_go	tinyint NULL,
	 deletepriv	tinyint,
	 delete_go	tinyint NULL,
	 selectpriv	varbinary (133) NULL,
	 select_go	varbinary (133) NULL,
	 updatepriv	varbinary (133) NULL,
	 update_go	varbinary (133) NULL,
	 referencepriv	varbinary (133) NULL,
	 reference_go	varbinary (133) NULL)

/*
** this cursor scans the distinct grantor, group_id pairs
*/
    declare grp_cursor cursor for
	select distinct grp_id, grantor 
	from #useful_groups, #distinct_grantors
	order by grantor

/* 
** this cursor scans all the protection tuples that represent
** grant/revokes to users only
*/
    declare user_protect cursor for
	select uid, action, protecttype, columns, grantor
	from   #sysprotects
	where  (uid != 0) and
	       ((uid < @@mingroupid) or (uid > @@maxgroupid)) 


/*
** this cursor is used to scan #column_privileges table to output results
*/
    declare col_priv_cursor cursor for
	  select grantor, grantee, insertpriv, insert_go, deletepriv, delete_go,
		 selectpriv, select_go, updatepriv, update_go, referencepriv, reference_go
	  from #column_privileges



/*
** column count is needed for privilege bit-map manipulation
*/
    select @col_count = count (*) 
    from   syscolumns
    where  id = @tab_id


/* 
** populate the temporary sysprotects table #sysprotects
*/

	insert into #sysprotects 
		select uid, action, protecttype, columns, grantor
		from sysprotects
		where (id = @tab_id)    	   and
		      ((action = @select_action)   or
		      (action = @update_action)    or
		      (action = @reference_action) or
		      (action = @insert_action)    or
		      (action = @delete_action))

/* 
** insert privilege tuples for the table owner. There is no explicit grants
** of these privileges to the owner. So these tuples are not there in sysprotects
** table
*/

if not exists (select * from #sysprotects where (action = @select_action) and
		(protecttype = @revoke_type) and (uid = @owner_id))
begin
	insert into #sysprotects
	     values (@owner_id, @select_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @update_action) and
		(protecttype = @revoke_type) and (uid = @owner_id))
begin
	insert into #sysprotects
	     values (@owner_id, @update_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @reference_action) and
		(protecttype = @revoke_type) and (uid = @owner_id))
begin
	insert into #sysprotects
	     values (@owner_id, @reference_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @insert_action) and
		(protecttype = @revoke_type) and (uid = @owner_id))
begin
	insert into #sysprotects
	     values (@owner_id, @insert_action, 0, NULL, @owner_id)
end

if not exists (select * from #sysprotects where (action = @delete_action) and
		(protecttype = @revoke_type) and (uid = @owner_id))
begin
	insert into #sysprotects
	     values (@owner_id, @delete_action, 0, NULL, @owner_id)
end


/* 
** populate the #distinct_grantors table with all grantors that have granted
** the privilege to users or to gid or to public on the table_name
*/

    insert into #distinct_grantors 
	  select distinct grantor from #sysprotects

/* 
** Populate the #column_privilegs table as a cartesian product of the table
** #distinct_grantors and all the users, other than groups, in the current database
*/


    insert into #column_privileges
	  select gid, g.grantor, su.uid, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00,
                 0x00
	  from sysusers su, #distinct_grantors g
	  where (su.uid != 0) and
	        ((su.uid < @@mingroupid) or (su.uid > @@maxgroupid))

/*
** populate #useful_groups with only those groups whose members have been granted/revoked
** privilges on the @tab_id in the current database. It also contains those groups
** that have been granted/revoked privileges explicitly
*/

    insert into #useful_groups
	select distinct gid
	from   sysusers su, #sysprotects sp
	where  (su.uid = sp.uid) 


    open grp_cursor

    fetch grp_cursor into @grp_id, @grantor

    /* 
    ** This loop computes all the inherited privilegs of users due
    ** their membership in a group
    */

    while (@@sqlstatus != 2)
   
    begin

	 /* 
	 ** initialize variables 
	 */
	 select @public_select = 0x00
 	 select @public_update = 0x00
	 select @public_reference = 0x00
	 select @public_delete = 0
	 select @public_insert = 0


	 /* get the select privileges granted to PUBLIC */

	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @select_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_select = columns
	      from #sysprotects
	      where (grantor = @grantor) and 
		    (uid = 0) and
		    (action = @select_action)
         end


	 /* get the update privilege granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @update_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_update = columns
	      from #sysprotects
	      where (grantor = @grantor) and 
		    (uid = 0) and
		    (action = @update_action)
         end

	 /* get the reference privileges granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @reference_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_reference = columns
	      from #sysprotects
	      where (grantor = @grantor) and 
		    (uid = 0) and
		    (action = @reference_action)
         end


	 /* get the delete privilege granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @delete_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_delete = 1
         end

	 /* get the insert privileges granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @insert_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_insert = 1
         end


	 /*
	 ** initialize group privileges 
	 */

	 select @grp_select = 0x00
	 select @grp_update = 0x00
	 select @grp_reference = 0x00
	 select @grp_insert = 0
	 select @grp_delete = 0

	 /* 
	 ** if the group id is other than PUBLIC, we need to find the grants to
	 ** the group also 
	 */

	 if (@grp_id <> 0)
	 begin
	 	/* find select privilege granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @select_action)))
	 	begin
	      		select @grp_select = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @grant_type) and 
		    	      (action = @select_action)
                end

		/* find update privileges granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @update_action)))
	 	begin
	      		select @grp_update = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @grant_type) and 
		    	      (action = @update_action)
                end

		/* find reference privileges granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @reference_action)))
	 	begin
	      		select @grp_reference = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @grant_type) and 
		    	      (action = @reference_action)
                end

		/* find delete privileges granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @delete_action)))
	 	begin

	      		select @grp_delete = 1
                end

		/* find insert privilege granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @insert_action)))
	 	begin

	      		select @grp_insert = 1

                end
		
	 end

	 /* at this stage we have computed all the grants to PUBLIC as well as
	 ** the group by a specific grantor that we are interested in. Now we will
	 ** use this info to compute the overall inherited privilegs by the users
	 ** due to their membership to the group or to PUBLIC 
	 */


	 exec sybsystemprocs.dbo.syb_aux_privunion @public_select, @grp_select, @col_count,
					   @inherit_select output
	 exec sybsystemprocs.dbo.syb_aux_privunion @public_update, @grp_update, @col_count,
					   @inherit_update output
	 exec sybsystemprocs.dbo.syb_aux_privunion @public_reference, @grp_reference, @col_count,
					   @inherit_reference output

	 select @inherit_insert = @public_insert + @grp_insert
	 select @inherit_delete = @public_delete + @grp_delete

	 /*
	 ** initialize group privileges to store revokes
	 */

	 select @grp_select = 0x00
	 select @grp_update = 0x00
	 select @grp_reference = 0x00
	 select @grp_insert = 0
	 select @grp_delete = 0

         /* 
	 ** now we need to find if there are any revokes on the group under
 	 ** consideration. We will subtract all privileges that are revoked from the 
	 ** group from the inherited privileges
	 */

	 if (@grp_id <> 0)
	 begin
		/* check if there is a revoke row for select privilege*/
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @select_action)))
	 	begin
	      		select @grp_select = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @revoke_type) and 
		    	      (action = @select_action)
                end

		/* check if there is a revoke row for update privileges */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @update_action)))
	 	begin
	      		select @grp_update = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @revoke_type) and 
		    	      (action = @update_action)
                end

		/* check if there is a revoke row for reference privilege */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @reference_action)))
	 	begin
	      		select @grp_reference = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @revoke_type) and 
		    	      (action = @reference_action)
                end

		/* check if there is a revoke row for delete privilege */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @delete_action)))
	 	begin
	      		select @grp_delete = 1
                end

		/* check if there is a revoke row for insert privilege */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @insert_action)))
	 	begin
	      		select @grp_insert = 1

                end


		/* 
		** now subtract the revoked privileges from the group
		*/

		exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
					 	 @grp_select,
						 @col_count,
						 @inherit_select output

		exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
					 	 @grp_update,
						 @col_count,
						 @inherit_update output

		exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference,
					 	 @grp_reference,
						 @col_count,
						 @inherit_reference output

		if (@grp_delete = 1)
			select @inherit_delete = 0

		if (@grp_insert = 1)
			select @inherit_insert = 0

	 end

	 /*
	 ** now update all the tuples in #column_privileges table for this
	 ** grantor and group id
	 */
	
	 update #column_privileges
	 set
		insertpriv 	= @inherit_insert,
		deletepriv 	= @inherit_delete,
	        selectpriv 	= @inherit_select,
		updatepriv 	= @inherit_update,
		referencepriv 	= @inherit_reference

	 where (grantor     = @grantor) and
	       (grantee_gid = @grp_id)


	 /*
	 ** the following update updates the privileges for those users
	 ** whose groups have not been explicitly granted privileges by the
	 ** grantor. So they will all have all the privileges of the PUBLIC
	 ** that were granted by the current grantor
	 */

	 select @prev_grantor = @grantor	 
         fetch grp_cursor into @grp_id, @grantor

	 if ((@prev_grantor <> @grantor) or (@@sqlstatus = 2))

	 begin
	 /* Either we are at the end of the fetch or we are switching to
	 ** a different grantor. 
	 */

	       update #column_privileges 
	       set
			insertpriv 	= @public_insert,
			deletepriv 	= @public_delete,
	        	selectpriv 	= @public_select,
			updatepriv 	= @public_update,
			referencepriv 	= @public_reference
		from #column_privileges cp
	 	where (cp.grantor = @prev_grantor) and
	       	      (not EXISTS (select * 
			    	   from #useful_groups ug
			    	   where ug.grp_id = cp.grantee_gid))

         end
    end


    close grp_cursor


    /* 
    ** At this stage, we have populated the #column_privileges table with
    ** all the inherited privileges
    */
    /*
    ** update #column_privileges to give all access to the table owner that way
    ** if there are any revoke rows in sysprotects, then the calculations will
    ** be done correctly.  There will be no revoke rows for table owner if
    ** privileges are revoked from a group that the table owner belongs to.
    */
    update #column_privileges
    set
	insertpriv 	= 0x01, 
	deletepriv 	= 0x01, 
	selectpriv 	= 0x01,
	updatepriv 	= 0x01,
	referencepriv 	= 0x01

	where grantor = grantee
	  and grantor = @owner_id

    
    /* 
    ** Now we will go through each user grant or revoke in table #sysprotects
    ** and update the privileges in #column_privileges table
    */
    open user_protect

    fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor

    while (@@sqlstatus != 2)
    begin
	/*
	** In this loop, we can find grant row, revoke row or grant with grant option
	** row. We use protecttype to figure that. If it is grant, then the user specific
	** privileges are added to the user's inherited privileges. If it is a revoke,
	** then the revoked privileges are subtracted from the inherited privileges. If
	** it is a grant with grant option, we just store it as is because privileges can
	** only be granted with grant option to individual users
	*/

	/* 
	** for select action
	*/
	if (@action = @select_action)
	begin
	     /* get the inherited select privilege */
	     select @inherit_select = selectpriv
	     from   #column_privileges
	     where  (grantee = @grantee) and
		    (grantor = @grantor)

	     if (@protecttype = @grant_type)
	     /* the grantee has a individual grant */
		exec sybsystemprocs.dbo.syb_aux_privunion @inherit_select, @columns, 
						  @col_count, @inherit_select output

	     else 
		if (@protecttype = @revoke_type)
		/* it is a revoke row */
		     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select, @columns, 
						      @col_count, @inherit_select output

	        else
		     /* it is a grant with grant option */

		     select @select_go = @columns

  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set selectpriv = @inherit_select
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin

	     	  update #column_privileges
	     	  set select_go = @select_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	end

	/*
	** update action
	*/
	if (@action = @update_action)
	begin
	     /* find out the inherited update privilege */
	     select @inherit_update = updatepriv
	     from   #column_privileges
	     where  (grantee = @grantee) and
		    (grantor = @grantor)

		
	     if (@protecttype = @grant_type)
	     /* user has an individual grant */
		exec sybsystemprocs.dbo.syb_aux_privunion @inherit_update, @columns, 
						  @col_count, @inherit_update output

	     else 
		if (@protecttype = @revoke_type)
		     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update, @columns, 
						      @col_count, @inherit_update output

	        else
		     /* it is a grant with grant option */
		     select @update_go = @columns


  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set updatepriv = @inherit_update
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set update_go = @update_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	end

	/* it is the reference privilege */
	if (@action = @reference_action)
	begin
	     select @inherit_reference = referencepriv
	     from   #column_privileges
	     where  (grantee = @grantee) and
		    (grantor = @grantor)


	     if (@protecttype = @grant_type)
	     /* the grantee has a individual grant */
		exec sybsystemprocs.dbo.syb_aux_privunion @inherit_reference, @columns, 
						  @col_count, @inherit_reference output

	     else 
		if (@protecttype = @revoke_type)
		/* it is a revoke row */
		     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference, @columns, 
						      @col_count, @inherit_reference output

	        else
		     /* it is a grant with grant option */
		     select @reference_go = @columns


  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set referencepriv = @inherit_reference
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set reference_go = @reference_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end

	end

	/*
	** insert action
	*/

	if (@action = @insert_action)
	begin
	     if (@protecttype = @grant_type)
		   select @inherit_insert = 1
	     else
		 if (@protecttype = @revoke_type)
		      select @inherit_insert = 0
		 else
		      select @insert_go = 1

	     
  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set insertpriv = @inherit_insert
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set insert_go = @insert_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end

	end

	/* 
	** delete action
	*/

	if (@action = @delete_action)
	begin
	     if (@protecttype = @grant_type)
		   select @inherit_delete = 1
	     else
		 if (@protecttype = @revoke_type)
		      select @inherit_delete = 0
		 else
		      select @delete_go = 1

	     
  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set deletepriv = @inherit_delete
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set delete_go = @delete_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end

	end

        fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor
    end

    close user_protect

open col_priv_cursor
fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
	                 @inherit_delete, @delete_go, @inherit_select, @select_go,
			 @inherit_update, @update_go, @inherit_reference, @reference_go

while (@@sqlstatus != 2)
begin

      /* 
      ** name of the grantor
      */
      select @grantor_name = name 
      from   sysusers
      where  uid = @grantor


      /*
      ** name of the grantee
      */

      select @grantee_name = name
      from   sysusers
      where  uid = @grantee

      /* 
      ** At this point, we are either printing privilege information for a
      ** a specific column or for table_privileges
      */

	    select @col_pos = 0

	    if (@calledfrom_colpriv = 1)
	    begin
	    /* 
	    ** find the column position
	    */
	         select @col_pos = colid
	         from syscolumns
	         where (id = @tab_id) and
		       (name = @column_name)
	    end

	    /* 
	    ** check for insert privileges
	    */
	    /* insert privilege is only a table privilege */
	    if (@calledfrom_colpriv = 0)
	    begin
		    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, @inherit_insert, @insert_go, 0x00, 0x00, 0, 
				@grantable output, @is_printable output

		    if (@is_printable = 1)
		    begin
			  insert into #results_table
			       values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'INSERT', @grantable)
		    end
	    end

	    /* 
	    ** check for delete privileges
	    */

	    if (@calledfrom_colpriv = 0)
	    /* delete privilge need only be printed if called from sp_table_privileges */
	    begin
	 	    exec sybsystemprocs.dbo.syb_aux_printprivs 
		         @calledfrom_colpriv, @col_pos, @inherit_delete, @delete_go, 0x00, 0x00, 0, 
				@grantable output, @is_printable output

	    	    if (@is_printable = 1)
		    begin
		  	insert into #results_table
			        values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'DELETE', @grantable)
		    end
	    end

	    /* 
	    ** check for select privileges
	    */
	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_select, @select_go, 1, 
			@grantable output, @is_printable output


	    if (@is_printable = 1)
	    begin
		  insert into #results_table
		  	 values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'SELECT', @grantable)
	    end
	    /* 
	    ** check for update privileges
	    */
	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_update, @update_go, 1, 
			@grantable output, @is_printable output

	    if (@is_printable = 1)
	    begin
		  insert into #results_table
		   	values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'UPDATE', @grantable)
	    end
	    /*
	    ** check for reference privs
	    */
 	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_reference, @reference_go, 1, 
			@grantable output, @is_printable output

    	    if (@is_printable = 1)
	    begin
	  	insert into #results_table
		        values (@table_qualifier, @table_owner, @table_name, @column_name,
			@grantor_name, @grantee_name, 'REFERENCE', @grantable)
	    end



      fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
	                 @inherit_delete, @delete_go, @inherit_select, @select_go,
			 @inherit_update, @update_go, @inherit_reference, @reference_go
end

    
/*
** Outputting the results table
*/

if (@calledfrom_colpriv = 0)
begin
	exec sp_autoformat @fulltabname = #results_table,
		@selectlist = "table_qualifier, table_owner, table_name, grantor, grantee, privilege, is_grantable",
		@orderby = "order by grantee"
end

close col_priv_cursor

    drop table #column_privileges
    drop table #distinct_grantors
    drop table #sysprotects
    drop table #useful_groups
go

/* 
** Drop temp table used for creation of sp_aux_computeprivs
*/
drop table #results_table
go
exec sp_procxmode 'sp_aux_computeprivs', 'anymode'
go
grant execute on sp_aux_computeprivs to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_text')
begin
	drop procedure sp_aux_text
end
go
print "Installing sp_aux_text"
go

/*
** Messages for "sp_aux_text"
**
** 567,  "You must have the following role(s) to execute this command/procedure:
** 'sa_role' .  Please contact a user with the appropriate role for help."
**
** 17232, "No user with the specified name exists in the current database."
** 17461, "Object does not exist in this database." 
** 18404, "Source text for compiled object %!1 (id = %!2) exists."
** 18405, "Source text for compiled object %!1 (id = %!2) does not exist."
** Parameters:
**      objname - compiled object name
**      tabname - table name
**      username - user name
**	opcode - 1 means to checksource
**		- 2 means to hidetext
**
** Returns:
**      1 - if error.
**      0 - if no error.
*/
create procedure sp_aux_text
@procname varchar(255) = NULL,
@tabname varchar(255) = NULL,
@username varchar(255) = NULL,
@opcode tinyint
as
declare @exec_uid int
declare @select_uid int
declare @all_null tinyint
declare @msg varchar(255)
declare @proc_id int
declare @objname varchar(255)
if @@trancount = 0
begin
        set chained off
end
 
set transaction isolation level 1
 
select @exec_uid = user_id()
select @all_null = 0

/* Create a temporary table which holds all the complied object ids.*/

create table #proc_objid_t_tab(id int not NULL)

if ((@procname is NULL) and (@tabname is NULL) and (@username is NULL))
begin
 
	/*
	**  Only the Database Owner (DBO) or
	**  Accounts with SA role can execute it.
	**  Call proc_role() with the required SA role.
	*/
	if ((user_id() != 1) and (proc_role("sa_role") < 1))
		return 1

	select @all_null = 1
	goto start_check
end

if (@username is not NULL)
begin
	select @select_uid = user_id(@username)
	if (@select_uid is NULL)
	begin
		
		/*
		** 17232, "No user with the specified name exists in the 
		** current database."
		*/
		raiserror 17232
		return 1
	end
end
else
begin
	/* Default to executor's own object */
	select @select_uid = @exec_uid 
end

/*
** If the user is not a dbo, the user can't operate on other user's
** object. If the user is a dbo, however, the user can operate
** on the object belongs to the user whose username is specified as @username.
*/
if (@select_uid != @exec_uid) 
begin
	 
	/*
	**  Only the Database Owner (DBO) or
	**  Accounts with SA role can execute it.
	**  Call proc_role() with the required SA role.
	*/
	if ((user_id() != 1) and (proc_role("sa_role") < 1))
		return 1
end
	

if (@procname is not NULL)
begin
	insert into #proc_objid_t_tab 
	select id from sysobjects
	where name = @procname and uid = @select_uid and
		id in (select id from sysprocedures)

	if (not exists (select * from #proc_objid_t_tab))
	begin
		/* No row has been selected into this table, this means that
		** the user must enter a wrong procedure name. Time
		** to quit.
		*/
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end
end
else
begin
	if (@tabname is NULL)
	begin
		insert into #proc_objid_t_tab 
		select id from sysobjects
		where sysobjects.uid = @select_uid
		and id in (select id from sysprocedures)
	end
end

if (@tabname is not NULL)
begin

	create table #table_ids(id int)
	insert into #table_ids
	select id from sysobjects where name = @tabname and uid = @select_uid

	if (not exists (select * from #table_ids))
	begin
		/* No row has been selected into this table, this means that
		** the user must enter a wrong table name. Time
		** to quit.
		*/
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end


	insert into #proc_objid_t_tab

	/* Get any check constraints defined on this table */

	select constrid 
	from sysconstraints, #table_ids
	where sysconstraints.tableid = #table_ids.id
		and (sysconstraints.status & 128) = 128

	union

	/* Get any declaractive defaults defined on this table */
	select cdefault
	from syscolumns, #table_ids, sysprocedures 
	where syscolumns.id = #table_ids.id and syscolumns.cdefault != 0
		and sysprocedures.id = syscolumns.cdefault and
		sysprocedures.status & 4096 = 4096

	union

	/* Get any decrypt_default defined on columns of this table */
	select object
	from syscolumns, #table_ids, sysattributes
	where syscolumns.id = #table_ids.id and
		syscolumns.status2 & 4096 = 4096 and
		sysattributes.object_info1 = #table_ids.id

	union

	/* Get all delete, insert or update triggers defined on this table */
	select deltrig from sysobjects, #table_ids
	where deltrig != 0 and sysobjects.id = #table_ids.id

	union

	select instrig from sysobjects, #table_ids
	where instrig != 0 and sysobjects.id = #table_ids.id

	union

	select updtrig from sysobjects, #table_ids
	where updtrig != 0 and sysobjects.id = #table_ids.id

	/* Get all the computed columns, functional index keys */
	union

	select computedcol 
	from syscolumns, #table_ids 
	where syscolumns.id = #table_ids.id and computedcol is not null 

	/*
	** Get all partition conditions defined on this table
	** Currently, only range and list partition type
	** has text stored in syscomments.
	*/
	union

	select conditionid from sysindexes i, #table_ids t
	where i.id = t.id and i.partitiontype in (
		select v.number from master.dbo.spt_values v
				where v.name in ('range', 'list')) 
end



start_check: if (@all_null = 1)
begin 
	insert into #proc_objid_t_tab
	select distinct id
	from sysprocedures
end

if (@opcode = 2)
begin
	/* Do hidetext stuff */
	/* ISSUE, get return value of dbcc */
	dbcc hidetext("#proc_objid_t_tab", 16)
	if (@@error != 0)
	begin
		return 1
	end
	return 0
end

/* Do checksource stuff */
declare sp_checksource_c cursor
for select id
from #proc_objid_t_tab
for read only

open sp_checksource_c
fetch sp_checksource_c into @proc_id
while (@@sqlstatus != 2)
begin
		if (not exists (
			select * from syscomments 
			where id = @proc_id and 
			(syscomments.text is NOT null
				 or (syscomments.status is not null and
					syscomments.status & 1 = 1)   )))
		begin
			/*
			** 18405, "Source text for procedure object 
			** %!1 (id = %!2) does not exist."
			*/
			select @objname = object_name(@proc_id)
			raiserror 18405, @objname, @proc_id
		end
		else
		begin
			/*
			** 18404, "Source text for procedure object 
			** %!1 (id = %!2) exists."
			*/
			select @objname = object_name(@proc_id)
			raiserror 18404, @objname, @proc_id
		end
	fetch sp_checksource_c into @proc_id
end
close sp_checksource_c
deallocate cursor sp_checksource_c

return 0
go
exec sp_procxmode 'sp_aux_text', 'anymode'
go
grant execute on sp_aux_text to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_encr_lookup')
begin
	drop procedure sp_aux_encr_lookup
end
go
print "Installing sp_aux_encr_lookup"
go


/* 
** Auxilliary stored procedure for getting the username, object name and
** column name in the database @dbname for which the column is encrypted
** by the specified encryption key.
*/

/*
** #encrypted_column_info needs to be created so that sp_aux_encr_lookup has a 
** temp table to reference when the procedure is compiled. Otherwise, the 
** calling stored procedure will create the temp table for sp_aux_encr_lokup.
*/
create table #encrypted_column_info
	(keyname varchar(255) null,
	keyowner varchar(30) null,
	dbname varchar(30) null,
	username varchar(30) null,
	objname varchar(255) null,
	colname varchar(255) null)
go

create procedure sp_aux_encr_lookup 
@owner		varchar(30),
@keyname	varchar(255),
@db_name	varchar(30)
as
begin
	declare	@keydbid	varchar(8)
	      , @sqlstmt	varchar(1100)

	select @keydbid = convert(varchar(8), db_id(@db_name))

	select @sqlstmt = 
	"insert #encrypted_column_info(keyname, keyowner,  username, objname, colname) " +
	"select o2.name, u.name, user_name(o1.uid), o1.name, c.name " +
	"from syscolumns c, sysobjects o1, " + 
		@db_name + "..sysobjects o2, " + @db_name + "..sysusers u " +
	"where c.id = o1.id and " +
		"(c.encrkeydb = " + "'" + @db_name + "'" +  
		"or (c.encrkeydb is NULL and " + "'" + @keydbid + "'" + 
			" = convert(varchar(8), db_id()))) " +
		"and c.encrkeyid = o2.id " +
		"and o2.type in ('EK') " +
		"and o2.name like " + "'" + @keyname + "' " +
		"and o2.uid = u.uid " +
		"and u.name like " + "'" + @owner + "'"

	exec sp_exec_SQL @sqlstmt, "sp_aux_encr_lookup"
end

go

/*
** Drop temp table used for creation of sp_aux_encr_lookup
*/
drop table #encrypted_column_info

go
go
exec sp_procxmode 'sp_aux_encr_lookup', 'anymode'
go
grant execute on sp_aux_encr_lookup to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_encrkey_lookup')
begin
	drop procedure sp_aux_encrkey_lookup
end
go
print "Installing sp_aux_encrkey_lookup"
go


/*
** Auxilliary stored procedure for extracting key information for the specified
** table/column.
*/

/*
** #encrypted_table_info needs to be created so that sp_aux_encrkey_lookup has a
** temp table to reference when the procedure is compiled. At runtime, the
** calling stored procedure will create the temp table for sp_aux_encrkey_lokup.
*/
create table #encrypted_table_info(
	username varchar(30) null,
	tabname varchar(255) null,
	colname varchar(255) null,
	keydbname varchar(30) null,
	keyowner varchar(30) null,
	keyid int null,
	keyname varchar(255) null,
	fullcolname varchar(540) null,
	fullkeyname varchar(315) null)

go

create procedure sp_aux_encrkey_lookup
as
declare @dbname		varchar(30)
begin	--{ /* sp_aux_encrkey_lookup Start */
	select @dbname = db_name()	

	update #encrypted_table_info
	set keyowner = user_name(o.uid)
		, keyname = o.name
	from sysobjects o
	where o.id = keyid
		and @dbname = keydbname
end	--}
go

/*
** Drop temp table used for creation of sp_aux_encrkey_lookup
*/

drop table #encrypted_table_info

go
go
exec sp_procxmode 'sp_aux_encrkey_lookup', 'anymode'
go
grant execute on sp_aux_encrkey_lookup to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_sys_encr_passwd_lookup')
begin
	drop procedure sp_aux_sys_encr_passwd_lookup
end
go
print "Installing sp_aux_sys_encr_passwd_lookup"
go


/* 
** Auxilliary stored procedure for getting the system encrytion password 
** information in the database @dbname.
*/

/*
** #sys_encr_passwd_info needs to be created so that sp_aux_sys_encr_passwd_lookup has a 
** temp table to reference when the procedure is compiled. Otherwise, the 
** calling stored procedure will create the temp table for sp_aux_sys_encr_passwd_lokup.
*/

create table #sys_encr_passwd_info(dbname varchar(30) null,
                                   typeofpasswd varchar(30) null,
				   modifier varchar(30) null,
				   moddate smalldatetime null)
go

create procedure sp_aux_sys_encr_passwd_lookup 
@db_name	varchar(30)
as
begin
	insert #sys_encr_passwd_info(dbname, typeofpasswd, modifier, moddate)
	select @db_name
		, case (object_info2)
			when 0 then "persistent"
			when 1 then "nonpersistent"
		end			
		, object_cinfo
		, convert(smalldatetime, convert(binary(4), object))
	from sysattributes 
	where   class = 25
		and attribute = 0
		and object_type = "EC"
end
go

/*
** Drop temp table used for creation of sp_aux_sys_encr_passwd_lookup
*/
drop table #sys_encr_passwd_info
go
go
exec sp_procxmode 'sp_aux_sys_encr_passwd_lookup', 'anymode'
go
grant execute on sp_aux_sys_encr_passwd_lookup to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_encrkey_info')
begin
	drop procedure sp_aux_encrkey_info
end
go
print "Installing sp_aux_encrkey_info"
go


/* 
** Auxilliary stored procedure for extracting key proerties.
*/

/*
** #encrypted_column_info needs to be created so that sp_aux_encr_lookup has a 
** temp table to reference when the procedure is compiled. Otherwise, the 
** calling stored procedure will create the temp table for sp_aux_encr_lokup.
*/
use sybsystemprocs
go
if object_id("sp_aux_encrkey_info") <> NULL
begin
   drop proc sp_aux_encrkey_info
end
go
create table #encr_column_info(keyname varchar(255),
				keyowner varchar(30),
				keydbname varchar(30),
				keylength int,
				keyalgorithm varchar(30),
				keytype int,
				random_pad int,
				init_vector int,
				typeofpasswd varchar(30),
				keyrecovery int)
go


create procedure sp_aux_encrkey_info
@owner		varchar(30),
@keyname	varchar(255)
as
declare @random_pad	int	
      , @init_vector	int
      , @system_password int
      , @login_access int
      , @login_password int
      , @user_password int	
      , @aes		int		
      , @default_key	int
      , @key_recovery  int
      , @dbname		varchar(30)
begin
	/* These bits are defined in encryptkey.h */
	select @random_pad = 2		/* EK_RANDOMPAD */
	     , @init_vector = 1 	/* EK_INITVECTOR */
	     , @login_password = 16     /* EK_LOGINPASS */
	     , @login_access = 8        /* EK_LOGINACCESS */
	     , @system_password = 32	/* EK_SYSENCRPASS */
	     , @user_password = 256     /* EK_USERPWD */
	     , @aes = 1                 /* AES algorithm */
	     , @default_key = 4 	/* EK_DEFAULT */
	     , @key_recovery = 64       /* EK_KEYRECOVERY */

	begin	--{
		select @dbname = db_name()
		insert #encr_column_info(keyname, keyowner, keydbname, keylength,
			keyalgorithm, keytype, random_pad, init_vector,
			typeofpasswd, keyrecovery)
		select o1.name, user_name(o1.uid), @dbname, e1.eklen 
			, case (e1.ekalgorithm & @aes)
				when 0 then "RSA"
				else "AES"
			  end
			/*
			** ENCR_RESOLVE: Will have to be enhanced to handle
			** asymmetric keys when they are supported.
			*/
			, e1.type
			, case (e1.status & @random_pad) 
				when 0 then 0
				else 1
			  end
			/*
			** ENCR_RESOLVE: Will have to be enhanced to handle
			** asymmetric keys when they are supported.
			*/
			, case (e1.status & @init_vector)
				when 0 then 0
				else 1
			  end
			, case  
				when (e1.status & @login_access ) > 0 then "Login Access"
				when (e1.status & @login_password) > 0 then "Login Passwd"
                                when (e1.status & @system_password) > 0 then "System Encr Passwd"
                                when (e1.status & @user_password) > 0 then "User Passwd"
			  end
			, case (e1.type & @key_recovery)
				when 0 then 0
				else 1
			  end
		from sysobjects o1, sysencryptkeys e1
		where o1.id = e1.id
			and o1.type = "EK"
			and o1.name like @keyname
			and user_name(o1.uid) like @owner
	end	--}

end

go

/*
** Drop temp table used for creation of sp_aux_encrkey_info
*/
drop table #encr_column_info

go




go
exec sp_procxmode 'sp_aux_encrkey_info', 'anymode'
go
grant execute on sp_aux_encrkey_info to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_encr_verify_downgrade')
begin
	drop procedure sp_aux_encr_verify_downgrade
end
go
print "Installing sp_aux_encr_verify_downgrade"
go

/*
** sp_getmessage Messages for encryption [Total 9]
** 19664, "Alter key to drop key copy"
** 19665, "Alter key to encrypt by system encryption password"
** 19667, "Revoke privileges from role"
** 19668, "Revoke keycustodian_role from user"
** 19669, "Reset system encryption password with length <= 64 bytes"
** 19670, "Alter table to drop decrypt default"
** 19671, "Turn off the configuration option parameter 'restricted decrypt permission"
** 19672, "Alter table to decrypt column"
** 19687, "Alter key to drop key recovery"
*/
/*
** Auxilliary stored procedure for verifying that all the steps have been
** taken in the area of encrypted columns to ready the 15.0.2 server for
** downgrade.
*/

create table #encrypted_verify_results(
	dbname		varchar(30) null
	, assignee	varchar(30) null
	, tabname	varchar(255) null
	, colname	varchar(255) null
	, type		tinyint null
	, length	tinyint null
	, username	varchar(30) null
	, keydbname	varchar(30) null
	, keyowner	varchar(30) null
	, keyid		int null
	, keyname	varchar(255) null
	, fullkeyname	varchar(315) null
	, error		int null
	, errstr	varchar(128) null
)

create table #encrypted_table_verify(
	dbname	varchar(30) null
	, assignee	varchar(30) null
	, username	varchar(30) null
	, tabname	varchar(255) null
	, colname	varchar(255) null
	, type		tinyint null
	, length	tinyint null
	, keydbname	varchar(30) null
	, keyowner	varchar(30) null
	, keyid		int null
	, keyname	varchar(255) null
	, keystatus	int null
	, action	int null
	, fullcolname	varchar(540) null
	, fullkeyname	varchar(315) null 
)
go

create procedure sp_aux_encr_verify_downgrade
	@cmd	varchar(30),
	@opt1	varchar(600)
as
begin -- { Beginning of sp_aux_encr_verify_downgrade.
	declare @dbname	varchar(255)	/* Database name */
	, @key_recovery  int
	, @login_access  int
	, @login_password int
	, @system_password int
	, @user_password int	
	, @key_copy     int               
	, @encolstatus  int
	, @user_name 	varchar(255)
	, @maxszsep int			
	, @decrypt_default int
	, @seplen int
	, @confignum int
        , @sysstatus int
        , @configname varchar(255)
        , @fullconfigname varchar(255)
	, @oldcfgvalue            int
	, @oldcfgvalue_char       varchar(255)
	, @defvalue       varchar(255)
	, @value		char(10)
	, @err_verify_keycopy int
	, @err_verify_key_recovery int
	, @err_verify_user_passwd int
	, @err_verify_login_passwd int
	, @err_check_key_custodian_roles int
	, @err_check_user_key_custodian_roles int
	, @err_check_SEP_len int
	, @err_check_decrypt_default int
	, @err_check_encrypted_columns int
	, @err_check_restricted_decrypt int
	, @err_check_column_datatype  int
	, @msgstr1 varchar(255) 
	, @msgstr2 varchar(255) 


/* These bits are defined either in encryptkey.h or in database.h */
select  @key_recovery = 64              /* EK_KEYRECOVERY */
	, @login_access = 8             /* EK_LOGINACCESS */
	, @login_password = 16          /* EK_LOGINPASS */
	, @system_password = 32         /* EK_SYSENCRPASS */
	, @user_password = 256          /* EK_USERPWD */
	, @key_copy = 16                /* EK_KEYCOPY */
	, @encolstatus = 128            /* Indicates encrypted column status */
	, @maxszsep = 193               /* Max size System Encrypted Passwd */
	, @decrypt_default = 4096       /* decrypt_default bit */
	, @dbname = db_name()
	, @err_verify_key_recovery = 1  /* Error for key recovery */
	, @err_verify_keycopy = 2 	/* Error for keycopy existence */
	, @err_verify_user_passwd = 3   /* Error for user password */
	, @err_verify_login_passwd = 4  /* Error for login password */
	, @err_check_user_key_custodian_roles = 5 /* Error for user keycustodian roles */
	, @err_check_key_custodian_roles = 6 	/* Error for keycustodian_role roles */
	, @err_check_decrypt_default = 7        /* Error for decrypt default */
	, @err_check_encrypted_columns = 8      /* Error for encrypted column */
	, @err_check_column_datatype = 9        /* Error for column datatype */
	, @err_check_SEP_len = 10               /* Error for System Encryption Password greater than 64 bytes */
	, @err_check_restricted_decrypt = 11 /* Error for restricted decrypt being set */

/* 
** Checking for the existence of key copies.
*/
if (@cmd = "verify_keycopy") 
begin -- { Beginning of verify_keycopy

	insert #encrypted_table_verify (assignee, keyname, keyid, keyowner)
		select user_name(e1.uid)
			, o1.name, e1.id
			, user_name(o1.uid)
			from sysobjects o1, sysencryptkeys e1
			where o1.id = e1.id
			and e1.type & @key_copy > 0

	if exists (select 1 from #encrypted_table_verify)
	begin
		exec sp_getmessage 19664, @msgstr1 output
		insert #encrypted_verify_results (dbname, assignee, keyname, keyid, keyowner, error, errstr)
			select @dbname 
				, assignee 
				, keyname
				, keyid
				, keyowner
				, @err_verify_keycopy 
				, @msgstr1
			from #encrypted_table_verify

		update #encrypted_verify_results
		set assignee = "NULL"
		where assignee is NULL

		return (1)
	end
	else
	begin
		return (0)
	end
end -- } End of verify_keycopy
if (@cmd = "verify_key_recovery_copy") 
begin -- { Beginning of verify_key_recovery_copy

	insert #encrypted_table_verify (assignee, keyname, keyid, keyowner)
		select user_name(e1.uid)
			, o1.name, e1.id
			, user_name(o1.uid)
			from sysobjects o1, sysencryptkeys e1
			where o1.id = e1.id
			and e1.type & @key_recovery > 0

	if exists (select 1 from #encrypted_table_verify)
	begin
		exec sp_getmessage 19687, @msgstr1 output
		insert #encrypted_verify_results (dbname, assignee, keyname, keyid, keyowner, error, errstr)
			select @dbname 
				, assignee 
				, keyname
				, keyid
				, keyowner
				, @err_verify_key_recovery
				, @msgstr1
			from #encrypted_table_verify

/*
		update #encrypted_verify_results
		set assignee = "NULL"
		where assignee is NULL
*/

		return (1)
	end
	else
	begin
		return (0)
	end
end -- } End of verify_key_recovery_copy

/* 
** Checking sysencryptkeys.status for keys encrypted by user password.
*/
if (@cmd = "verify_user_passwd") 
begin -- { Beginning of verify_user_passwd

	insert #encrypted_table_verify (assignee, keyname, keyid, keyowner, keystatus)
		select user_name(e1.uid) 
			, o1.name
			, e1.id 
			, user_name(o1.uid)
			, e1.status
		from sysobjects o1, sysencryptkeys e1
		where   o1.id = e1.id 
			and e1.type & @key_copy = 0

	if exists (select 1 from #encrypted_table_verify)
	begin
		exec sp_getmessage 19665, @msgstr1 output
		insert #encrypted_verify_results (dbname, username, keyname, 
			keyid, keyowner, error, errstr)
			select @dbname 
				, assignee
				, keyname 
				, keyid 
				, keyowner 
				, @err_verify_user_passwd
				, @msgstr1 
			from #encrypted_table_verify
			where keystatus & @user_password > 0 

		update #encrypted_verify_results
		set username = "NULL"
		where username is NULL

		return (1)
	end
	else
	begin
		return (0)
	end
end -- } end of verify_user_passwd

/* 
** Checking existence of permissions granted to keycustodian_role.
*/
if (@cmd = "check_key_custodian_roles") 
begin -- { Beginning of check_key_custodian_roles


	insert #encrypted_table_verify (action)
		select p1.action
		from sysprotects p1, sysusers u1
		where u1.uid = p1.uid
			and u1.name = "keycustodian_role"

	if not exists (select 1 from #encrypted_table_verify)
	begin
		return (0)
	end
	else
	begin
		exec sp_getmessage 19667, @msgstr1 output
		insert #encrypted_verify_results (dbname, error, errstr)
			select @dbname 
				, @err_check_key_custodian_roles
				, @msgstr1
		return (1)
	end
end -- } end of check_key_custodian_roles

/* 
** Checking if keycustodian_role is granted to any user.
*/

if (@cmd = "check_user_key_custodian_roles" )
begin -- { Beginning of check_user_key_custodian_roles

	insert #encrypted_table_verify (assignee)
		select s.name
		from master.dbo.syslogins s, master.dbo.sysloginroles r
		where s.suid = r.suid
			and r.srid  = 16

	if not exists (select 1 from #encrypted_table_verify)
	begin
		return (0)
	end
	else
	begin
		exec sp_getmessage 19668, @msgstr1 output
		insert #encrypted_verify_results (dbname, username, error, errstr)
			select @dbname
				, assignee 
				, @err_check_user_key_custodian_roles
				, @msgstr1
			from #encrypted_table_verify
		return (1)
	end
end -- } end of check_user_key_custodian_roles

/*
** Check the length of the System Encryption PWD.
*/
if (@cmd = "check_SEP_len")  
begin -- { Beginning of check_SEP_len
	select @seplen = char_length(char_value) from sysattributes
		where class = 25 and attribute = 0
	if (@seplen > @maxszsep)
	begin
		exec sp_getmessage 19669, @msgstr1 output
		insert #encrypted_verify_results (dbname, error, errstr)
			select @dbname 
				, @err_check_SEP_len
				, @msgstr1
		return(1)
	end
	else
	begin
		return (0)
	end
end -- } end of check_SEP_len

/* 
** Check for presence of decrypt_default. 
*/
if (@cmd = "check_decrypt_default")  
begin -- { Beginning of check_decrypt_default


	insert #encrypted_table_verify (dbname
		,	username 
		,	tabname
		,	colname
			)
		select @dbname
			, user_name(o1.uid)
			, object_name(o1.id, d1.dbid) 
			, col_name(o1.id, c1.colid, d1.dbid)
		from  	master.dbo.sysdatabases d1  
			, syscolumns c1 
			, sysusers u1 
			, sysobjects o1
		where 	d1.name = @dbname
			and c1.status2 & @decrypt_default > 0
			and d1.suid = u1.suid
			and c1.id = o1.id

	if exists (select 1 from #encrypted_table_verify)
	begin
		exec sp_getmessage 19670, @msgstr1 output
		insert #encrypted_verify_results (dbname, username, tabname, colname, error, errstr)
			select @dbname 
				, username
				, tabname
				, colname
				, @err_check_decrypt_default
				, @msgstr1
			from #encrypted_table_verify

		return(1)
	end
	else
	begin
		return(0)
	end

end -- } end of check_decrypt_default

/* 
** Check is restricted decrypt set. 
*/
if (@cmd = "check_restricted_decrypt") 
begin -- { Beginning of check_restricted_decrypt


	select @configname = "restricted decrypt permission"

	/* set @confignum */
	select  @confignum = config,
		@sysstatus = status,
		@fullconfigname = name
		from master.dbo.sysconfigures
			where name like "%" + @configname  + "%"
			and parent != 19
			and config != 19

	select  @oldcfgvalue = b.value,
		@oldcfgvalue_char = b.value2,
		@defvalue = c.defvalue
	from master.dbo.sysconfigures b,
		master.dbo.syscurconfigs c
	where b.config = @confignum
	and b.config *= c.config

	if (@oldcfgvalue > 0)
	begin
		exec sp_getmessage 19671, @msgstr1 output
		select @value=convert(char(10),@oldcfgvalue)
		insert #encrypted_verify_results (dbname, error, errstr)
			select @dbname 
				, @err_check_restricted_decrypt
				, @msgstr1
		return(1)
	end
	else
	begin
		return(0)
	end

end -- } End of check_restricted_decrypt

/* 
** Check existence of encrypted columns. 
*/
if (@cmd = "check_encrypted_columns") 
begin -- { Beginning of check_encrypted_columns

	insert #encrypted_table_verify (username , tabname , colname)
		select  user_name(o1.uid)
			, object_name(o1.id, d1.dbid) 
			, c.name
		from syscolumns c
			, sysobjects o1
			, master.dbo.sysdatabases d1
		where 	d1.name = @dbname
			and c.id = o1.id
			and ((c.status2 & @encolstatus) = @encolstatus)

	if exists (select 1 from #encrypted_table_verify)
	begin
		exec sp_getmessage 19672, @msgstr1 output
		insert #encrypted_verify_results (dbname, username, tabname, colname, error, errstr)
			select @dbname 
				, username
				, tabname
				, colname
				, @err_check_encrypted_columns
				, @msgstr1
			from #encrypted_table_verify

		return(1)
	end
	else
	begin
		return(0)
	end
end -- } End of check_encrypted_columns

/*
** Checking for encrypted columns whose datatypes can't be encrpted
** in 15.0.1.
*/
if (@cmd = "check_column_datatype") 
begin -- { Beginning of check_column_datatype
	insert #encrypted_table_verify (username , tabname , colname, type, length)
		select  user_name(o1.uid)
			, object_name(o1.id, d1.dbid) 
			, c.name
			, c.type
			, c.length
		from syscolumns c
			, sysobjects o1
			, master.dbo.sysdatabases d1
			, master.dbo.systypes t1
		where 	d1.name = @dbname
			and c.id = o1.id
			and ((c.status2 & @encolstatus) = @encolstatus)
			and c.type = t1.type
			and t1.name in ( "bigint", "ubigint", "bit" 
					,"time" ,"date" 
					,"datetime" ,"smalldatetime" 
					, "money","smallmoney" 
					,"unichar" ,"univarchar" )
	if exists (select 1 from #encrypted_table_verify)
	begin
		exec sp_getmessage 19672, @msgstr1 output
		insert #encrypted_verify_results (dbname, username, tabname, colname, type, length, error, errstr)
			select @dbname 
				, username
				, tabname
				, colname
				, type
				, length
				, @err_check_encrypted_columns
				, @msgstr1
			from #encrypted_table_verify
		return(1)
	end
	else
	begin
		return(0)
	end
end -- } End of check_column_datatype

end -- } End of sp_aux_encr_verify_downgrade.
go

drop table #encrypted_verify_results
drop table #encrypted_table_verify
go
go
exec sp_procxmode 'sp_aux_encr_verify_downgrade', 'anymode'
go
grant execute on sp_aux_encr_verify_downgrade to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_checksource')
begin
	drop procedure sp_checksource
end
go
print "Installing sp_checksource"
go

/* Can be Executed in any database */

/*
** Syntax:
**
** execute sp_checksource with no parameter checks source for every compiled
** object in the current database. This only reserves to user with SA role.
**
** User John can check the source of his procedure john_proc using the 
** following two ways:
**
**	 execute sp_checksource @objname = "john_proc", @username = "John"
** or 
**	 execute sp_checksource @objname = "john_proc"
**
** User John can check the source of all the check constraints and 
** declaractive defaults defined on his table john_tab using the following
** two ways:
**
**	 execute sp_checksource @tabname = "john_tab", @username = "John"
** or 
**	 execute sp_checksource @tabname = "john_tab"
**
** User John can check the source of all the check constraints and declaractive
** defaults defined on this table john_tab2 and also his view john_vu as
** following:
**
**	execute sp_checksource @objname = "john_vu", @tabname = "john_tab2" 
**
** or
**
**	execute sp_checksource @objname = "john_vu", @tabname = "john_tab2" ,
**		@username = "John"
**
** User John can check the source of all the compiled objects owned by him
** using the following way:
**
**	execute sp_checksource @username = "John"
**
** User John can not check the source of Mary's view mary_vu as following:
**
**	execute sp_checksource @objname = "mary_vu". @username = "Mary"
**
** But the user with SA role can do the above.
**
** Parameters:
**	objname - compiled object name
**	tabname - table name
**	username - user name
**
** Returns:
**	1 - if error.
**	0 - if no error.
*/
create procedure sp_checksource
@objname varchar(255) = NULL,
@tabname varchar(255) = NULL,
@username varchar(255) = NULL
as
declare @ret int
execute @ret = sp_aux_text @objname, @tabname, @username, 1
return @ret
go
go
exec sp_procxmode 'sp_checksource', 'anymode'
go
grant execute on sp_checksource to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_column_privileges')
begin
	drop procedure sp_column_privileges
end
go
print "Installing sp_column_privileges"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_column_privileges ( 
                        @table_name  varchar(257),
                        @table_owner varchar(32) = null,
                        @table_qualifier varchar(32)= null,
                        @column_name varchar(257) = null)

as        

    declare @owner_id    		int
    declare @full_table_name    	char(287)
    declare @tab_id 			int	    /* object id of the table specified */

    set nocount on
    /*
    ** set the transaction isolation level
    */
    if @@trancount = 0
    begin
	   set chained off
    end
    else
    begin
		/* we are inside a transaction. catalog procedure sp_column privileges
		** can't be run inside a transaction 
	 	*/
		raiserror 18040, "sp_column_privileges"
		return (1)
    end

    set transaction isolation level 1

    /*
    **  Check to see that the table is qualified with database name
    */
    if @table_name like "%.%.%" 
    begin
		/* 18021, "Object name can only be qualified with owner name" */
		raiserror 18021
		return (1)
    end

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like "#%" and db_name() != db_name(tempdb_id()))
    begin
		/* 
		** 17676, "This may be a temporary object. Please execute 
		** procedure from your temporary database."
		*/
		raiserror 17676
		return (1)
    end

    /*
    ** The table_qualifier should be same as the database name. Do the sanity check
    ** if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
	/* set the table qualifier name */
	select @table_qualifier = db_name ()
    else
    begin
        if db_name() != @table_qualifier
        begin
			raiserror 18039
	     	return (1)
		end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name prefixed
    ** by the owner id
    */
    if (@table_owner is null) or (@table_owner = '')
	        select @full_table_name = @table_name
    else
    begin
	if (@table_name like "%.%") and
	    substring (@table_name, 1, charindex(".", @table_name) -1) != @table_owner
	begin
	 	/* 18011, Object name must be qualified with the owner name * */
		raiserror 18011
		return (1)
	end
	
	if not (@table_name like "%.%")
        	select @full_table_name = @table_owner + '.' + @table_name
	else
	        select @full_table_name = @table_name

    end

    /* 
    ** check to see if the specified table exists or not
    */

    select @tab_id = object_id(@full_table_name)
    if (@tab_id is null)
    begin
		raiserror 17492
		return (1)
    end


    /*
    ** check to see if the @tab_id indeeed represents a table or a view
    */

    if not exists (select * 
                  from   sysobjects
                  where (@tab_id = id) and
	                ((type = 'U') or
                        (type = 'S') or
		        (type = 'V')))
    begin
		raiserror 17492
		return (1)
    end
 

    /*
    ** if the column name is not specified, set the column name to wild 
	** character such it matches all the columns in the table
    */
    if @column_name is null
        select @column_name = '%'

    else
    begin
     /*
	 ** check to see if the specified column is indeed a column belonging
	 ** to the table
	 */
         if not exists (select * 
                        from syscolumns
			where (id = @tab_id) and
			      (name like @column_name))
	 begin
		raiserror 17563, @column_name
		return (1)
	end
    end

   /* Create temp table to store results from sp_aux_computeprivs */
    create table #results_table
	 (table_qualifier	varchar (32),
	  table_owner		varchar (32),
	  table_name		varchar (257),
	  column_name		varchar (257) NULL,
	  grantor		varchar (32),
	  grantee 		varchar (32),
	  privilege		varchar (32),
	  is_grantable		varchar (3))


   /*
   ** declare cursor to cycle through all possible columns
   */
   declare cursor_columns cursor
	for select name from syscolumns 
	    where (id = @tab_id) 
	      and (name like @column_name)

   /*
   ** For each column in the list, generate privileges
   */
   open cursor_columns
   fetch cursor_columns into @column_name
   while (@@sqlstatus = 0)
   begin

	/* 
	** compute the table owner id
	*/

	select @owner_id = uid
	from   sysobjects
	where  id = @tab_id


	/*
	** get table owner name
	*/

	select @table_owner = name 
	from sysusers 
	where uid = @owner_id

	exec sp_aux_computeprivs @table_name, @table_owner, @table_qualifier, 
			     @column_name, 1, @tab_id

	set nocount off 	

	fetch cursor_columns into @column_name
   end

   close cursor_columns
   deallocate cursor cursor_columns

   /* Print out results */ 
   select distinct * into #temp_result from #results_table
   
   exec sp_autoformat @fulltabname = #temp_result,
   @orderby = "order by column_name, grantee"

   drop table #temp_result
   drop table #results_table
return (0)
go
exec sp_procxmode 'sp_column_privileges', 'anymode'
go
grant execute on sp_column_privileges to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_table_privileges')
begin
	drop procedure sp_table_privileges
end
go
print "Installing sp_table_privileges"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_table_privileges ( 
                        @table_name  varchar(257),
                        @table_owner varchar(257) = null,
                        @table_qualifier varchar(257)= null)
as        
 
    declare @owner_id    		int
    declare @full_table_name    	varchar(520)
    declare @tab_id 			int	    /* object id of the table specified */


    set nocount on
    /*
    ** set the transaction isolation level
    */
    if @@trancount = 0
    begin
	   set chained off
    end
    else
    begin
	 /* 18040, "Catalog procedure %1! can not be run in a transaction." */
	 raiserror 18040, "sp_column_privileges"
	 return (1)
    end

    set transaction isolation level 1

    /*
    **  Check to see that the table is qualified with the database name
    */
    if @table_name like "%.%.%"
    begin
	/* 18021, "Object name can only be qualified with owner name." */
	raiserror 18021
	return (1)
    end

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like "#%" and db_name() != db_name(tempdb_id()))
    begin
	/* 
	** 17676, "This may be a temporary object. Please execute 
	** procedure from your temporary database."
	*/
	raiserror 17676
	return (1)
    end


    /*
    ** The table_qualifier should be same as the database name. Do the sanity check
    ** if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
	/* set the table qualifier name */
	select @table_qualifier = db_name ()
    else
    begin
        if db_name() != @table_qualifier
        begin
	     /* 18039, "Table qualifier must be name of current database." */
	     raiserror 18039
	     return (1)
	end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name prefixed
    ** by the owner id
    */
    if (@table_owner is null) or (@table_owner = '')
        select @full_table_name = @table_name
    else
    begin
	if (@table_name like "%.%") and
	    substring (@table_name, 1, charindex(".", @table_name) -1) != @table_owner
	begin
	 	/* 18011, Object name must be qualified with the owner name */
		raiserror 18011
		return (1)
	end
	
	if not (@table_name like "%.%")
        	select @full_table_name = @table_owner + '.' + @table_name
	else
	        select @full_table_name = @table_name
    end

    /* 
    ** check to see if the specified table exists or not
    */

    select @tab_id = object_id(@full_table_name)
    if (@tab_id is null)
    begin
	/* 17492, "The table or view named doesn't exist in the current database." */
	raiserror 17492
	return (1)
    end


    /*
    ** check to see if the @tab_id indeeed represents a table or a view
    */

    if not exists (select * 
                  from   sysobjects
                  where (@tab_id = id) and
	                ((type = 'U') or
                        (type = 'S') or
		        (type = 'V')))
    begin
	/* 17492, "The table or view named doesn't exist in the current database." */
	raiserror 17492
	return (1)
    end

   /* 
   ** compute the table owner id
   */

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id



   /*
   ** get table owner name
   */

    select @table_owner = name 
    from sysusers 
    where uid = @owner_id


   /* Create temp table to store results from sp_aux_computeprivs */
    create table #results_table
	 (table_qualifier	varchar (257),
	  table_owner		varchar (257),
	  table_name		varchar (257),
	  column_name		varchar (257) NULL,
	  grantor		varchar (257),
	  grantee 		varchar (257),
	  privilege		varchar (257),
	  is_grantable		varchar (3))

    exec sp_aux_computeprivs @table_name, @table_owner, @table_qualifier, 
			     NULL, 0, @tab_id

    set nocount off 	

return (0)

go
exec sp_procxmode 'sp_table_privileges', 'anymode'
go
grant execute on sp_table_privileges to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_changegroup')
begin
	drop procedure sp_changegroup
end
go
print "Installing sp_changegroup"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/changegroup */

/*
** Messages for "sp_changegroup"        17370
**
** 17289, "Set your curwrite to the hurdle of current database."
** 17333, "No such group exists."
**      (is now: "No group with the specified name exists.")
** 17232, "No such user exists."
**      (is now: "No user with the specified name exists in the current
** database.")
** 17370, "Group changed."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18776, "Please also run stored procedure '%1!' on the companion server '%2!'."
** 18792, "Unable to find a group with name '%1!' and id '%2!' in sysusers."
** 18793, "Unable to find a user with name '%1!' and id '%2!' in sysusers."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_changegroup
@grpname varchar(30),			/* group name */
@username varchar(30)			/* user name to add to group */
as

declare @gid int			/* group id */
declare @uid int			/* user id */
declare @msg varchar(1024)
declare @id  int			/* object id */
declare @grantee int			/* grantee */
declare @action	smallint		/* action (i.e select, insert) */
declare @protecttype tinyint		/* grant/revoke/option */
declare @columns varbinary (133)		/* column priv bit map */
declare @grantor int			/* grantor */
declare @gcolumns varbinary (133)       /* group column privileges */
declare @pcolumns varbinary (133)	/* public column privileges */
declare @aggrprivs tinyint		/* object level privs of group and public */
declare @aggrcolumns varbinary (133)	/* aggregate of group and public privileges */
declare @col_count smallint
declare @dummy int
declare @dbname varchar(30)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_changegroup', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  Call proc_role() with the required SA role.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("sso_role", show_role()) = 0)
	begin
		select @dummy = proc_role("sa_role")
		select @dummy = proc_role("sso_role")
		return (1)
	end
end

if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")

if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  See if the group name exists.
*/
select @gid = uid from sysusers
where name = @grpname
and (uid = gid)
and not exists (select name from master.dbo.syssrvroles where name = @grpname)

/*
**  If no such group, quit.
*/
if @gid is NULL
begin
	/* 17333, "No group with the specified name exists." */
	raiserror 17333
	return (1)
end

/*
**  See if the user name exists.
*/
select @uid = uid from sysusers
where name = @username
and ((uid >= @@minuserid and uid < @@mingroupid and uid != 0) 
or uid > @@maxgroupid)

/*
**  If no such user in the database, quit.
*/
if @uid is NULL
begin

	/*
	** 17232, "No such user exists."
	*/
	raiserror 17232
	return (1)
end

/*
** At this stage everything is consistent with respect to parameters.
** Now we need to update the GRANTS/REVOKES to the user with respect to
** the new group
*/

begin transaction rs_logexec

/* 
** cursor to find tuples in sysprotect for which grantee is @uid 
*/
declare priv_curs cursor for 
	select id, uid, action, protecttype, columns, grantor
	from sysprotects
	where uid = @uid
	for update

/*
** open the cursor and start fetching from it
*/

open priv_curs

fetch priv_curs into @id, @grantee, @action, @protecttype, @columns, @grantor

/* loop for all qualifying rows */
while (@@sqlstatus != 2)
begin
     if (@@sqlstatus = 1)
     begin
	 /* error in fetching from the cursor */
	raiserror 17333
	rollback transaction rs_logexec
	return (1)
     end

     /*
     ** 193 is SELECT, 197 is UPDATE, 151 is REFERENCES. These are column
     ** level privileges 
     */
     if (((@action != 193) and (@action != 197)) and (@action != 151))
     begin
	  /*
	  ** these are object level privileges 
	  ** Note that grant with grant can't be given to group/PUBLIC thus
	  ** not considered  
          */
	  if (@protecttype = 1)
	  begin
	       /* it is a grant row  */
	       /* initialize aggregate privs */
	       select @aggrprivs = 0

	       /*
	       ** check if this grant is available to public
               */
	       if (exists (select * from sysprotects
		           where (id = @id) and
				 (uid = 0) and
				 (action = @action) and
				 (protecttype = @protecttype) and
				 (grantor = @grantor)))
	       begin
		     select @aggrprivs = 1		    
	       end

	       
	       if (@aggrprivs = 1)
	       begin
		    /* the grant of this privilege is available thru PUBLIC
		       check if there is a revoke to the new group */
	            if (exists (select * from sysprotects
		                where (id = @id) and
				      (uid = @gid) and
				      (action = @action) and
				      (protecttype = 2) and
				      (grantor = @grantor)))
		    begin
			  /* the revoke from group nullifies the grant from 
			     PUBLIC */
			  select @aggrprivs = 0
		    end
	       end
	       else
	       begin
		    /* the privilege was not available thru PUBLIC, check if
		       it is available thru group */
	            if (exists (select * from sysprotects
		                where (id = @id) and
				      (uid = @gid) and
				      (action = @action) and
				      (protecttype = 1) and
				      (grantor = @grantor)))
		    begin
			 /* the privilege is inherited from the group */
			 select @aggrprivs = 1
		    end
	       end


	       /* delete the grant to the user, if inherited due to the 
		  membership in the group or public */

	       if (@aggrprivs = 1)
		begin
			delete from sysprotects where current of priv_curs
	 	end 
	  end
	  else if (@protecttype = 2)
	  begin
	      /* it is a revoke */
	       if ((exists (select * from sysprotects
		           where (id = @id) and
			 	 (uid = @gid) and
				 (action = @action) and
				 (protecttype = @protecttype) and
				 (grantor = @grantor)))
	          or 
		  (not exists (select * from sysprotects
			   where (id = @id) and
				 (uid = @gid or uid = 0) and
				 (action = @action) and
				 (protecttype = 1) and	
				 (grantor = @grantor))))
	       begin
		    /* the privilege is already revoked from the group or there is no
		       explicit grant of this privilege to either group or public, so
		       this revoke row not needed */
			delete from sysprotects where current of priv_curs

		end
	end	
      end
      else
      begin
	   /* column level privileges */
           /* initialize column privilege map for public and group */
	   select @pcolumns = 0x00
	   select @gcolumns = 0x00

           /* get the number of columns in this table. It is only used for
           ** column level privileges 
	   */
           select @col_count = count (*)
           from syscolumns
           where id = @id

	   /* find the column level privileges to PUBLIC */
	   if (exists (select * from sysprotects
		       where (id = @id) and
			     (uid = 0) and
			     (action = @action) and
			     (protecttype = 1) and
		 	     (grantor = @grantor)))
	   begin
		select @pcolumns = columns from sysprotects
		where (id = @id) and
		      (uid = 0) and
		      (action = @action) and
		      (protecttype = 1) and
		      (grantor = @grantor)
	   end

	   /* find the column level privilege to the new GROUP */
	   if (exists (select * from sysprotects
		       where (id = @id) and
			     (uid = @gid) and
			     (action = @action) and
			     (protecttype = 1) and
			     (grantor = @grantor)))
	   begin
		select @gcolumns = columns from sysprotects
		where (id = @id) and
		      (uid = @gid) and
		      (action = @action) and
		      (protecttype = 1) and
		      (grantor = @grantor)
	   end
	      
	  /* find the union of column privileges from public as
	  ** new group  
	  */
	  exec sybsystemprocs.dbo.syb_aux_privunion @pcolumns, @gcolumns, @col_count, @aggrcolumns output

	  /* find if there is a revoke row for the above privilege 
	  ** in the group 
          */
	  select @gcolumns = 0x00
          if (exists (select * from sysprotects
	  	      where (id = @id) and
			    (uid = @gid) and
			    (action = @action) and
			    (protecttype = 2) and
			    (grantor = @grantor)))
	  begin
	       select @gcolumns = columns from sysprotects
	       where (id = @id) and
		     (uid = @gid) and
		     (action = @action) and
		     (protecttype = 2) and
		     (grantor = @grantor)

	  end

          /* subtract the revoke to columns from the group. In order to subtract,
	     exor operation will do as the revoke column bit can only be for columns
	     for which the user has inherited grant */

          exec sybsystemprocs.dbo.syb_aux_privexor @aggrcolumns, @gcolumns, @col_count, @aggrcolumns output

          /* at this stage, aggrcolumns contains the effective column privileges 
	     that are inherited */

	  if (@protecttype = 1)
	  begin
	       /* we encountered an explicit user specific grant row */
	       exec sybsystemprocs.dbo.syb_aux_privnots @aggrcolumns, @col_count, @aggrcolumns output

	       exec sybsystemprocs.dbo.syb_aux_privsand @columns, @aggrcolumns, @col_count, @columns output


	       if (@columns = 0x00)
	       begin
		     /* delete the grant row if no column is left. This implies that
			all explicit user grants were also inherited due to the user's
			membership in the group or PUBLIC */
		     delete sysprotects where current of priv_curs


	       end
	       else
	       begin
		    /* update the list of columns in the grant */
		    update sysprotects set columns = @columns
		    where current of priv_curs
	       end
	  end
	  else if (@protecttype = 2)
	  begin
	       /* it is a revoke row */
	       exec sybsystemprocs.dbo.syb_aux_privsand @columns, @aggrcolumns, @col_count, @columns output
	       /* We only keep those revoke bits for which there is an inherited
		  grant from the user's membership in the group or PUBLIC */
	       if (@columns = 0x00)
	       begin
		     /* delete the revoke row if no column is left */
		     delete sysprotects where current of priv_curs

	       end
	       else
	       begin
		    /* update the list of columns in the revoke */
		    update sysprotects set columns = @columns
		    where current of priv_curs
	       end
	  end
      end
      /*
      ** get the next qualifying tuple 
      */
      fetch priv_curs into @id, @grantee, @action, @protecttype, @columns, @grantor
end	
	
/*
**  Everything is consistent so change the group.
*/
update sysusers
	set gid = @gid
		from sysusers
	where uid = @uid

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_changegroup", @dbname
			
	rollback transaction rs_logexec
	return(1)
end

commit transaction rs_logexec

/*
**  We need to invalidate the protection cache since objects have
**  changed ownership.  This command will invalidate the current
**  protection cache so when protections are checked the new and
**  correct protections will be used.
*/
grant all to null
/*
** 17370, "Group changed."
*/
exec sp_getmessage 17370, @msg output
print @msg



return (0)
go
exec sp_procxmode 'sp_changegroup', 'anymode'
go
grant execute on sp_changegroup to public
go
exec sp_procxmode 'sp_changegroup', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_commonkey')
begin
	drop procedure sp_commonkey
end
go
print "Installing sp_commonkey"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/commonkey */
/*
** Messages for "sp_commonkey"          17390
**
** 17390, "Table or view name must be in 'current' database."
** 17391, "First table in the common key doesn't exist."
** 17392, "Second table in the common key doesn't exist."
** 17393, "Only the table owner may define its common keys."
** 17394, "The tables have no such first column or the columns are of different types."                     
** 17395, "The tables have no such second column or the columns are of different types."                    
** 17396, "The tables have no such third column or the columns are of different types."                     
** 17397, "The tables have no such fourth column or the columns are of different types."
** 17398, "The tables have no such fifth column or the columns are of different types."
** 17399, "The tables have no such sixth column or the columns are of different types."
** 17400, "The tables have no such seventh column or the columns are of different types."
** 17401, "The tables have no such eighth column or the columns are of different types."
** 17402, "New common key added."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17403, "Common key definition already exists between the tables '%1!' and table '%2!' for the specified columns."
*/


/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_commonkey 
@tabaname  varchar(767),	/* name of first table in the key */
@tabbname varchar(767),		/* name of second table in the key */
@col1a     varchar(255), 	/* first column name of first table */
@col1b     varchar(255), 	/* first column name of second table */
@col2a     varchar(255) = NULL,
@col2b     varchar(255) = NULL,
@col3a     varchar(255) = NULL,
@col3b     varchar(255) = NULL,
@col4a     varchar(255) = NULL,
@col4b     varchar(255) = NULL,
@col5a     varchar(255) = NULL,
@col5b     varchar(255) = NULL,
@col6a     varchar(255) = NULL,
@col6b     varchar(255) = NULL,
@col7a     varchar(255) = NULL,
@col7b     varchar(255) = NULL,
@col8a     varchar(255) = NULL,
@col8b     varchar(255) = NULL
as

declare @uida int		/* owner of the first table */
declare @uidb int		/* owner of the second table */
declare @cnt    int		/* how many columns are in the key */
declare @msg    varchar(1024)

declare @key1a int		/* colids of the first table */
declare @key2a int
declare @key3a int
declare @key4a int
declare @key5a int
declare @key6a int
declare @key7a int
declare @key8a int

declare @key1b int		/* colids of the second table */
declare @key2b int
declare @key3b int
declare @key4b int
declare @key5b int
declare @key6b int
declare @key7b int
declare @key8b int
declare @dbname varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see that the tabnames are local.
*/
if @tabaname like "%.%.%"
begin
	if substring(@tabaname, 1, charindex(".", @tabaname) - 1) != db_name()
	begin
		/*
		** 17390, "Table or view name must be in 'current' database."
		*/
		raiserror 17390
		return (1)
	end
end
if @tabbname like "%.%.%"
begin
	if substring(@tabbname, 1, charindex(".", @tabbname) - 1) != db_name()
	begin
		/*
		** 17390, "Table or view name must be in 'current' database."
		*/
		raiserror 17390
		return (1)
	end
end

/*
**  See if we can find the objects.  They must be a system table, user table,
**  or view.  The low 3 bits of sysobjects.sysstat indicate what the 
**  object type is -- it's more reliable than using sysobjects.type which
**  could change.
*/
if not exists (select *
	from sysobjects
		where id = object_id(@tabaname)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3))	/* user table */
/*
**  If either of the tables don't exist, quit.
*/
begin
	/*
	** 17391, "First table in the common key doesn't exist."
	*/
	raiserror 17391
   	return (1)
end 
if not exists (select id
	from sysobjects
		where id = object_id(@tabbname)
			and (sysstat & 7 = 1
				or sysstat & 7 = 2
				or sysstat & 7 = 3))
begin
	/*
	** 17392, "Second table in the common key doesn't exist."
	*/
	raiserror 17392
   	return (1)
end 

/*
**  In order to define a commonkey, the user must be the owner of one of
**  the tables.
*/
select @uida = uid
	from sysobjects
		where id = object_id(@tabaname)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3)	/* user table */

select @uidb = uid
	from sysobjects
		where id = object_id(@tabbname)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3)	/* user table */

if ( @uida != user_id() and @uidb != user_id() )
begin
	/*
	** 17393, "Only the table owner may define its common keys."
	*/
	raiserror 17393
	return (1)
end

/*
**  Now check to see that the first key columns exist and have compatible types.
*/
select @cnt = 1, @key1a = a.colid, @key1b = b.colid
	from syscolumns a, syscolumns b, master.dbo.spt_values y,
		master.dbo.spt_values z
		where a.name = @col1a
			and a.id = object_id(@tabaname)
			and b.name = @col1b
			and b.id = object_id(@tabbname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number
if @key1a is NULL
begin
	/*
	** 17394, "The tables have no such first column or the columns are of different types."
	*/
	raiserror 17394
	return (1)
end

if @col2a is not NULL
begin
	select @cnt = @cnt + 1, @key2a = a.colid, @key2b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col2a
				and a.id = object_id(@tabaname)
				and b.name = @col2b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key2a is NULL
	begin
		/*
		** 17395, "The tables have no such second column or the columns are of different types."
		*/
		raiserror 17395
		return (1)
	end
end
else goto keys_ok

if @col3a is not NULL
begin
	select @cnt = @cnt + 1, @key3a = a.colid, @key3b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col3a
				and a.id = object_id(@tabaname)
				and b.name = @col3b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key3a is NULL
	begin
		/*
		** 17396, "The tables have no such third column or the columns are of different types."                     
		*/
		raiserror 17396
		return (1)
	end
end
else goto keys_ok

if @col4a is not NULL
begin
	select @cnt = @cnt + 1, @key4a = a.colid, @key4b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col4a
				and a.id = object_id(@tabaname)
				and b.name = @col4b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key4a is NULL
	begin
		/*
		** 17397, "The tables have no such fourth column or the columns are of different types."
		*/
		raiserror 17397
		return (1)
	end
end
else goto keys_ok

if @col5a is not NULL
begin
	select @cnt = @cnt + 1, @key5a = a.colid, @key5b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col5a
				and a.id = object_id(@tabaname)
				and b.name = @col5b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key5a is NULL
	begin
		/*
		** 17398, "The tables have no such fifth column or the columns are of different types."
		*/
		raiserror 17398
		return (1)
	end
end
else goto keys_ok

if @col6a is not NULL
begin
	select @cnt = @cnt + 1, @key6a = a.colid, @key6b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col6a
				and a.id = object_id(@tabaname)
				and b.name = @col6b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key6a IS  NULL
	begin
		/*
		** 17399, "The tables have no such sixth column or the columns are of different types."
		*/
		raiserror 17399
		return (1)
	end
end
else goto keys_ok

if @col7a is not NULL
begin
	select @cnt = @cnt + 1, @key7a = a.colid, @key7b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col7a
				and a.id = object_id(@tabaname)
				and b.name = @col7b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key7a is NULL
	begin
		/*
		** 17400, "The tables have no such seventh column or the columns are of different types."
		*/
		raiserror 17400
		return (1)
	end
end
else goto keys_ok

if @col8a is not NULL
begin
	select @cnt = @cnt + 1, @key8a = a.colid, @key8b = b.colid
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
			where a.name = @col8a
				and a.id = object_id(@tabaname)
				and b.name = @col8b
				and b.id = object_id(@tabbname)
				and y.type = "J"
				and a.type = y.low
				and z.type = "J"
				and b.type = z.low
				and y.number = z.number
	if @key8a is NULL
	begin
		/*
		** 17401, "The tables have no such eighth column or the columns are of different types."
		*/
		raiserror 17401
		return (1)
	end
end

/*
**  If we made it this far then all the columns for the common key are ok.
**  Everything is consistent so add the common key to syskeys.
*/
keys_ok:

/*
** Before we insert a new common key relationship, check if a duplicate
** one exists. If so, fail this new insert. We are allowed to only have
** one common key relationship defined for a set of tables on the same
** set of columns. In case of common key relationships, users can define
** one even on a table that they don't own. So we have to check for the
** existence of a row for both 'tabaname' and 'tabbname'. [ See below where
** the INSERT is done. ]
*/
/*
** User owns 'tableA'. So if there was a relationship defined earlier, it
** would have been [from id] tableA -> [to depid] tableB. Check if one 
** such row exists.
*/
if (@uida = user_id())
begin
    if exists (select 1 from syskeys
		   where id 		= object_id(@tabaname)
		     and type 		= 3
		     and depid		= object_id(@tabbname)
		     and keycnt		= @cnt
		     and size		= 0
		     and key1		= @key1a
		     and key2		= @key2a
		     and key3		= @key3a
		     and key4		= @key4a
		     and key5		= @key5a
		     and key6		= @key6a
		     and key7		= @key7a
		     and key8		= @key8a

		     and depkey1	= @key1b
		     and depkey2	= @key2b
		     and depkey3	= @key3b
		     and depkey4	= @key4b
		     and depkey5	= @key5b
		     and depkey6	= @key6b
		     and depkey7	= @key7b
		     and depkey8	= @key8b
	  )
	begin
		raiserror 17403, @tabaname, @tabbname
		return (1)
	end
end
/*
** User owns 'tableB'. So if there was a relationship defined earlier, it
** would have been [from id] tableB -> [to depid] tableA. Check if one
** such row exists.
*/
else if exists (select 1 from syskeys
		   where id 		= object_id(@tabbname)
		     and type 		= 3
		     and depid		= object_id(@tabaname)
		     and keycnt		= @cnt
		     and size		= 0
		     and key1		= @key1b
		     and key2		= @key2b
		     and key3		= @key3b
		     and key4		= @key4b
		     and key5		= @key5b
		     and key6		= @key6b
		     and key7		= @key7b
		     and key8		= @key8b

		     and depkey1	= @key1a
		     and depkey2	= @key2a
		     and depkey3	= @key3a
		     and depkey4	= @key4a
		     and depkey5	= @key5a
		     and depkey6	= @key6a
		     and depkey7	= @key7a
		     and depkey8	= @key8a
	  )
	begin
		raiserror 17403, @tabbname, @tabaname
		return (1)
	end

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction	
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

if @uida = user_id()
begin
	insert syskeys (id, type, depid, keycnt, size,
		key1, key2, key3, key4, key5, key6, key7, key8,
		depkey1, depkey2, depkey3, depkey4, depkey5, depkey6,
		depkey7, depkey8, spare1)
	values (object_id(@tabaname), 3, object_id(@tabbname), @cnt, 0,
		@key1a, @key2a, @key3a, @key4a, @key5a, @key6a, @key7a, @key8a,
		@key1b, @key2b, @key3b, @key4b, @key5b, @key6b,
		@key7b, @key8b, 0)
end
else
begin

/*
**  The user owns the second table but not the first.  In this case, we need
**  to invert the entries inserted into syskeys.  This is done to
**  keep things consistent for the sp_dropkey procedure.
*/
	insert syskeys (id, type, depid, keycnt, size,
		key1, key2, key3, key4, key5, key6, key7, key8,
		depkey1, depkey2, depkey3, depkey4, depkey5, depkey6,
		depkey7, depkey8, spare1)
	values (object_id(@tabbname), 3, object_id(@tabaname), @cnt, 0,
		@key1b, @key2b, @key3b, @key4b, @key5b, @key6b, @key7b, @key8b,
		@key1a, @key2a, @key3a, @key4a, @key5a, @key6a,
		@key7a, @key8a, 0)
end

if (@@error != 0)
begin
	rollback transaction rs_logexec
	return(1)
end

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_commonkey", @dbname
				
	rollback transaction rs_logexec
	return(1)
end

commit transaction

/*
** 17402, "New common key added."
*/
exec sp_getmessage 17402, @msg output
print @msg

return(0)

go
exec sp_procxmode 'sp_commonkey', 'anymode'
go
grant execute on sp_commonkey to public
go
exec sp_procxmode 'sp_commonkey', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_cursorinfo')
begin
	drop procedure sp_cursorinfo
end
go
print "Installing sp_cursorinfo"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

create procedure sp_cursorinfo 
@cursor_level int = null,		/* nesting level for cursor */
@cursor_name  varchar(30) = null	/* cursor name */
as

	if @@trancount = 0
	begin
		set chained off
	end
	set transaction isolation level 1

	/* set cursor level to -1 to get cursor info for all nesting levels */
	if @cursor_level is null
		select @cursor_level = -1

	/* Do the work */
	dbcc cursorinfo(@cursor_level, @cursor_name)

return(0)

go
exec sp_procxmode 'sp_cursorinfo', 'anymode'
go
grant execute on sp_cursorinfo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_deviceattr')
begin
	drop procedure sp_deviceattr
end
go
print "Installing sp_deviceattr"
go


/*
** Messages for "sp_deviceattr"         17482
**
** 17260, "Can't run %1! from within a transaction." 
** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices."
** 19104, "'%1!' attribute of device '%2!' turned '%3!'. Restart Adaptive 
**	   Server for the change to take effect."
** 18807, "Changing attribute for master or HA master_companion device is not allowed"
** 18683, "The device %1! is not a disk device."
** 18684, "Usage: sp_deviceattr device_name, %1!, { true | false }"
** 18685, "The attribute %1! is already turned %2!"
** 19389, "The attributes %1! and %2! can not be both set to ON for the same device."
** 19608, "No such parameter: '%1!'"
** 19641, "Warning: '%1!', is a file system device.
**          A system failure may cause data loss if the dsync is set to false."
** 19642, "Warning: Sybase recommends not to use '%1!' as a database device,
**          because it is a block device and may cause data loss in case of system failure."
** 19975, "You cannot set attribute %1! for %2! device '%3!'."
*/

create procedure sp_deviceattr
(
@logicalname	varchar(30),	/* logical name of the device */
@optname	varchar(10),	/* name of the parameter: "dsync", "directio" */
@optvalue	varchar(10)	/* the value of the dsync/directio flag: true or false */
)
as
declare @status 	int	/* status bit for the device */
declare @status1 	int	/* status bitmap for the device */
declare @status2 	int	/* status2 bitmap for the device */
declare @whichstat	tinyint /* indicates which status field to store */
declare @disk_device	int	/* disk device identifier */
declare @optbitvalue	int	/* the dsync/directio flag */
declare @msg 	varchar(1024)	/* temp buffer for messages */
declare @chg_attr_value	char(3)	/* denotes if the attribute is on or off */
declare @directio_support int   /* direct io support on current platform */
declare @phyname varchar(100)  /* device physical path */
declare @devicetype     int     /* temp buffer for to store type of device */
declare @platform varchar(30)  /* temp buffer to store platform name*/

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_deviceattr"
	return (1)
end

else
begin
	set chained off
end

set transaction isolation level 1

/*
** check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
 ** Disallow the user to change the status of the master or the HA
 ** master_companion device. The use of @@cmpstate here is to distinguish
 ** a master_companion device from a HA failover and a non-HA user
 ** created one. It is possible for user to create a device named
 ** "master_companion" in a non-HA ASE.
 */
if ((@logicalname = "master")
    or ((@logicalname = "master_companion") and (@@cmpstate in (4,12))))
begin
	/*
	** 18807, "Changing attribute for master or HA master_companion
	** device is not allowed."
	*/
	raiserror 18807
	return (1)
end

/*  Check and make sure that the device actually exists. */
if not exists (select * 
		from master.dbo.sysdevices
			where name = @logicalname)
begin
	/*
	** 17471, "No such device exists -- run sp_helpdevice to list
	** the DataServer devices." 
	*/
	raiserror 17471
	return (1)
end

select @phyname = phyname, @status1 = status, @status2 = status2
	from master.dbo.sysdevices 
		where name = @logicalname

/* get device type; 1 - character special, 2 - block special, 3 - file system */
select @devicetype = getdevicetype(@phyname)

/* get platform info from spt_values table */
select @platform = name from master.dbo.spt_values
                        where type='E' and number=1

/* warn block device usage on all platforms except hp , nt and linux*/
if ( @devicetype = 2 and @platform not in ("hp9000/800","nt386","linux") )
begin
	exec sp_getmessage 19642, @msg output
        print @msg, @phyname
end

/* InitIalize status bits. */
select @disk_device = 2

/* Check that the name of the device is a disk device. */
if ((@status1 & @disk_device) != @disk_device)
begin
	
	/* 18683, "The device %1! is not a disk device." */
	raiserror 18683, @logicalname
	return (1)
end

/* Check that there is no syntax error in the command line */

if lower(@optname) not in ("dsync","directio") or lower(@optvalue) not in
		("true","false")
begin
	/* 18684, "Usage: sp_deviceattr device_name, %1!, { true | false }" */
	raiserror 18684, "dsync | directio"	
	return (1)

end

if (lower(@optname) = "dsync")
begin
	if ((lower(@optvalue) = "true") and (@devicetype = 1))
	begin
		/*
		** 19975, "You cannot set attribute %1! for %2! device '%3!'."  
		*/
		raiserror 19975,"dsync","raw",@logicalname
		return(1)
	end
	if ((lower(@optvalue) = "true") and ((@status2 & 1) = 1))
	begin
		/*
		** 19389, "The attributes %1! and %2! can not 
		** be both set to ON for the same device."
		*/
		raiserror 19389,@optname,"directio"
		return(1)
	end
	select @whichstat = 1
	select @status = @status1
	select @optbitvalue = 16384
end
else	if (lower(@optname) = "directio")
begin
	select  @directio_support=low from master.dbo.spt_values
		where name="directio" and type="io"
	/* check for directio support on current platform */ 
	if ( @directio_support = 0 )
	begin
		/*
		** 19608, "No such parameter: '%1!'"  
		*/
		raiserror 19608,"directio" 
		return(1)
	end
	if ((lower(@optvalue) = "true") and (@devicetype = 1))
	begin
		/*
		** 19975, "You cannot set attribute %1! for %2! device '%3!'."
		*/
		raiserror 19975,"directio","raw",@logicalname
		return(1)
	end
	if ((lower(@optvalue) = "true") and ((@status1 & 16384) = 16384))
	begin
		/*
		** 19389, "The attributes %1! and %2! can not 
		** be both set to ON for the same device."
		*/
		raiserror 19389,@optname,"dsync"
		return(1)
	end
	select @whichstat = 2
	select @status = @status2
	select @optbitvalue = 1
end

if  (lower(@optvalue) = "true")

begin
	if ((@status & @optbitvalue) = @optbitvalue)
	begin
		/* 18685, "The attribute %1! is already turned %2!" */
		raiserror 18685,@optname,"on" 
		return(1)
	end
        else
	begin
		/* The user wants to turn on the  o_dsync flag */
		select @status = (@status | @optbitvalue)
	end

	select @chg_attr_value = "on"
end
else	if (lower(@optvalue) = "false")
begin
	if ((@status & @optbitvalue) != @optbitvalue)
	begin
		/* 18685, "The attribute %1! is already turned %2!" */
		raiserror 18685,@optname,"off"
		return(1)
	end
	else
	begin
		/* The user wants to turn off the o_dsync flag */
		select @status = (@status & ~@optbitvalue)
		/* warn the user , if he is using file system device with dsync off */
		if ( ( @devicetype = 3) and (lower(@optname) = "dsync") )
		begin
			exec sp_getmessage 19641, @msg output
			print @msg, @phyname
		end
	end

	select @chg_attr_value = "off"
end 
 
/* Validation passed, now update the status in sysdevices table. */
if (@whichstat = 1)
begin
	update master.dbo.sysdevices set status = @status where name = @logicalname
end
else if (@whichstat = 2)
begin
	update master.dbo.sysdevices set status2 = @status where name = @logicalname
end

/*
** 19104, "'%1!' attribute of device '%2!' turned '%3!'. Restart Adaptive 
**	   Server for the change to take effect."
*/
exec sp_getmessage 19104, @msg output
print @msg, @optname, @logicalname, @chg_attr_value

return (0)
go
exec sp_procxmode 'sp_deviceattr', 'anymode'
go
grant execute on sp_deviceattr to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_defaultdb')
begin
	drop procedure sp_defaultdb
end
go
print "Installing sp_defaultdb"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.2	28.1	05/14/90	sproc/src/defaultdb */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:15 2006 
*/
/*
** raiserror Messages for defaultdb [Total 7]
**
** 17231, "No login with the specified name exists."
** 17260, "Can't run %1! from within a transaction."
** 17440, "Database name not valid -- default not changed."
** 17443, "Error in updating the default database."
** 17445, "Cannot change default database since login trigger for user '%1!' is currently active."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 18388, "You must be in the master database in order to run '%1!'."
** 18409, "The built-in function %1! failed. Please see the other messages printed along with this message."
** 19822, "A local temporary database is not permitted as the default database for a login."
*/
/*
** sp_getmessage Messages for defaultdb [Total 4]
**
** 17442, "Default database changed."
** 17444, "Automatic login script for user '%1!' is disabled. Use sp_modifylogin to enable execution of auto login script for the new database."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_defaultdb
@loginame varchar(30),			/* login name of the user */
@defdb varchar(30) 			/* default db for the user */
as

declare @msg varchar(1024)
declare @rtn_code int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @dummy int
declare @sa_role int	/* has sa role */
declare @sso_role int	/* has sso role */

declare @log_for_rep int
declare @db_rep_level_all int
declare @db_rep_level_none int
declare @db_rep_level_l1 int
declare @lt_rep_get_failed int

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2

select @HA_CERTIFIED = 0

select @sa_role = charindex("sa_role", show_role()),
	@sso_role = charindex ("sso_role", show_role())



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_defaultdb', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_defaultdb"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_defaultdb"
	return (1)
end

/*
**  Only the Account Owner or
**  Accounts with SA role or SSO role can execute it.
**  proc_role will also do auditing if required and
**  will also print error message if required.
*/
if ((suser_name() != @loginame) and
		(@sa_role = 0) and (@sso_role = 0))
begin
	select @dummy = proc_role("sa_role")
	select @dummy = proc_role("sso_role")
	return(1)
end
else
begin
	if (@sa_role > 0)
	begin
		select @dummy = proc_role("sa_role")
	end
	if (@sso_role > 0)
	begin
		select @dummy = proc_role("sso_role")
	end
end

/*
**  Check that the account exists.
*/
if not exists (select *
	from master.dbo.syslogins
	where name = @loginame)
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return (1)
end

/*
**  Check that the database name is valid.
*/
if not exists (select *
	from master.dbo.sysdatabases
	where name = @defdb)
begin
	/*
	** 17440, "Database name not valid -- default not changed."
	*/
	raiserror 17440
	return (1)
end

/*
**  Check that the database name is useable on all instances of cluster.
**  If specified default database is a local temporary database then
**  fail the command to avoid problems at connection time.
*/
if db_instanceid(db_id(@defdb)) is not null
begin
	/*
	** 19822, "A local temporary database is not permitted as the 
	** default database for a login."
	*/
	raiserror 19822
	return (1)
end



	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



/*
** User cannot change the default database if automatic login script
** is enabled.
*/
if exists ( select * from master.dbo.syslogins
		where name = @loginame  and procid is not NULL )
begin
	/*
	** 17445, "Cannot change default database since login trigger for
	** user '%1!' is currently active."
	*/
	exec sp_getmessage 17445, @msg output
	print @msg, @loginame
	return (1)
end

/*
**  Change the database
*/

update master.dbo.syslogins
	set dbname = @defdb, procid = NULL
	where name = @loginame

if @@rowcount = 1
	select @rtn_code = 0
else
	select @rtn_code = 1



if (@rtn_code = 0)
begin
	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_defaultdb", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec

	/*
	** 17442, "Default database changed." 
	*/
	exec sp_getmessage 17442, @msg output
	print @msg
	return (0)
end
else
begin
	/*
	** 17443, "Error in updating the default database."
	*/
	raiserror 17443
	goto clean_all
end

return (0)

clean_all:
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		rollback tran rs_logexec
        return (1)

go
exec sp_procxmode 'sp_defaultdb', 'anymode'
go
grant execute on sp_defaultdb to public
go
exec sp_procxmode 'sp_defaultdb', 'rep_master'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_databases')
begin
	drop procedure sp_databases
end
go
print "Installing sp_databases"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

create procedure sp_databases
as

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* Use temporary table to sum up database size w/o using group by */
	create table #databases (
				  database_name varchar(32),
				  size int)

	/* Insert row for each database */
	insert into #databases
		select
			name,
			(select sum(size) from master.dbo.sysusages
				where dbid = d.dbid)
		from master.dbo.sysdatabases d

	select
		 database_name,
				/* Convert from number of pages to K */
		 database_size = size * (@@maxpagesize / 1024),
		 remarks = convert(varchar(254),null)	/* Remarks are NULL */
	from #databases

	return(0)
go
go
exec sp_procxmode 'sp_databases', 'anymode'
go
grant execute on sp_databases to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dbremap')
begin
	drop procedure sp_dbremap
end
go
print "Installing sp_dbremap"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */

/*
** Messages for "sp_dbremap"      17550
**
** 17260, "Can't run %1! from within a transaction."
** 17284, "'%1!' is not a valid identifier."
** 17590, "The specified database does not exist."
** 18336, "Permission denied. Your curwrite label must be
**	   set at the hurdle of the affected database."
*/

create procedure sp_dbremap
@dbname varchar(30)	/* name of database whose diskmap is to be remapped */
as

declare @procval int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
** Check for valid identifier.
*/
if valid_name(@dbname) = 0
begin
	/*
	** 17284, "'%1!' is not a valid identifier."
	*/
	raiserror 17284, @dbname
	return (1)
end


/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  if user  had SA role he would be the dbo hence check only
**  whether user is DBO.
**  Call proc_role() with the required SA role.
*/
if (user_id() = 1)
begin    
        /* If user has sa role audit this as a successful sa
        ** command execution.
        */
        if charindex("sa_role",show_role()) > 0
                select @procval = proc_role("sa_role")
end
else 
begin
        /* user_id() is not DBO hence user does not have SA role
        ** audit this as a failed sa command execution.
        */
        select @procval = proc_role("sa_role")
        return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
 	*/
	raiserror 17260, "sp_dbremap"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see if the database exists.
*/
if not exists (select *
		from master.dbo.sysdatabases
			where name = @dbname)
begin
	/*
	** 17590, "The specified database does not exist."
	*/
	raiserror 17590
	return (1)
end



/*
**  Now go ahead and update the in-core image of the database usage map table.
*/
dbcc dbrepair (@dbname, remap)


return (0)
go
exec sp_procxmode 'sp_dbremap', 'anymode'
go
grant execute on sp_dbremap to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_remap')
begin
	drop procedure sp_remap
end
go
print "Installing sp_remap"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** 17732, "You do not own table '%1!'."
** 17461, "Object does not exist in this database."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/
CREATE PROCEDURE sp_remap
@objname 	varchar(92)		/* object to remap */
AS

/*
**	Local variables here
*/
DECLARE @procid		int,		/* object id of the procedure */
	@site		varchar(255),
	@dbname		varchar(255),
	@uname		varchar(255),
	@procname	varchar(255),
	@other_owner	int


IF @@trancount = 0
BEGIN
	SET chained off
END

SET transaction isolation level 1

/*
** Initialize some local variables.
*/
select @procid		= NULL
select @site		= NULL
select @dbname		= NULL
select @uname		= NULL
select @procname	= NULL
select @other_owner	= 0

/*
** Crack the name passed in.
*/
EXECUTE sp_namecrack	@objname, @site OUTPUT, @dbname OUTPUT,
			@uname OUTPUT, @procname OUTPUT

/*
**  Make sure that the user specified an object in this
**  database.
*/
IF (@dbname is not NULL AND @dbname != db_name())
BEGIN
	/* 17461, "Object does not exist in this database." */
	raiserror 17461
	RETURN (1)
END

/*
**  Make sure that, if the user specified an object owned
**  by somebody other than him/herself, that user has the
**  proper permissions to remap that object.
*/
IF (@uname is NULL)
BEGIN
	/*
	** By normal SQL Server object resolution standards,
	** this means the object is owned either by the user
	** *or* by the dbo (if the user doesn't own an object
	** with the given name).  Let's check for the
	** DBO case.
	*/
	IF (object_id(user_name() + "." + @procname) is NULL)
	BEGIN
		/*
		**  Check if the object really doesn't exist
		**  before causing an audit record to be sent.
		*/
		if((user_id() = 1) OR
		   (object_id("dbo." + @procname) is NULL))
		BEGIN
			/*
			** The object really doesn't exist.
			*/
			/*
			** 17461, "Object does not exist
			**	   in this database."
			*/
			raiserror 17461
			RETURN (1)
		END
		select @other_owner = 1
	END
END		
ELSE
BEGIN
	IF (user_name() != @uname)
	BEGIN
		/*
		**  Check if the object really doesn't exist
		**  before causing an audit record to be sent.
		*/
		IF(object_id(@uname + "." + @procname) is NULL)
		BEGIN
			/*
			** The object really doesn't exist.
			*/
			/*
			** 17461, "Object does not exist
			**	   in this database."
			*/
			raiserror 17461
			RETURN (1)
		END
		SELECT @other_owner = 1
	END
END

IF (@other_owner = 1)
BEGIN
	/*
	** The user specified somebody else's object.  This
	** user must possess SA role in order to proceed.
	*/
	IF (proc_role("sa_role") = 0)
	BEGIN
		RETURN 1
	END
END

/*
**  Get the object id.
*/
SELECT @procid  = id
FROM   sysobjects
WHERE  name = @procname
       AND (uid = user_id() OR user_id() = 1)
       AND type IN ('V ', 'P ', 'R ', 'D ', 'TR', 'IT')

/*
**  If the object doesn't exist, return.
*/
IF @procid is NULL
BEGIN
	/* 17461, "Object does not exist in this database." */
	raiserror 17461
	RETURN (1)
END

/*
**	Obtain current database information
*/
SELECT @dbname = db_name()

/*
**  Do the actual remap here now that we have the object id.
**  The command is run in the current database.
*/

DBCC REMAP(@procid, @dbname, 1)

go
go
exec sp_procxmode 'sp_remap', 'anymode'
go
grant execute on sp_remap to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_depends_cols')
begin
	drop procedure sp_depends_cols
end
go
print "Installing sp_depends_cols"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Create a dummy definition of this table so that we can install this
** sproc. This table is created at run-time in sp_depends.
*/
if ((select object_id("#column_depends")) is not NULL)
begin
	drop table #column_depends
end
go

create table #column_depends (
	  Type 		varchar(23)
	, Property	varchar(11)
	, Dependency 	varchar(255)	-- @Depend_col_length
	, Column	varchar(255)
	, AlsoSee	varchar(100)
) lock allpages
go

/*
** Messages for "sp_depends_cols"
**
** There are no messages for this sproc. Its an 'internal' sproc, and only
** inserts output rows into a #temp table. The only message raised by this
** sproc is a generic one as follows:
**
** 17563, "The table does not have a column named '%1!'."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
**
** This is an internally used sproc called by sp_depends. The interface for
** this is not documented, and cannot be directly invoked by the user.
*/

create procedure sp_depends_cols
  @objname varchar(767)			/* the object we want to check */
, @column_name varchar(255) = null	/* the column we want to check */
, @findTableLevelConstraints int = 0	/* default is first call when user has
					** specified column name to sp_depends.
					** Otherwise, sp_depends will call us
					** iteratively for each column.
					*/
as

declare   @indid	int
	, @keycnt	int 		/* # of keys in index */
	, @colid 	int		/* column id from syscolumns */
	, @cdefault	int		/* default id from syscolumns */
	, @domain	int		/* rule/check constraint from syscolumns */
	, @accessrule	int		/* accessrule from syscolumns */
	, @repstatus	int		/* status from syscolumns, to infer
					** replication status of column
					*/
	, @colidarray	varbinary(100)	/* column id array from sysstatistics */
	, @col_index	tinyint		/* index to parse colidarray 
					** from sysstatistics. That array is
					** 100 bytes, so tinyint will suffice.
					*/
	, @statstring	varchar(256)	/* used for formatting column lists */
	, @statcolumn	varchar(255)
	, @statcount	tinyint
	, @objid 	int
	, @id 		int
	, @type 	tinyint
	, @depid 	int
	, @frgndbname 	varchar(30)
	, @constrid 	int
	, @reftabid 	int
	, @key1		int   		/* these are keys for checking syskeys */
	, @key2		int
	, @key3		int
	, @key4		int
	, @key5		int
	, @key6		int
	, @key7		int
	, @key8		int
	, @depkey1	int
	, @depkey2	int
	, @depkey3	int
	, @depkey4	int
	, @depkey5	int
	, @depkey6	int
	, @depkey7	int
	, @depkey8	int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
set nocount on

/* 
** Column name should have been provided. Check that it exists in the
** said table. (Also used to initialize @cdefault, @domain @accessrule 
** etc. below.)
*/
if @column_name is not null
begin
	select @objid = object_id(@objname)

	select @colid = colid, @cdefault = cdefault, @domain = domain
		, @accessrule = accessrule, @repstatus = status
	from syscolumns 
	where id = @objid and name = @column_name

	if (@colid is NULL)
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @column_name
		return (1)
	end
end
else
begin
	/*
	** This is an unexpected error. sp_depends will always provide
	** a column name. In any case, report a useful error.
	*/
	raiserror 17563, @column_name
	return (1)
end
/*
** =========================================================================
** Start of column level dependency processing.
** =========================================================================
*/

declare @Depend_col_length int

-- Length of Dependency column in output table
select @Depend_col_length = 255

/* 
** =========================================================================
** Report replication status of column.
**
** Note that @repnever, @repalways, @repifchanged are never translated
** into local languages, so it is safe to declare them as varchar(30)
** rather than extend them to varchar(1024).
*/
declare	  @texttype	int
	, @imagetype	int
	, @javacoltype	int
	, @rep_constant	smallint
	, @offrowstat	int
	, @repnever 	varchar(30)
	, @repalways	varchar(30)
	, @repifchanged	varchar(30)

select	@texttype = 34, @imagetype = 35, @javacoltype = 36

	-- Replication enabled flag is 0x8000 (which is -32768D)
	, @rep_constant = -32768
	, @offrowstat = 1

/*
** Initialize strings to specify replication status
*/
exec sp_getmessage 18111, @repnever out		-- "do_not_replicate"
exec sp_getmessage 18112, @repalways out	-- "always_replicate"
exec sp_getmessage 18113, @repifchanged out	-- "replicate_if_changed"

insert into #column_depends
select    case when c.type = @javacoltype then "Java column replication"
	       when c.type in (@texttype, @imagetype) then "Text/image replication"
	       else ""
	  end
	, "replication"
	, case (c.status & 3)
		when 0 then @repnever
		when 1 then @repalways
		when 2 then @repifchanged
		else " "
	  end
	, c.name
	, "sp_setrepcol, sp_setreptable"
from syscolumns c
where c.id = @objid

  and (select (sysstat & @rep_constant)	-- replication status for table
       from sysobjects
       where id = @objid) != 0		-- => object is replicated (If object
					-- is not replicated, do not output
					-- any replication info.)
  and c.colid = @colid
					-- Only extract rows for text/image
					-- columns, or off-row Java columns.
  and (c.type in (@texttype, @imagetype)
       or (c.type =  @javacoltype and c.xstatus & @offrowstat = @offrowstat) )
  and (c.status & 3) in (0,1,2)

/* 
** =========================================================================
** Report any indexes on the column.
** Initialize @indid, and search the sysindexes column list for
** all indexes on the table for the specified column. 
**
** Since the status2 column in sysindexes means a foreign key
** reference exists for the column, we'll handle those here too.
*/
select @indid = 0

while @indid is not null
begin						-- { start of indid check
	select @indid = min(indid)
	from sysindexes
	where id = object_id(@objname)
	  and indid > @indid
	  and indid < 255

	-- Account for the RID key in the keycnt for non-clust indexes.
	-- (indid > 1 for non-clustered indexes)
	--
	select @keycnt = case when @indid > 1 then (keycnt - 1)
				else keycnt
			 end
	from sysindexes
	where id = object_id(@objname)
	  and indid = @indid
	
	/*
	**  First we'll figure out what the index keys are.
	*/
	declare @i 		int,
		@found_depind	int,
		@status2	int,		-- From sysindexes
		@keyname 	varchar(255),	-- Name of index key column
		@indkeys_str	varchar(256),	-- List of index key columns
		@found_fkref	int		-- Found an index which has
						-- foreign key references from
						-- another table.

	select @i = 1, @keyname = "start work", @indkeys_str = NULL
		, @found_depind = 0

	while (@i <= @keycnt)
	begin 					-- { start of "keys" while loop

		-- Find out the current key column's name.
		select    @keyname = index_col(@objname, @indid, @i)

		select @indkeys_str = @indkeys_str +
					case @indkeys_str
						when NULL then " (" + @keyname
						else ", " + @keyname
					end

		if (@keyname = @column_name)
		begin 			-- { start of "if found column name"

			select @found_depind = 1

			/* 
			** This detects foreign key references from other
			** tables and prints the name of the foreign key
			** constraint. Since very long DB + table + constraint
			** names are longer than the #column_depends
			** column size, use special handling for the lengths.
			**
			** References to other tables are detected in another 
			** section. 
			*/
			if (select (status2 & 1) from sysindexes
			    where id = object_id(@objname)
			      and indid = @indid) = 1
			begin

				-- Remember that we found an index defined
				-- as a foreign key reference. We'll use this
				-- boolean to scan sysreferences later on.
				--
				select @found_fkref = 1
			end
		end 			-- } end of "if found column name"

		/*
		**  Increment @i so it will check for the next index key column.
		*/
		select @i = @i + 1

	end 					-- } end of "keys" while loop

	-- If we found a dependent index, output its info.
	if (@found_depind = 1)
	begin
		-- Prefix index name to string of key names.
		--
		select @indkeys_str = name + @indkeys_str + ")"
			, @status2 = status2
		from sysindexes
		where id = object_id(@objname)
		and indid = @indid

		-- Populate result table w/info on index on this column
		insert into #column_depends values
			("index"
			 , case	when (@status2 & 2 = 0) then "index"
				when (@status2 & 2 = 2) then "constraint"
			   end
			  , case
				when (datalength(@indkeys_str) >
					@Depend_col_length)

				-- Truncate string and append with '...)'
				then convert(char(251), @indkeys_str) + "...)"
				else @indkeys_str
			    end
			, @column_name
			, "sp_helpindex, drop index, sp_helpconstraint, alter table drop constraint"
			)
	end
end 						-- } end of indid check

/*
** =========================================================================
** If we found even one index defined as a foreign key reference containing
** the column of interest as an index key, then scan sysreferences to collect
** names of the foreign key reference, and populate the output table.
*/
if (@found_fkref = 1)
begin
	declare @foreignkey_str	varchar(255)

	-- See if this column appears as a foreign 
	-- key column from sysreferences.
	--
	declare fkref cursor for
	select frgndbname, constrid, tableid
	from sysreferences
	where reftabid = object_id(@objname)
	  and ( refkey1  = @colid or
		refkey2  = @colid or
		refkey3  = @colid or
		refkey4  = @colid or
		refkey5  = @colid or
		refkey6  = @colid or
		refkey7  = @colid or
		refkey8  = @colid or
		refkey9  = @colid or
		refkey10 = @colid or
		refkey11 = @colid or
		refkey12 = @colid or
		refkey13 = @colid or
		refkey14 = @colid or
		refkey15 = @colid or
		refkey16 = @colid)

	open fkref
	fetch fkref into @frgndbname, @constrid, @reftabid

	while (@@sqlstatus != 2)
	begin 					-- { start of fkref cursor loop
		select @foreignkey_str = 
			case 
			  when (@frgndbname is NULL)
				then object_name(@constrid)
					+ " on " + object_name(@reftabid)
			  else 	@frgndbname
				+ ".."
				+ object_name(@reftabid, db_id(@frgndbname))
				+ " "
			  	+ object_name(@constrid, db_id(@frgndbname))
			end

		insert into #column_depends
		select   "foreign key reference"
			, "constraint"
			, @foreignkey_str
			, @column_name
			, "sp_helpconstraint, alter table drop constraint"

		fetch fkref into @frgndbname, @constrid, @reftabid
	end 					-- } end of fkref cursor loop

	close fkref
	deallocate cursor fkref
end

/*
** =========================================================================
** Defaults:
**	Procedural	Created by sp_addefault, sp_bindefault.
**	Declarative	Created by specifying the default clause in the
**			CREATE/ALTER TABLE statements.
*/
if (@cdefault != 0)
begin
	insert into #column_depends 
	select "default"
		, case when (pr.status & 4096 = 4096)
		       then "declarative"
		       else "procedural"
		  end
		, object_name(col.cdefault) 
		, @column_name
		, "sp_help, " + case when (pr.status & 4096 = 4096)
				     then "alter table drop constraint"
				     else "sp_unbindefault"
				end
	from syscolumns col, sysprocedures pr
	where col.id = object_id(@objname)
	  and col.colid = @colid
	  and col.name = @column_name
	  and col.cdefault = pr.id 
	  and pr.sequence = 1
end

/* 
** =========================================================================
** Rules:
** Get the rules, with ID's stored in syscolumns.domain, or 
** syscolumns.accessrule.
** Eliminate the check constraints, the next step locates them.
*/
if ( @domain != 0 )
begin
	insert into #column_depends 
	select "rule", "procedural", object_name(col.domain)
		, @column_name
		, "sp_help, sp_unbindrule"
	from syscolumns col
	where col.id = object_id(@objname)
	  and col.name = @column_name
	  and col.domain not in (select constrid from sysconstraints con
			      	 where con.colid = @colid
				   and con.tableid = object_id(@objname)
				   and status = 128)
end

if ( isnull(@accessrule,0) != 0 )
begin
        insert into #column_depends
        select "accessrule", "procedural", object_name(col.accessrule)
                , @column_name
                , "sp_help, sp_unbindrule"
        from syscolumns col
        where col.id = object_id(@objname)
          and col.name = @column_name
end


/* 
** =========================================================================
** Get the check constraints and referential constraints
** by checking the status bits in sysconstraints
*/

/*
** Table-level constraints are stored with colid=0. We need to present this
** output to the reader in two ways.
**
** 1. If user issues sp_depends on a single-column, then include all info
**    of constraints on the column of choice, and the info on table-level
**    check constraints. The check for this case is
**    if (@findTableLevelConstraints = 0 and colid = 0).
**
** 2. If the user is running sp_depends for the table (i.e. to get output
**    for all columns in the table), then, the output for table-level
**    constraints is not done here. Its generated in the caller's context.
*/
if exists (select colid from sysconstraints
	   where tableid = object_id(@objname)
	     and colid = @colid)
begin
	insert into #column_depends

	select
		  -- Form string like: 'table-level check constraint',
		  -- 'check constraint', 'referential constraint'.
		  --
		  case when (@findTableLevelConstraints = 0 and colid = 0)

		    -- check for table-level constraints
		    then "table-level check"

		    else case when status & 128 = 128 then "check"
		    	      when status & 64 = 64 then "referential"
		  	 end
		  end
		  + " constraint"

		, "constraint"
		, object_name(constrid)
		, case when (@findTableLevelConstraints = 0 and colid = 0)
		       then "(Unknown column name)"
		       else @column_name
		  end

		, "sp_helpconstraint, alter table drop constraint"

	from sysconstraints 
	where tableid = object_id(@objname)
	  and (colid = @colid			-- For this column

		-- For table-level constraints during the very first call.
		or (@findTableLevelConstraints = 0 and colid = 0))
end

/*
** =========================================================================
** sysstatistics:
** Get all of the column-name groups from sysstatistics
** that include this column
*/
declare statrows cursor for
select colidarray
from sysstatistics
where id = object_id(@objname)
  and formatid = 100 		-- column statistics rows
  and statid = 0

declare	  @statrowqualifies 	int
	, @colid_size		int	-- in bytes

-- sysstatistics.colidarray is 2 bytes each. Setting this to 2 will
-- ensure that we can use sp_depends after upgrade has completed. But,
-- if it is used before upgrade has completed, we will get incorrect
-- info as sysstatistics would not have been upgraded, yet. That is a
-- small window to worry about.
--
select @colid_size = 2

open statrows

fetch statrows into @colidarray
while (@@sqlstatus != 2)
begin -- {

	select @col_index = 1, @statcount = 0, @statrowqualifies = 0

	-- Parse colidarray, searching for match on required colid.
	-- (Use <= rather than < as varbinary colidarray will have trailing
	--  0s truncated. On NT/Linux, if we used <, we would miss out on
	-- the last column in this array. Same reason below.)
	--
	while (@col_index <= datalength(@colidarray))
	begin
		if (select convert(smallint,substring(@colidarray,@col_index,
					     	      @colid_size))) = @colid
		begin
			select @statrowqualifies = 1
			break
		end
		else
			select @col_index = @col_index + @colid_size
	end

	-- If row qualifies, re-parse the columns it contains, and build
	-- a string of column names. Output that to the #temp table.
	--
	if (@statrowqualifies = 1)
	begin -- {

		select @col_index = 1, @statstring = NULL

		-- (See note above why we use <= rather than <)
		while (@col_index <= datalength(@colidarray) )
		begin -- {

			select @statcolumn =
				col_name(object_id(@objname), 
					 convert(smallint,
						 substring(@colidarray,
							   @col_index,
							   @colid_size)))

			-- Concatenate, accounting for initial empty string.
			--
			select @statstring = @statstring
					     + case when (@statstring IS NULL)
						  then "(" + @statcolumn
						  else ", " + @statcolumn
						  end

			select @col_index = @col_index + @colid_size

		end -- }

		select @statstring = @statstring + ")"

		insert into #column_depends values
			("statistics", "row"
			  , case
				when (datalength(@statstring) >
					@Depend_col_length)

				-- Truncate string and append with '...)'
				then convert(char(251), @statstring) + "...)"
				else @statstring
			    end
			  , @column_name, "update statistics")
	end -- }

fetch statrows into @colidarray

end -- }

close statrows
deallocate cursor statrows

/*
** =========================================================================
** Check for permissions on the column.
** Note that grant select on mytab...revoke select on mytab(c1)...
** means that sysprotects has column perms grants for all OTHER
** columns of mytab.
*/
if exists ( select * from sysprotects p, master..spt_values c
	    where c.type = "P" and c.number <= 1024
	      and id = object_id(@objname)
	      and convert(tinyint,
			  substring(isnull(p.columns, 0x1),
				    c.low,1)) & c.high != 0
	      and col_name(id, number) = @column_name)
begin
	insert into #column_depends values 
		("permission", "permission", "column permission"
		 , @column_name, "sp_helprotect, grant/revoke")
end

/* 
** =========================================================================
** Look in syskeys for any primary, foreign or common keys 
*/
if exists (select * from syskeys 
	   where (id = object_id(@objname) 
	    	  and (key1 = @colid or
		       key2 = @colid or
		       key3 = @colid or
		       key4 = @colid or
		       key5 = @colid or
		       key6 = @colid or
		       key7 = @colid or
		       key8 = @colid) )

	     or  (depid = object_id(@objname) 
		  and (depkey1 = @colid or
		       depkey2 = @colid or
		       depkey3 = @colid or
		       depkey4 = @colid or
		       depkey5 = @colid or
		       depkey6 = @colid or
		       depkey7 = @colid or
		       depkey8 = @colid) )
	)
begin
	-- Strings to store comma separated concatenated string of names
	-- of key columns for Primary->Foreign tables.
	--
	declare @syskeys_str	varchar(255)
	declare @depkeys_str	varchar(255)

	declare lrikeys cursor for
	select    id, type, depid
		, key1, key2, key3, key4, key5, key6, key7, key8
		, depkey1, depkey2, depkey3, depkey4, depkey5, depkey6
		, depkey7, depkey8
	from syskeys
	where 	(id = object_id(@objname) 
		 and (key1 = @colid or		-- Column is a primary key
		      key2 = @colid or		-- column.
		      key3 = @colid or
		      key4 = @colid or
		      key5 = @colid or
		      key6 = @colid or
		      key7 = @colid or
		      key8 = @colid) )

	or 	(depid = object_id(@objname) 
		 and (depkey1 = @colid or	-- Column is a foreign key
		      depkey2 = @colid or	-- column.
		      depkey3 = @colid or
		      depkey4 = @colid or
		      depkey5 = @colid or
		      depkey6 = @colid or
		      depkey7 = @colid or
		      depkey8 = @colid) )

	open lrikeys
	fetch lrikeys into @id, @type, @depid
		, @key1, @key2, @key3, @key4, @key5, @key6, @key7, @key8
		, @depkey1, @depkey2, @depkey3, @depkey4, @depkey5, @depkey6
		, @depkey7, @depkey8
	
	while (@@sqlstatus != 2)
	begin
		-- Build the primary table's key column names string
		-- using (@id, @key<n>)
		--
		select @syskeys_str = 
			" ("
			   + case when @key1 is not null
				then col_name(@id, @key1)
			      end
			   + case when @key2 is not null
				then ", " + col_name(@id, @key2)
			      end
			   + case when @key3 is not null
				then ", " + col_name(@id, @key3)
			     end
			   + case when @key4 is not null
				then ", " + col_name(@id, @key4)
			     end
			   + case when @key5 is not null
				then ", " + col_name(@id, @key5)
			     end
			   + case when @key6 is not null
				then ", " + col_name(@id, @key6)
			     end
			   + case when @key7 is not null
				then ", " + col_name(@id, @key7)
			     end
			   + case when @key8 is not null
				then ", " + col_name(@id, @key8)
			     end
			   + ")"

		-- Build the foreign table's key column names string
		-- using (@depid, @depkey<n>)
		--
		if (@type = 2) or (@type = 3)
		begin

			select @depkeys_str = 
			" ("
			   + case when @depkey1 is not null
				then col_name(@depid, @depkey1)
			      end
			   + case when @depkey2 is not null
				then ", " + col_name(@depid, @depkey2)
			      end
			   + case when @depkey3 is not null
				then ", " + col_name(@depid, @depkey3)
			     end
			   + case when @depkey4 is not null
				then ", " + col_name(@depid, @depkey4)
			     end
			   + case when @depkey5 is not null
				then ", " + col_name(@depid, @depkey5)
			     end
			   + case when @depkey6 is not null
				then ", " + col_name(@depid, @depkey6)
			     end
			   + case when @depkey7 is not null
				then ", " + col_name(@depid, @depkey7)
			     end
			   + case when @depkey8 is not null
				then ", " + col_name(@depid, @depkey8)
			     end
			   + ")"
		end

		if (@type = 1)
			insert into #column_depends values
			("logical RI", "primary", @objname + @syskeys_str
			 , @column_name, "sp_helpkey, sp_dropkey")

		if (@type = 2) or (@type = 3)
			insert into #column_depends values
			("logical RI" 

			 , case when @type = 2 then "foreign"
			      else "common"
			   end
			 ,  "From " + object_name(@id) + @syskeys_str +
			    " To "   + object_name(@depid) + @depkeys_str
			, @column_name, "sp_helpkey, sp_dropkey")
		
		fetch lrikeys into @id, @type, @depid, 
			@key1, @key2, @key3, @key4, @key5, @key6, @key7, @key8
			, @depkey1, @depkey2, @depkey3, @depkey4, @depkey5
			, @depkey6, @depkey7, @depkey8
	end
end

set nocount off
return (0)
go

-- Clean it out so that we can install sp_depends successfully.
--
if ((select object_id("#column_depends")) is not NULL)
begin
	drop table #column_depends
end
go
go
exec sp_procxmode 'sp_depends_cols', 'anymode'
go
grant execute on sp_depends_cols to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_depends')
begin
	drop procedure sp_depends
end
go
print "Installing sp_depends"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_depends"            17460
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
** 17462, "Things the object references in the current database."
** 17463, "Things inside the current database that reference the object."
** 17464, "Object doesn't reference any object and no objects reference it."
** 17465, "The specified column (or all columns, if none was specified) in %1! has no dependencies on other objects, and no other object depends on any columns from it."
** 17466, "Dependent objects that reference column %1!."
** 17467, "Dependent objects that reference all columns in the table. Use sp_depends on each column to get more information."
** 17468, "Columns referenced in stored procedures, views  or triggers are not included in this report."
** 17469, "Tables that reference this object: "
** 19986, "The dependencies of the stored procedure cannot be determined until the first successful execution."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/
create procedure sp_depends
  @objname varchar(767)			/* the object we want to check */
, @column_name varchar(255) = null	/* the column we want to check */
as

declare @found_some 	bit		/* flag for table dependencies found */
	, @msg		varchar(1024)
	, @sptlang	int		/* current sessions language */
	, @length	int
	, @colid 	int		/* column id from syscolumns */
	, @objid 	int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
set nocount on

/*
**  Make sure the @objname is local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/*
	** 17460, "Object must be in the current database."
	*/
	raiserror 17460
	return (1)
end

/*
**  See if @objname exists.
*/
select @objid = object_id(@objname)
if not exists (select id
		from sysobjects
			where id = @objid)
begin
	/*
	** 17461, "Object does not exist in this database."
	*/
	raiserror 17461
	return (1)
end

/* 
** If a column name is provided, check that it exists in the said table.
*/
if @column_name is not null
begin
	select @colid = colid
	from syscolumns 
	where id = @objid and name = @column_name

	if (@colid is NULL)
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @column_name
		return (1)
	end
end

/*
** If procedure was created with deferred name resolution and
** it was not executed already then indicate that dependencies
** will be calculated after the first successfully execution.
*/
if exists (select type
		from sysprocedures
			where id = @objid and type = 2048 )
begin
	/*
	** 19986, "The dependencies of the stored procedure cannot be 
	**	   determined until the first successful execution."
	*/
	exec sp_getmessage 19986, @msg output
	print @msg

	return (0)
end

/*
**  Initialize @found_some to indicate that we haven't seen any dependencies.
*/
select @found_some = 0

/*
**  Print out the particulars about the local dependencies.
*/
if exists (select *
		from sysdepends
			where id = @objid)
begin
	/*
	** 17462, "Things the object references in the current database."
	*/
	exec sp_getmessage 17462, @msg output
	print @msg

	select @sptlang = @@langid
	if @@langid != 0
	begin
		if not exists (
			select * from master.dbo.sysmessages where error
			between 17010 and 17014
			and langid = @@langid)
		    select @sptlang = 0
		else
		if not exists (
			select * from master.dbo.sysmessages where error
			between 17100 and 17109
			and langid = @@langid)
		    select @sptlang = 0
	end

	/* Check if this is a sqlj proc/func. If it is then the object 
	** will reference only a java class.
	*/
	if exists (select *  
			from sysdepends d, sysxtypes x
			where d.id = @objid
				and d.depid = x.xtid)

	begin
		select object = x.xtname, 
			type = "java class"
		into #depend1result
			from sysdepends d, 
				sysxtypes x
			where d.id = @objid
				and d.depid = x.xtid
	exec sp_autoformat @fulltabname = #depend1result,
		@selectlist = "object, 'java class' = type"
	drop table #depend1result
	end
	else
	begin
	    select object = s.name + "." + o.name,
		type = convert(char(16), m0.description),
		updated = convert(char(10), m1.description),
		selected = convert(char(10), m2.description)
	    into #depend2result
			from sysobjects o, master.dbo.spt_values v,
				sysdepends d, master.dbo.spt_values u,
				master.dbo.spt_values w,
				sysusers s, 
				master.dbo.sysmessages m0, 
				master.dbo.sysmessages m1, 
				master.dbo.sysmessages m2
			where o.id = d.depid
				and o.sysstat & 15 = v.number and v.type = 'O'
				and v.msgnum = m0.error
				and isnull(m0.langid, 0) = @sptlang
				and u.type = 'B' and u.number = d.resultobj
				and u.msgnum = m1.error
				and isnull(m1.langid, 0) = @sptlang
				and w.type = 'B' and w.number = d.readobj
				and w.msgnum = m2.error
				and isnull(m2.langid, 0) = @sptlang
				and d.id = @objid
				and o.uid = s.uid
	exec sp_autoformat @fulltabname = #depend2result
	drop table #depend2result
	end		
	select @found_some = 1
end

/*
**  Now check for things that the objects depends upon
*/
if exists (select *
		from sysdepends
			where depid = @objid)
begin
	/*
	** 17463, "Things inside the current database that reference the object."
	*/
	exec sp_getmessage 17463, @msg output
	print @msg
	    select distinct
		object = s.name + "." + o.name,
		type = (case
				when (o.type = "IT")
					then "instead of "
				else	null
			end)
			+ (v.name)
	    into #depend3result
			from sysobjects o, master.dbo.spt_values v,
				sysdepends d, sysusers s
			where o.id = d.id
				and o.sysstat & 15 = v.number 
				and v.type = 'O'
				and d.depid = @objid
				and o.uid = s.uid
			       -- Match on column name, if  one is provided.
			       	and (@column_name IS NULL
					or exists 
						(select *
						 from master..spt_values v2
						 where v2.type = "P"
						   and v2.number <= 1024
						   and @column_name = col_name(d.depid, v2.number)
						   and ((convert(tinyint, substring(isnull(d.columns, 0x1),
										  v2.low, 1) )
								& v2.high) != 0)
						)
				   )					
	exec sp_autoformat @fulltabname = #depend3result,
		@selectlist = "object, type",
		@orderby = "order by object"
	drop table #depend3result
	select @found_some = 1
end

/* If this object aplied to a column in a table we want to
** display the table name that references it (used for rules and 
** defaults).
*/ 

if exists (select *
	from syscolumns
		where @objid IN (cdefault, domain, accessrule))
begin
	/*
	**  17469, "Tables that reference this object: "
	*/
		exec sp_getmessage 17469, @msg output
		print @msg
	select distinct
		object = u.name + "." + o.name
	into #depend4result
		from syscolumns c, sysobjects o, sysusers u
		where  @objid IN (c.cdefault, c.domain, c.accessrule)
			and c.id = o.id 
			and o.uid = u.uid
	exec sp_autoformat @fulltabname = #depend4result
	drop table #depend4result
	select @found_some = 1
end 

/*
**  Did we find anything in sysdepends?
*/
if (@found_some = 0)
begin
	/*
	** 17464, "Object doesn't reference any object and no objects reference it."
	*/
	exec sp_getmessage 17464, @msg output
	print @msg
end


/*
** If object is something other than a table (i.e. view, rule, default,
** trigger etc., return immediately, without further processing for
** column level dependencies. These do not apply to non-table objects,
** and will needlessly add to the processing time for, say, views with
** large number of columns.
*/
if (select type from sysobjects
    where id = @objid ) not in ('U', 'S')
begin
	return (0)
end

/*
** =========================================================================
** Start of column level dependency processing.
** =========================================================================
*/

/*
** Store results in #column_depends as we go
*/
if ((select object_id("#column_depends")) is NULL)
begin
	create table #column_depends (
		  Type 		varchar(23)
		, Property	varchar(11)
		, Dependency 	varchar(255)	-- @Depend_col_length = 255
		, Column	varchar(255)
		, AlsoSee	varchar(100)
	) lock allpages
end

declare @Depend_col_length int

-- Length of Dependency column in output table
select @Depend_col_length = 255

/*
** =========================================================================
** If no column name was specified, generate dependencies for all columns
** in the table. Output one result at the end of the procedure.
*/
if @column_name is null 
begin
	declare colcur cursor for
	select name from syscolumns where id = @objid

	open colcur
	fetch colcur into @column_name

	while (@@sqlstatus != 2)
	begin
		-- Change recursion level to skip table-level dependency code
		exec sp_depends_cols @objname, @column_name
				     , @findTableLevelConstraints = 1

		fetch colcur into @column_name
	end

	close colcur
	deallocate cursor colcur

	-- To flag output of column name in end result.
	select @column_name = NULL

	-- Special case code to pick out check constraints defined at the
	-- table level. These appear with colid==0 in SYSCONSTRAINTS. Get
	-- their info, and display them in the summary output report.
	--
	if exists (select colid from sysconstraints
		   where tableid = @objid
		     and colid = 0)		-- table level constraints
	begin
		insert into #column_depends
		select "table-level check constraint"
			, "constraint"
			, object_name(constrid)
			  + " (Table-level check constraint)"
			, "(Unknown column name)"
			, "sp_helpconstraint, alter table drop constraint"
		from sysconstraints 
		where tableid = @objid
		  and colid = 0
	end
end
else
begin
	-- Find column-level dependencies for just this one column.
	exec sp_depends_cols @objname, @column_name
			     , @findTableLevelConstraints = 0
end

/*
** =========================================================================
**  Did we find anything for the specified column, or for all columns?
*/

-- Only do printing when we are in the first invocation of this sproc,
-- and not when we recurse to process each column.
--
-- Check and report if no column-level dependencies were found.
if ((select count(*) from #column_depends) = 0)
begin
	exec sp_getmessage 17465, @msg output
	print @msg, @objname

	return (0)
end

-- Report on dependencies for the specified column.
if (@column_name is not NULL)
begin
	exec sp_getmessage 17466, @msg output
	print @msg, @column_name
	
	exec sp_getmessage 17468, @msg output
	print @msg

	exec sp_autoformat @fulltabname = #column_depends,
		@selectlist = "Type, Property,
		'Object Names or Column Names' = Dependency,
		'Also see/Use command' = AlsoSee",
		@orderby = "order by Type"
end

-- Report on dependencies for all columns in the table.
else
begin
	print " "
	exec sp_getmessage 17467, @msg output
	print @msg

	exec sp_getmessage 17468, @msg output
	print @msg

	print " "

	exec sp_autoformat @fulltabname = #column_depends,
		@selectlist = "Column, Type,
		'Object Names or Column Names' = Dependency",
		@orderby = "order by Column, Type"
end
drop table #column_depends
set nocount off
return (0)
go
go
exec sp_procxmode 'sp_depends', 'anymode'
go
grant execute on sp_depends to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_diskdefault')
begin
	drop procedure sp_diskdefault
end
go
print "Installing sp_diskdefault"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/diskdefault */

/*
** Messages for "sp_diskdefault"        17470
**
** 17260, "Can't run %1! from within a transaction." 
** 17470, "No such device exists -- run sp_helpdevice to list the DataServer devices."
** 17471, "The device name supplied is not a database disk."
** 17472, "Usage: sp_diskdefault logicalname {defaulton | defaultoff}." 
** 17473, "The device '%1!' is a private device. This operation is not valid for private devices." 
*/

create procedure sp_diskdefault
@logicalname	varchar(30),		/* logical name of the device */
@defstatus	varchar(15)		/* turn on or off */
as


/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_diskdefault"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
**  Make sure that a device with @logicalname exists.
*/
if not exists (select *
		from master.dbo.sysdevices
			where name = @logicalname)
begin
	/*
	** 17470, "No such device exists -- run sp_helpdevice to list the DataServer devices."
	*/
	raiserror 17470
	return (1)
end

/*
**  Make sure that is a database disk and not a dump device.
*/
if exists (select *
		from master.dbo.sysdevices
			where name = @logicalname 
				and status & 16 = 16)
begin
	/*
	** 17471, "The device name supplied is not a database disk."
	*/
	raiserror 17471
	return (1)
end

/* Do not allow this operation for a private device. */
if exists (select *
	   from master.dbo.sysdevices
	   where name = @logicalname
	     and (status2 & 2) = 2)
begin
	raiserror 17473, @logicalname
	return (1)
end

/* Do not allow this operation for a virtual cache device. */
if exists (select *
	   from master.dbo.sysdevices
	   where name = @logicalname
	     and (status2 & 8) = 8)
begin
	raiserror 17474, @logicalname
	return (1)
end

if @defstatus = "defaulton"
begin
	update master.dbo.sysdevices
		set status = status | 1
			where name = @logicalname
	return (0)
end

if @defstatus = "defaultoff"
begin
	update master.dbo.sysdevices
		set status = status & ~1
			where name = @logicalname
	return (0)
end

/*
**  @defstatus must be "defaulton" or "defaultoff"
*/
/*
** 17472, "Usage: sp_diskdefault logicalname {defaulton | defaultoff}." 
*/
raiserror 17472
return (1)
go
exec sp_procxmode 'sp_diskdefault', 'anymode'
go
grant execute on sp_diskdefault to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_is_valid_user')
begin
	drop procedure sp_is_valid_user
end
go
print "Installing sp_is_valid_user"
go


/*
** Messages for "sp_is_valid_user"
** 	Currently, sp_is_valid_user does not use any messages.
**
** Description
**
** 	sp_is_valid_user determines if a user is a 'valid user' in a specified 
**	database.  
**
**	For a user to be considered a 'valid user' in a database, one or more 
**	of the following criteria must be met:
**		o The user has been granted sa_role.
**		o The user is the database owner
**		o The user's suid is listed in the target database's
**                Sysusers or Sysalternates tables.
**              o The target database's Sysusers table contains a 
**                guest entry 
**
** Parameters
**	@uid		- (output)
**		  	  Values returned are:
**		           The user id of the user in the database.
**		           0 if the user is not a valid user in the database.
**	@dbname		- name of the target database. null indicates 
**			  current database.
**	@loginname 	- name of the login being checked, null indicates
**			  current login.
**      @mode   	- Default value is 0. This is a bit mask to special 
**			  case the search criteria.
** 		  		1 => ignore the guest user
** 		  		2 => ignore the sa_role
** 		  		4 => ignore the aliases
**
** Returns
** 	0 	- sproc completed successfully
**	1	- sproc didn't complete successfully as database could not be 
**		  opened.
**
** Note
**	This procedure may create a temporary table so unless the 'ddl in tran'
**	option is turned on for the temp database this procedure may 
**	raise the error 2762.
**
*/
create procedure sp_is_valid_user 
	@uid int output,		/* Output, user id, 0 if invalid user */
	@dbname varchar(255) = NULL, 	/* db name to look in. */
	@loginname varchar(255) = NULL, /* login name to check for */
	@mode int = 0			/* Mode of search, see description */
as
begin
        declare @suid int,		/* suid being checked for */
		@suidstr varchar(32),	/* suid as a varchar */ 
		@cmd  varchar(2000),	/* Variable to store the dynamic SQL */
		@ignore_guest int,	/* value for ignore_guest mode */
		@ignore_sarole int,	/* value for ignore_sarole mode */
		@ignore_alias int	/* value for ignore_alias mode */

	set nocount on

	/* Initialize @uid to 0 */
	select @uid = 0

	/* 
	** If @loginname is not specified, work on current login.
	** If @dbname is not specified check in current database.
	*/ 
	select 	@suid = case 
			when @loginname is null then suser_id()
			else suser_id(@loginname)
			end
		, @dbname = isnull(@dbname, db_name())

	/* If @suid is NULL i.e. an invalid login name is specified return. */
	if (@suid is NULL)
	begin
		return 0
	end

	/* Initialize other variables */
        select 	@suidstr = convert(varchar,@suid), 
		@ignore_guest = 1, @ignore_sarole = 2, @ignore_alias = 4

	/* If we are not ignoring sa_role check if the user has sa_role. */
	if ( (@mode & @ignore_sarole = 0) 
	 and exists (select 1 from master.dbo.sysloginroles 
			  where suid = @suid and srid = role_id('sa_role')))
	begin
		select @uid = 1
		return 0
	end

	/* Check if this user is the database owner.  */
	if exists (select 1 from master.dbo.sysdatabases 
			where name = @dbname and suid = @suid)
	begin
		select @uid = 1
		return 0
	end

	/* We now need to check the database so check if the db is online */
        if exists (select 1 from master.dbo.sysdatabases
                	where name=@dbname 
			  and (status & 256 = 256 or status2 & 16 = 16))
        begin
                return 1
        end

	/* Create temp table for getting uid back from dynamic SQL */
	create table #t (uid int)

	/* Now look for the user in sysusers and sysalternates.  */

	/* construct sql to query sysusers */
	select @cmd = "insert into #t select uid from " 
			+ @dbname + ".dbo.sysusers where suid = " + @suidstr  

	/* If we are not ignoring aliases query sysalternates */
	if (@mode & @ignore_alias = 0)
	begin
		select @cmd = @cmd + " or suid = (select altsuid from " 
			   + @dbname + ".dbo.sysalternates where suid = " 
			   + @suidstr + ")"
	end

	exec (@cmd)

	/*
	** If user exists get the uid else if we are not ignoring guest user 
	** check for guest user, if present then return the guest user id.
	*/
	if (@@rowcount > 0) 
	begin
		/* Get the uid from temp table */
		select @uid = uid from #t
	end
	else if (@mode & @ignore_guest = 0)
	begin
		select @cmd = "declare @dummy int select @dummy = 1 from " 
				+ @dbname 
				+ ".dbo.sysusers where suid = -1 and uid = 2"
		exec (@cmd)
		if (@@rowcount > 0)
		begin
			select @uid = 2
		end
	end

	drop table #t

	set nocount off

	return (0)
end

go
exec sp_procxmode 'sp_is_valid_user', 'anymode'
go
grant execute on sp_is_valid_user to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropalias')
begin
	drop procedure sp_dropalias
end
go
print "Installing sp_dropalias"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Messages for "sp_dropalias"          17480
**
** 17231, "No login with the specified name exists."
** 17480, "Alias user dropped."
** 17481, "No alias for specified user exists."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18337, "Setting curwrite label to data_low for deleting from sysalternates
**	   table failed."
** 18790, "You cannot drop the alias for login '%1!' because '%2!' owns
**	   objects in the database."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18778, "A login with Login name '%1!' AND login id '%2!' could not be found in syslogins."
** 18806, "You cannot drop the alias for login '%1!' because '%2!' owns
**	   thresholds in the database."
** 18935, "Warning: You have forced the drop of the alias for login '%1!'
**	   which owns objects in the database. This may result in errors when
**	   those objects are accessed from or contain references to another
**	   database."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
** 18790, "You cannot drop the alias for login '%1!' because '%2!' owns objects in the database."
*/

create procedure sp_dropalias
@loginame varchar(255),		/* account name of the user with the alias */
@option varchar(30) = NULL	/* 'force' to force dropping the alias, even if
				** there are objects created by the alias.
				*/
as

declare @msg varchar(1024)
declare @dbname varchar(255)
declare @suid	int		/* suid of the user */
declare @objectcount int	/* count of objects owned by login */
declare @threshcount int	/* count of thresholds owned by login */
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @dummy int

select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_dropalias', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  If the user has SA role, it's uid will
**  be DBO uid (1).
*/
if ((user_id() != 1) and (charindex("sso_role", show_role()) = 0)) 
begin
	/* 
	** proc_role() will raise permission errors  
	** and send audit records to the audit trail
	*/
	select @dummy = proc_role("sa_role")        
	select @dummy = proc_role("sso_role")        
	return (1)        
end

/* Send apropriate audit records. */
if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")
if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  Check to make sure that the @loginame has an account.
*/
select @suid = suser_id(@loginame)
if @suid is NULL
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return (1)
end

/*
** If the user owns any objects return after raising error. 
*/
select @objectcount = count(*)
	from sysobjects
		where loginame = @loginame

if @objectcount > 0
begin
if @option = 'force'
        begin
		/* 18935, "Warning: You have forced the drop of the alias for
		** login '%1!' which owns objects in the database. This
		** may result in errors when those objects are accessed
		** from or contain references to another database."
		*/
		exec sp_getmessage 18935, @msg output
		print @msg, @loginame
	end
	else
	begin
		/* 18790, "You cannot drop the alias for login '%1!' because
		** '%2!' owns objects in the database."
		*/
		raiserror 18790, @loginame, @loginame
		select name, type from sysobjects
				where loginame = @loginame
		return(1)
	end

end
/*
** If the user owns any thresholds return after raising error.
*/
select @threshcount = count(*)
	from systhresholds
		where suid = @suid

if @threshcount > 0
begin
	/* 18806, "You cannot drop the alias for login '%1!' because
	**	'%2!' owns thresholds in the database."
	*/
	raiserror 18806, @loginame, @loginame
	select "Segment name" = g.name, "Free pages" = t.free_space
		from syssegments g, systhresholds t
			where t.suid = @suid
			and t.segment = g.segment
	return(1)
end



/*
**  Delete the alias, if any, from sysalternates.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec



	delete from sysalternates
		where suid = suser_id(@loginame)

	/*
	**  If nothing happened (rowcount = 0), there was no alias.
	*/
	if (@@rowcount = 0)
	begin
		/*
		** 17481, "No alias for specified user exists."
		*/
		raiserror 17481
	
		rollback transaction rs_logexec
		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_dropalias", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end



commit transaction rs_logexec

/*
** 17480, "Alias user dropped."
*/
exec sp_getmessage 17480, @msg output
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)
go
exec sp_procxmode 'sp_dropalias', 'anymode'
go
grant execute on sp_dropalias to public
go
exec sp_procxmode 'sp_dropalias', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropgroup')
begin
	drop procedure sp_dropgroup
end
go
print "Installing sp_dropgroup"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/dropgroup */

/*
** Messages for "sp_dropgroup"          17486
**
** 17289, "Set your curwrite to the hurdle of current database."
** 17333, "No group with the specified name exists." 
** 17486, "Can't drop the group 'public'."
** 17487, "You cannot drop group because it owns objects in database."
** 17488, "Group has members.  It must be empty before it can be dropped."
** 17489, "Group has been dropped."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18075, "Set your maxwrite label correctly."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
**
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
**
*/

create procedure sp_dropgroup
@grpname varchar(255)		/* group to be dropped */
as

declare @gid int		/* group id of the group to be dropped */
declare @msg varchar(1024)
declare @dummy int
declare @dbname varchar(255)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_dropgroup', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  Call proc_role() with the required SA role.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("sso_role", show_role()) = 0)
	begin
		select @dummy = proc_role("sa_role")
		select @dummy = proc_role("sso_role")
		return (1)
	end
end

if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")

if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  See if the group exists.
*/
select @gid = uid from sysusers
where name = @grpname
and ((uid between @@mingroupid and @@maxgroupid) or uid = 0)
and not exists (select name from master.dbo.syssrvroles where name = @grpname)

if @gid is NULL
begin
	/*
	** 17333, "No group with the specified name exists." 
	*/
	raiserror 17333
	return (1)
end

/*
**  Can't drop the group public.
*/
if @gid = 0
begin
	/*
	** 17486, "Can't drop the group 'public'."
	*/
	raiserror 17486
	return (1)
end

/*
**  Check to see if the group owns anything.  If so, return.
*/
if exists (select * from sysobjects where uid = @gid)
begin
	/*
	** 17487, "You cannot drop group because it owns objects in database."
	*/
	raiserror 17487

	/*
	**  Show what is owned by the group.
	*/
	select s.name, s.type, owner = u.name
		from sysobjects s, sysusers u
			where s.id = @gid
				and u.uid = @gid
	return (1)
end


/*
**  Check to see that nobody is in the group.  If so, return.
*/
if (select count(*) from sysusers
where gid = @gid and (uid < @@mingroupid or uid > @@maxgroupid)) != 0
begin
	/*
	** 17488, "Group has members.  It must be empty before it can be dropped."
	*/
	raiserror 17488

	/*
	**  Show who is in the group.
	*/
	select name from sysusers
	where gid = @gid and (uid < @@mingroupid or uid > @@maxgroupid)
	
	return (1)
end



out_of_HA_checking:

/*
**  Drop the group.
**  Also drop any references to the group in the sysprotects table.
*/
begin transaction rs_logexec



	delete from sysusers
		where uid = @gid


	delete from sysprotects
		where uid = @gid

 

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_dropgroup", @dbname
			
	rollback transaction rs_logexec
	return(1)
end



commit transaction rs_logexec

/*
** 17489, "Group has been dropped."
*/
exec sp_getmessage 17489, @msg output
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)
go
exec sp_procxmode 'sp_dropgroup', 'anymode'
go
grant execute on sp_dropgroup to public
go
exec sp_procxmode 'sp_dropgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropkey')
begin
	drop procedure sp_dropkey
end
go
print "Installing sp_dropkey"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_dropkey"            17490
**
** 17390, "Table or view name must be in 'current' database." 
** 17490, "Usage: sp_dropkey {primary | foreign | common}, tabname [,deptabname]."
** 17491, "Type must be 'primary', 'foreign', or 'common'."
** 17492, "The table or view named doesn't exist in the current database."
** 17493, "You must be the owner of the table or view to drop its key."
** 17494, "No primary key for the table or view exists."
** 17495, "Primary key for the table or view dropped."
** 17496, "Dependent foreign keys were also dropped."
** 17497, "You need to supply the dependent table or view as the third parameter."      
** 17498, "The dependent table or view doesn't exist in the current database."          
** 17499, "No foreign key for the table or view exists."
** 17500, "Foreign key dropped."
** 17501, "No common keys exist between the two tables or views supplied."
** 17502, "Common keys dropped."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_dropkey
@keytype varchar(10), 			/* type of key to drop */
@tabname varchar(767),			/* table with the key */
@deptabname varchar(767) = null		/* dependent table */
as

declare @uid int			/* owner of @tabname */
declare @msg varchar(1024)
declare @dbname varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  First make sure that the key type is ok.
*/
if @keytype not in ("primary", "foreign", "common")
begin
	/*
	** 17490, "Usage: sp_dropkey {primary | foreign | common}, tabname [,deptabname]."
	*/
	raiserror 17490
	/*
	** 17491, "Type must be 'primary', 'foreign', or 'common'."
	*/
	raiserror 17491
	return (1)
end

/*
**  Check to see that the tabname is local.
*/
if @tabname like "%.%.%"
begin
	if substring(@tabname, 1, charindex(".", @tabname) - 1) != db_name()
	begin
		/*
		** 17390, "Table or view name must be in 'current' database." 
		*/
		raiserror 17390
		return (1)
	end
end
if @deptabname like "%.%.%"
begin
	if substring(@deptabname, 1, charindex(".", @deptabname) - 1) != db_name()
	begin
		/*
		** 17390, "Table or view name must be in 'current' database."
		*/
		raiserror 17390
		return (1)
	end
end

/*
**  Get the ids of the @tabname and @deptabname.
*/
if not exists (select *
		from sysobjects
			where id = object_id(@tabname))
begin
	/*
	** 17492, "The table or view named doesn't exist in the current database."
	*/
	raiserror 17492
	return (1)
end

/*
** Get the user-id of @tabname
*/
select @uid = uid
	from sysobjects
		where id = object_id(@tabname)

if @uid != user_id()
begin
	/*
	** 17493, "You must be the owner of the table or view to drop its key."
	*/
	raiserror 17493
	return (1)
end

/*
**  If primary key, just drop it.
*/
if @keytype = "primary"
begin
	delete from syskeys
		where id = object_id(@tabname)
			and type = 1

	if @@rowcount = 0
	begin
		/*
		** 17494, "No primary key for the table or view exists."
		*/
		raiserror 17494
		return (1)
	end

	else
	begin
		/*
		** 17495, "Primary key for the table or view dropped."
		*/
		exec sp_getmessage 17495, @msg output
		print @msg
	end

	/*
	**  Check to see if there are any foreign keys dependent on the
	**  primary key.  If so -- drop them.
	*/
	/* 
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	delete from syskeys
		where depid = object_id(@tabname)
			and type = 2
	
	if @@rowcount != 0
	begin
		/*
		** 17496, "Dependent foreign keys were also dropped."
		*/ 
		exec sp_getmessage 17496, @msg output
		print @msg
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_dropkey", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end
	
	commit transaction

	return (0)
end

/*
**  It's either a foreign or common key so we need to verify the
**  existence of the @deptabname.
*/
if not exists (select id
			from sysobjects
				where id = object_id(@deptabname))
begin
	/*
	**  Was the @deptabname supplied?
	*/
	if @deptabname is null
	begin
		/*
		** 17497, "You need to supply the dependent table or view as the third parameter."      
		*/
		raiserror 17497
		return (1)
	end

	/*
	**  It was supplied but it doesn't exist.
	*/
	/*
	** 17498, "The dependent table or view doesn't exist in the current database."          
	*/
	raiserror 17498
	return (1)
end


/*
**  If foreign key, get rid of it.
*/
if @keytype = "foreign"
begin
	/*
	**  Get rid of the foreign key entry.
	*/

	/* 
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	delete from syskeys
		where type = 2
			and id = object_id(@tabname)
			and depid = object_id(@deptabname)
	if @@rowcount = 0
	begin
		/*
		** 17499, "No foreign key for the table or view exists."
		*/
		raiserror 17499

		rollback transaction rs_logexec
		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_dropkey", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17500, "Foreign key dropped."
	*/
	exec sp_getmessage 17500, @msg output
	print @msg

	return (0)
end

/*
**  Key type must be common so just get rid of the common keys
**  with the right ids and depids.  Since whenever a common key is defined
**  it is added to both of the tables involved, we'll get rid of both of
**  those entries.
*/
delete from syskeys
	where type = 3
		and id = object_id(@tabname)
		and depid = object_id(@deptabname)

if @@rowcount = 0
begin

	/* This error does not use raiserror because it affects
	** the installmaster which would break upgrades.
	*/

	/*
	** 17501, "No common keys exist between the two tables or views supplied."
	*/
	exec sp_getmessage 17501, @msg output
	print @msg
	return (1)
end

/*
**  Now get rid of the inverse common key entries.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction	
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

	delete from syskeys
		where type = 3
			and id = object_id(@deptabname)
			and depid = object_id(@tabname)

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_dropkey", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

commit transaction

/*
** 17502, "Common keys dropped."
*/
exec sp_getmessage 17502, @msg output
print @msg
	
return (0)
go
exec sp_procxmode 'sp_dropkey', 'anymode'
go
grant execute on sp_dropkey to public
go
exec sp_procxmode 'sp_dropkey', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_droplogin')
begin
	drop procedure sp_droplogin
end
go
print "Installing sp_droplogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/droplogin */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:16 2006 
*/
/*
** raiserror Messages for droplogin [Total 10]
**
** 17231, "No login with the specified name exists."
** 17260, "Can't run %1! from within a transaction."
** 17509, "User exists or is an alias or is a database owner in at least one database. Drop the user or the alias, or change the database ownership before dropping the login."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17880, "No such account -- nothing changed."
** 18013, "Cannot lock the last remaining unlocked SA account."
** 18388, "You must be in the master database in order to run '%1!'."
** 18409, "The built-in function '%1!' failed. Please see the other messages printed along with this message."
** 18553, "Login '%1!' cannot be dropped because it has execution class bindings. Use sp_unbindexeclass before dropping login."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."
** 19587, "User exists or is an alias or is a database owner in %1! database(s)."
*/
/*
** sp_getmessage Messages for droplogin [Total 5]
**
** 17511, "Login dropped."
** 17915, "Warning: the specified account is currently active."
** 17918, "Nothing changed."
** 18553, "Login '%1!' cannot be dropped because it has execution class bindings. Use sp_unbindexeclass before dropping login."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_droplogin
@loginame varchar(255)		/* name of login account to drop */
as
declare @msg varchar (1024)
declare @suid int		/* suid of person to change pw on    */
declare @returncode int
declare @dummy int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @log_for_rep int
declare @db_rep_level_all int
declare @db_rep_level_none int
declare @db_rep_level_l1 int
declare @lt_rep_get_failed int
declare @dbname varchar(255)    /* Variable to store database name */
declare @temp_val int           /* Temporary variable */
declare @valid_user int         /* Stores if user is valid in any database */
declare @valid_dbnames varchar(2000) /* Stores all database names in
                                     ** which user is valid
                                     */
declare @scope varchar(32)	/* SDC only, command execution scope */
declare @instanceid int		/* SDC only, ID of owning instance of database */

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_droplogin"
	return (1)
end

select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_droplogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  This procedure makes a weak attempt to check for any dependencies.
**  It looks in the current database to see if the suid is used in
**  sysusers or sysalternates.  If so, a diagnostic is issued and the
**  login is not dropped.
**
**  Ideally, this procedure should check each database to see if the login
**  is a user.  However, this is not yet possible since procedures do not
**  allow parameters to be used for database or table names.
*/

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_droplogin"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sso_role") = 0)
	return (1)

/*
**  Check if the account exists
*/
select @suid = suid 
	from master.dbo.syslogins
	where name = @loginame
if @suid is NULL
begin
        /*
        ** 17880, "No such account -- nothing changed."
        */
	raiserror 17880
        return (1)
end

/*
** Declare a read only cursor to select all the database names
** in master.dbo.sysdatabases
*/
declare drop_login cursor for
select name from master.dbo.sysdatabases

for read only

/* Open the cusor to fetch the content in local variable */
open drop_login

fetch drop_login into @dbname

while @@sqlstatus <> 2
begin
        if @@sqlstatus = 1
        begin
                /*
                ** 18999, "An error occurred while fetching data from a temporary
                ** table. If there are no other error messages and this error
                ** persists, please contact Sybase Technical Support."
                */
                raiserror 18999
                close drop_login
                deallocate cursor drop_login
                return (1)
        end

	/*
	** SDC only, skip the local temporary database belonging to other nodes
	*/
	if (@@clustermode = "shared disk cluster")
	begin
		/*
		** Get the ID of the owning instance if the specified database
		** is a local temporary database
		*/
		select @instanceid = db_instanceid(@dbname)
		if ( (@instanceid is not null)  and (@instanceid <> @@instanceid) )
		begin
			fetch drop_login into @dbname
			continue
		end
	end

        select @temp_val = 0

        /*
	** while executing sp_is_valid_user last parameter(mode parameter) is 2,
	** to ignore sa_role check since sso_role checking is already performed before
	*/
	exec sp_is_valid_user @temp_val output, @dbname, @loginame, 2

        if (@temp_val = 1 or @temp_val > 2)
        begin
                select @valid_dbnames = @valid_dbnames + "'" + @dbname + "'" + " "
                select @valid_user = 1
        end

        fetch drop_login into @dbname
end
close drop_login
deallocate cursor drop_login

/* return if user is valid in any database */
if @valid_user = 1
begin
        /* 19587, "User exists or is an alias or is a database owner in %1! database(s)." */
        raiserror 19587, @valid_dbnames
        return (1)
end

/*
** SDC only, check clusterwide sysprocesses for active login
*/
if (@@clustermode = "shared disk cluster")
begin
	select @scope=@@system_view
	set system_view cluster
end

/*
**  Disallow dropping an account who has already logged in.
**  Note that it eliminates the race condition between two processes
**  for checking the last remaining unlocked SSO account.
*/
if exists (select * from master.dbo.sysprocesses where suid = @suid)
begin
	/*
	** SDC only, restore previous system_view scope
	*/
	if (@@clustermode = "shared disk cluster")
	begin
		set system_view @scope
	end

	/* 17915,
	** "Warning: the specified account is currently active."
	*/
	exec sp_getmessage 17915, @msg output
	print @msg
	/*
	** 17918, "Nothing changed."
	*/
	exec sp_getmessage 17918, @msg output
	print @msg
	return (1)
end
/*
** SDC only, restore previous system_view scope
*/
if (@@clustermode = "shared disk cluster")
begin
	set system_view @scope
end





/*
**  Lock the account to prevent it from begin active.
*/
execute @returncode = sp_locklogin @loginame, "lock"

if (@returncode != 0)
	return (@returncode)

if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
	begin tran rs_logexec



/* remove all resource limits associated with this login */
delete from master.dbo.sysresourcelimits where name = @loginame


/*
**  Delete the login.
*/
delete from master.dbo.syslogins
	where name = @loginame

/*
**  Check @@rowcount when it works
*/
if (@@rowcount > 0)
begin
	/* remove all roles related information from sysloginroles */
	delete from master.dbo.sysloginroles
		where suid = @suid


	/*
	** delete entries from sysattributes for this login.
	** login entries are type 'PS'; login entries are 
	** type 'L' or external login entries are type 'EL';
	** login entries for local mapped logins
	** are type 'LM'
	*/
	delete from master.dbo.sysattributes
		where object = @suid
		and object_type in ("EL", "L", "LM")


	delete from master.dbo.sysattributes
		where object_type = "PS" and object_cinfo = "login"
		and object = @suid


	/*
	** Delete any bindings associated with the login.
	*/
	delete from master.dbo.sysattributes
		where (     (class = 6 or class = 16) 
			and (    (     object_type = "LG" 
				   and object = @suid)
			      or (     object_type = "AP" 
			           and object_info1 = @suid)))


	/* delete entries in sysremotelogins for this login */
	delete from master.dbo.sysremotelogins
		where suid = @suid



	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_droplogin", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec

	/*
	** Run the custom clean up procedure
	*/
	if exists (select 1 from master.dbo.sysobjects where name = 
		'sp_cleanpwdchecks')
	begin
		exec("exec master.dbo.sp_cleanpwdchecks @loginame")
	end

	/*
	** 17511, "Login dropped."
	*/
	exec sp_getmessage 17511, @msg output
	print @msg
	return (0)
end
else
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	goto clean_all
end

clean_all:
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		rollback tran rs_logexec
	return (1)
go
exec sp_procxmode 'sp_droplogin', 'anymode'
go
grant execute on sp_droplogin to public
go
exec sp_procxmode 'sp_droplogin', 'rep_master'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropthreshold')
begin
	drop procedure sp_dropthreshold
end
go
print "Installing sp_dropthreshold"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_dropthreshold"      17903
**
** 17871, "There is no segment named '%1!'."
** 17875, "Only the DBO of database '%1!' or a user with System Administrator
**	   (SA) authorization may add, delete, or modify thresholds in that
**	   database."
** 17903, "Table '%1!' does not exist in database '%2!' -- cannot drop
**	  thresholds."
** 17904, "Segment '%1!' does not have a threshold at '%2!' pages."
** 17905, "You may not drop the log's last-chance threshold."
** 17906, "Dropping threshold for segment '%1!' at '%2!' pages."
** 17289, "Set your curwrite to the hurdle of current database."
*/

create procedure sp_dropthreshold
@dbname		varchar(255),		/* current database name */
@segname	varchar(255),		/* segment name		*/
@free_space	int			/* threshold level	*/
as

declare	@segno	int,
	@status	smallint,
	@msg	varchar(1024)

/*
** If we are under a user defined xact, disallow this since we may
** leave the dbtable's threshold cache out-of-sync if the end user
** rollbacks its xact.
*/
if @@trancount > 0
begin
     /*
		 ** 17260, "Can't run %1! from within a transaction."
		 */
		 raiserror 17260, "sp_dropthreshold"
		 return (1)
end

set transaction isolation level 1
set chained off

/*
** Make sure we are in the right database
*/
if (@dbname != db_name())
begin
	/*
	** 18031, "You are in the wrong database.  Say 'USE %1!', then run
	**         this procedure again."
	*/
	raiserror 18031, @dbname
	return (5)
end

/*
** Make sure our database is recent enough to contain Systhresholds
*/
if (select name from sysobjects
	where	name = 'systhresholds'
	  and	type = 'S')
   is NULL
begin
	/*
	** 17903, "Table '%1!' does not exist in database '%2!' -- cannot drop
	**	  thresholds."
	*/
	raiserror 17903, "systhresholds", @dbname
	return (1)
end

/*
** Make sure the user (is the DBO) or (has "sa_role")
*/
if ((user_id() != 1) and (proc_role("sa_role") < 1))
begin
	/*
	** 17875, "Only the DBO of database %1! or a user with System
	** Administrator (SA) authorization may add, delete, or modify
	** thresholds in that database."
	*/
	raiserror 17875, @dbname
	return (1)
end



/*
** Make sure the segment name is valid.
*/
select @segno = segment from syssegments where name = @segname
if @segno is NULL
begin
	/*
	** 17871, "There is no segment named '%1!'."
	*/
	raiserror 17871, @segname
	return (2)
end

/*
** Make sure the threshold exists
*/
if (select free_space from systhresholds
	where	segment = @segno
	  and	free_space = @free_space)
   is null
begin
	/*
	** 17904, "Segment '%1!' does not have a threshold at '%2!' pages."
	*/
	raiserror 17904, @segname, @free_space
	select segment_name=@segname, free_space
	from systhresholds
	where	segment = @segno

	return (3)
end

/* Make sure this is not the last-chance threshold for syslogs */
if @segname = 'logsegment' and
   (select status from systhresholds
	where segment = @segno
	  and free_space = @free_space) & 1 = 1
begin
	/*
	** 17905, "You may not drop the log's last-chance threshold."
	*/
	raiserror 17905
	return (4)
end

/*
** We have done all the tests we can.  Drop the threshold.
*/

/*
** 17906, "Dropping threshold for segment '%1!' at '%2!' pages."
*/
exec sp_getmessage 17906, @msg output
print @msg, @segname, @free_space

begin transaction delete_threshold
delete systhresholds
where	segment = @segno
  and	free_space = @free_space

if @@error != 0
begin
	rollback transaction
	/*
	** 17907, "Delete of systhresholds row failed."
	*/
	raiserror 17907
	return (1)
end
/*
** Last, rebuild the database threshold table
*/
dbcc dbrepair(@dbname, "newthreshold", @segname)


if @@error != 0
begin
rollback transaction
/*
** 17878, "Rebuild of the database threshold table failed."
 */
raiserror 17878
return (1)
end

commit transaction

return (0)
go
exec sp_procxmode 'sp_dropthreshold', 'anymode'
go
grant execute on sp_dropthreshold to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_droptype')
begin
	drop procedure sp_droptype
end
go
print "Installing sp_droptype"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_droptype"           17540
**
** 17540, "The type doesn't exist or you don't own it."
** 17541, "Type is being used. You cannot drop it."
** 17542, "Type has been dropped."
** 17704, "Curread label needs to dominate the database hurdle."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17844, "You do not own a user datatype of that name."
** 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
** 18302, "User '%1!' is not a valid user in the '%2!' database."
** 18331, "Drop failed.  Your curwrite label must match the security label of the type.  Check systypes."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%
2!'"
** 18787, "The type with name '%1!' does not exists."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_droptype
@typename varchar(255)			/* the user type to drop */
as

declare @typeid smallint		/* the typeid of the usertype to drop */
declare @msg    varchar(1024)
declare @dbname varchar(255)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_droptype', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Initialize @typeid so we can tell if we can't find it.
*/
select @typeid = 0

/*
**  Find the user type with @typename.  It must be a user type (usertype > 99)
**  and it must be owned by the person (or dbo) running the procedure.
*/
select @typeid = usertype
	from systypes
		where (uid = user_id() or user_id() = 1)
			and name = @typename
			and usertype > 99

if @typeid = 0
begin
	/*
	** 17540, "The type doesn't exist or you don't own it."
	*/
	raiserror 17540
	return (1)
end

/*
**  Check to see if the type is being used.  If it is, it can't be dropped.
*/
if exists (select *
		   from syscolumns
			   where usertype = @typeid)
begin
	/*
	** 17541, "Type is being used. You cannot drop it."
	*/
	raiserror 17541

	/*
	**  Show where it's being used.
	*/
	select object = o.name, type = o.type, owner = u.name, column = c.name,
		datatype = t.name
	from syscolumns c, systypes t, sysusers u, sysobjects o
		where c.usertype = @typeid
			and t.usertype = @typeid
			and o.uid = u.uid
			and c.id = o.id
	order by object, column

	return (1)
end



out_of_HA_checking:

/*
**  Everything is consistent so drop the type.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction	
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec



	delete from systypes
		where usertype = @typeid

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_droptype", @dbname
				
		rollback transaction rs_logexec
		return (1)
	end



commit transaction rs_logexec

/*
** 17542, "Type has been dropped."
*/
exec sp_getmessage 17542, @msg output
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)
go
exec sp_procxmode 'sp_droptype', 'anymode'
go
grant execute on sp_droptype to public
go
exec sp_procxmode 'sp_droptype', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropuser')
begin
	drop procedure sp_dropuser
end
go
print "Installing sp_dropuser"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_dropuser"           17543
**
** 17232, "No user with the specified name exists in the current database."
** 17289, "Set your curwrite to the hurdle of current database."
** 17431, "true"
** 17432, "false"
** 17543, "You cannot drop the 'database owner'."
** 17544, "You cannot drop the 'guest' user from master database or a temporary
**         database."
** 17545, "You cannot drop user because user '%1!' owns objects in database."
** 17546, "You cannot drop user because user '%1!' owns types in database."
** 17547, "The dependent aliases were also dropped."
** 17548, "User has been dropped from current database."
** 17549, "You cannot drop user because user '%1!'  owns grantable
**         privileges and granted them to other users.  The user
** 	   has granted the following privileges:"
** 17673, "All"
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18033, "You cannot drop user because user '%1!' owns thresholds in database."
** 18053, "User '%1!' was granted grantable privileges by the following users:"
** 18075, "Set your maxwrite label correctly."
** 18554, "You cannot drop user '%1!' because stored proc '%2!' owned by it 
**	   is bound to an execution class. Use sp_unbindexeclass before 
**	   dropping user."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18797, "Unable to find a user with name '%1!' and login id '%2!' in sysusers."
** 18815, "You cannot drop user '%1!' because it still owns objects, types, thresholds, privileges, and/or execution classes on the companion server '%2!'.  Issue stored procedure '%3!' on server '%4!' for details."
** 19941, "You cannot drop the user because the suid value for user '%1!' is
**        not unique in the database."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	After that, you need to add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_dropuser
@name_in_db varchar(255)			/* user name to drop */
as

declare @suid int			/* suid of the user */
declare @uid int			/* uid of the user */
declare @objectcount int		/* count of objects user owns */
declare @typecount int			/* count of types user owns */
declare @grantcount int			/* count of grants user made */
declare	@userdropped int		/* flag to indicate user was dropped */
declare @threshcount int		/* count of thresholds bound by user */
declare @spexebndcount int		/* cnt of user owned sp exe bindings */
declare @sp_name varchar(255)		/* name of stored proc */
declare @msg varchar(1024)
declare @msg_all   varchar(30)		/* msg for "all" equivalent */
declare @msg_true  varchar(30)		/* msg for "true" equivalent */
declare @msg_false varchar(30)		/* msg for "false" equivalent */
declare @dummy	int
declare @dbname varchar(255)
declare @tempdb_mask   int	/* All database status bit for a tempdb */
declare @isatempdb int			/* is database a temporary database */
declare @err1 int			/* temp. variable to store @@error */

declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_dropuser', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA or SSO role can execute it.
**  Call proc_role() with the required SA role.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("sso_role", show_role()) = 0)
	begin
		select @dummy = proc_role("sa_role")
		select @dummy = proc_role("sso_role")
		return(1)
	end
end

if (charindex("sa_role", show_role()) > 0)
	select @dummy = proc_role("sa_role")

if (charindex("sso_role", show_role()) > 0)
	select @dummy = proc_role("sso_role")

/*
**  See if the user exists in the database.
*/
select @uid = uid, @suid = suid from sysusers
  where name = @name_in_db and 
	((uid < @@mingroupid and uid != 0) or (uid > @@maxgroupid))

/*
**  No such user so return.
*/
if @uid is NULL
begin
	/*
	** 17232, "No user with the specified name exists in the current database."
	*/
	raiserror 17232
	return (1)
end



out_of_HA_checking:

/*
**  Big trouble if dbo (uid = 1) is dropped so check.
*/
if @uid = 1
begin
	/*
	** 17543, "You cannot drop the 'database owner'."
	*/
	raiserror 17543
	return (1)
end

/*
** Check to see if we are dealing with a temporary database.
*/
select @tempdb_mask = number
	from master.dbo.spt_values
	where type = "D3" and name = "TEMPDB STATUS MASK"

if (db_id() = 2) or exists (select * from master..sysdatabases 
		       where dbid = db_id() 
		       and (status3 & @tempdb_mask) != 0) 
begin
	select @isatempdb = 1
end

/*
**  Trouble if guest gets dropped from master or tempdb, so check.
*/
if (@name_in_db = "guest" and (db_id() = 1 or @isatempdb = 1))
begin
	/*
	** 17544, "You cannot drop the 'guest' user from master or tempdb."
	*/
	raiserror 17544
	return(1)
end

/*
**  If the user owns any objects or datatypes and we're not
**  forcing the drop, return without doing anything.
*/
select @objectcount = count(*)
	   from sysobjects
		   where uid = @uid
select @typecount = count(*)
	from systypes
		where uid = @uid
select @grantcount = count(*)
	from sysprotects
		where grantor = @uid
			and id not in (select id from sysobjects
						where uid = @uid)
select @threshcount = count(*)
	from systhresholds
		where suid = @suid

select @spexebndcount = count(*)
	from sysattributes
		where (class = 6 and object_type = 'PR' and object_info1 = @uid)

if @objectcount > 0 or @typecount > 0 or @grantcount > 0 or @threshcount > 0 or
		@spexebndcount > 0
begin
	if @objectcount > 0
	begin
		/*
		** 17545, "You cannot drop user because user '%1!' owns objects in database."
		*/
		raiserror 17545, @name_in_db
		select name, type
			from sysobjects
				where uid = @uid
	end

	if @typecount > 0
	begin
		/*
		** 17546, "You cannot drop user because user '%1!' owns types in database."
		*/
		raiserror 17546, @name_in_db
		select user_type = a.name, physical_type = b.name
			from systypes a, systypes b
				where a.uid = @uid
					and a.type = b.type
					and b.usertype < 100
	end

	if @grantcount > 0
	begin

		/*
		** 17431, "true"
		** 17432, "false"
		*/
		exec sp_getmessage 17431, @msg_true output
		exec sp_getmessage 17432, @msg_false output
		/* 17673, "All" */
		exec sp_getmessage 17673, @msg_all out

		/* create and populate temp tables so that we can map 
		** column bit map to names 
		*/
		create table #sysprotects1 (id int, uid int, 
					    action smallint,
					    protecttype tinyint,
					    grantor int, number int)

		create table #sysprotects2 (id int, col_count smallint)

		insert into #sysprotects2 (id, col_count)
			select id, count (*)
			from syscolumns
			group by id

		insert into #sysprotects1 (id, uid, action, protecttype,
			grantor, number)
			select distinct
				p.id, p.uid, p.action, p.protecttype,
				p.grantor, c.number
				from sysprotects p, master.dbo.spt_values c
				where (~isnull (convert(tinyint, substring(p.columns, c.low, 1)), 0) & c.high != 0
					and c.number <= (select col_count from #sysprotects2 where id = p.id))
					and c.type = "P"
					and c.number <= 1024
					and p.columns is not null
					and convert(tinyint, substring(p.columns, 1, 1)) & 0x1 != 0
					and (convert(tinyint, substring(p.columns, 1, 1)) & 0xfe != 0
						or substring(p.columns, 2, 1) is not null)

		insert into #sysprotects1 (id, uid, action, protecttype,
			grantor, number)
			select distinct
				p.id, p.uid, p.action, p.protecttype,
				p.grantor, c.number
				from sysprotects p, master.dbo.spt_values c
				where convert(tinyint, substring(isnull(p.columns, 0x1), c.low, 1))
					& c.high != 0
					and c.type = "P"
					and c.number <= 1024
					and (p.columns is null
						or convert(tinyint, substring(p.columns, 1, 1)) & 0x1 = 0
						or (convert(tinyint, substring(p.columns, 1, 1)) & 0xfe = 0
							and substring(p.columns, 2, 1) is null))

		/* Set nocount on to avoid intermingling of output */
		set nocount on

		/*
		** 17549, "You cannot drop user because user '%1!' owns grantable
		**         privileges and granted them to other users.  The user
		** 	   has granted the following privileges:"
		*/
		raiserror 17549, @name_in_db
		print " "

		select grantee = u.name, 
			object = o.name, 
			column = substring(isnull(col_name(p.id, p.number), 
						  @msg_all), 1, 10),
			privilege = s.name
		from sysusers u, sysobjects o, #sysprotects1 p, 
		     master.dbo.spt_values s
		where p.grantor = @uid and p.uid = u.uid and p.protecttype < 2
	 	     and p.id = o.id and s.number = p.action 
		     and s.name is not NULL
		     and s.type = 'T'
		order by grantee, object, privilege

		/*
		** 18053, "User '%1!' was granted grantable privileges by the
		**         following users:"
		*/
		exec sp_getmessage 18053, @msg output
		print " "
		print @msg, @name_in_db
		
		select distinct grantor = u.name
		from sysusers u, sysprotects p
		where p.uid = @uid and u.uid = p.grantor and p.protecttype = 0
		order by grantor
	end

	if @threshcount > 0
	begin
		/*
		** 18033, "You cannot drop user because user '%1!' owns thresholds in database."
		*/
		raiserror 18033, @name_in_db
		select "Segment name" = g.name, "Free pages" = t.free_space
			from syssegments g, systhresholds t
				where t.suid = @suid
				  and t.segment = g.segment
	end

	if @spexebndcount > 0
	begin
		select @sp_name = object_cinfo from sysattributes
		where (class = 6 and object_type = 'PR' and object_info1 =@uid)
		/*
		** 18554, "You cannot drop user '%1!' because stored proc '%2!'
		**	 owned by it is bound to an execution class. Use 
		**	 sp_unbindexeclass before dropping user."
		*/
		raiserror 18554, @name_in_db, @sp_name
	end
	return (1)
end

/*
** Check if userid appears in sysprocesses. In that case somebody
** is still using it so we can not remove it.
*/
if exists (select * from master.dbo.sysprocesses where uid = @uid
			and dbid = db_id())
begin
	/*
	** 17915, "Warning: the specified account is currently active."
	*/
	exec sp_getmessage 17915, @msg output
	print @msg

	/*
	** 17918, "Nothing changed."
	*/
	exec sp_getmessage 17918, @msg output
	print @msg
	return (1)
end

/*
**  Drop the user.
**  Also drop any references to the user in the sysprotects table.
**  If anyone is aliased to the user, drop them also.
**
** IMPORTANT: The name rs_logexec is significant. It is used by 
** Replication Server.
*/



begin transaction rs_logexec



	delete from sysusers
		where suid = @suid
	select @err1 = @@error, @userdropped = @@rowcount



	delete from sysprotects
		where uid = @uid


	
	/*
	**  Drop any dependent aliases.
	*/
	if exists (select *
			from sysalternates
				where altsuid = @suid)
	begin
		delete from sysalternates
			where altsuid = @suid


		/*
		** 17547, "The dependent aliases were also dropped."
		*/
		exec sp_getmessage 17547, @msg output
		print @msg
	end

	/* 
	**  Delete entries from sysattributes
	*/
	delete from sysattributes
		where object_type = "U"
		and object = @uid



        /* Delete entries from sysencryptkeys */

        if exists (select * from sysencryptkeys
                        where uid = @uid)
        begin
                delete from sysencryptkeys
                        where uid = @uid
        end



	if @userdropped != 1
	begin
		/*
		** 19941, "You cannot drop the user because the suid value for
		** user '%1!' is not unique in the database."
		*/
		raiserror 19941, @name_in_db

		goto clean_all
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_dropuser", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end



commit transaction rs_logexec

print_msg:

/*
** 17548, "User has been dropped from current database."
*/
exec sp_getmessage 17548, @msg output
print @msg

return (0)

clean_all:
	rollback transaction rs_logexec
	return (1)
go
exec sp_procxmode 'sp_dropuser', 'anymode'
go
grant execute on sp_dropuser to public
go
exec sp_procxmode 'sp_dropuser', 'rep_current'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addextendedproc')
begin
	drop procedure sp_addextendedproc
end
go
print "Installing sp_addextendedproc"
go


/* 
** Messages from addextendedproc
**
** 17260, "Can't run %1! from within a transaction." 
** 18388, "You must be in the master database to run %1!"
** 17240, "'%1!' is not a valid name."
** 18387  "addextendedproc failed. Check the server error log file."
*/

create procedure sp_addextendedproc
		@esp_name  varchar(255), 	/* esp name */
		@dll_name  varchar(259) 		/* dll name (which may
						   include extension) */
as


/* If we're not in the master database, disallow addextendedproc */

if db_name() != "master"
begin
	/*
	** 18388, "You must be in the master database in order to run %1!
	*/
	raiserror 18388, "sp_addextendedproc"
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction." 
        */
	raiserror 17260, "sp_addextendedproc"
	return(1)
end

set chained off

set transaction isolation level 1
/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sa_role") = 0)
        return(1) 

/* check that esp_name is a valid identifier */
if valid_name(@esp_name,255) = 0
begin
        /*
        ** 17240, "'%1!' is not a valid name."
        */
	raiserror 17240, @esp_name
	return(1)
end

/* can't check that dll_name is valid since it might
** include .syntax, so check length only:
*/
if char_length(@dll_name) > 255 
begin
        /*
        ** 17240, "'%1!' is not a valid name." 
        */
	raiserror 17240, @dll_name
	return(1)
end


dbcc addextendedproc(@esp_name, @dll_name)

if (@@error != 0)
begin
	/*
	** 18387, "sp_addextendedproc failed."
	*/
	raiserror 18387
	return (1)
end

return(0)

go
exec sp_procxmode 'sp_addextendedproc', 'anymode'
go
grant execute on sp_addextendedproc to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropextendedproc')
begin
	drop procedure sp_dropextendedproc
end
go
print "Installing sp_dropextendedproc"
go


/*
** Messages from dropextendedproc
**
** 17260, "Can't run %1! from within a transaction." 
** 18388, "You must be in the 'master' database in order to run %1!
** 17240, "'%1!' is not a valid name."
** 18389, "sp_dropextendedproc failed."
*/
create procedure sp_dropextendedproc
		@esp_name  varchar(255)
as

declare	@maxlen	int

/* If we're not in master, disallow this */

if db_name() != "master"
begin
	/*
	** 18388, "You must be in the 'master' database in order to run %1!
	*/
	raiserror 18388, "sp_dropextendedproc"
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction." 
        */
	raiserror 17260, "sp_dropextendedproc"
	return(1)
end

set chained off

set transaction isolation level 1
/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print an error message if required.
*/
if (proc_role("sa_role") = 0)
        return(1)

/* check that esp_name is a valid identifier */
select @maxlen = length from syscolumns
	 where id = object_id("sysobjects") and name="name"

if valid_name(@esp_name, @maxlen) = 0
begin
        /*
        ** 17240, "'%1!' is not a valid name."
        */
	raiserror 17240, @esp_name
	return(1)
end

dbcc dropextendedproc(@esp_name)

if (@@error != 0)
begin
	/*
	** 18389, "sp_dropextendedproc failed."
	*/
	raiserror 18389
	return (1)
end

return(0)
go
exec sp_procxmode 'sp_dropextendedproc', 'anymode'
go
grant execute on sp_dropextendedproc to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_freedll')
begin
	drop procedure sp_freedll
end
go
print "Installing sp_freedll"
go


/* 
** Messages from freedll
**
** 17260, "Can't run %1! from within a transaction." 
** 17240, "'%1!' is not a valid name." 
** 18393, "DLL for the extended stored procedure '%1!' is not found." 
** 18392, "sp_freedll failed."
*/

create procedure sp_freedll
		@dll_name  varchar(259)		/* dll name (which may
						   include extension) */
as


/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction." 
        */
	raiserror 17260, "sp_freedll"
	return(1)
end

set chained off

set transaction isolation level 1
/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
        return(1)

/* 
** Remove optional . and extension (.dll or .so) from @dllname
*/
declare @dotposition int
select @dotposition = patindex("%.%", @dll_name)
if (@dotposition > 0)
	select @dll_name = substring(@dll_name, 1, @dotposition - 1)

/*
**  Check to see that the @dll_name is valid.
*/

if valid_name(@dll_name, 255) = 0
begin
        /*
        ** 17240, "'%1!' is not a valid name." 
        */
	raiserror 17240, @dll_name
	return(1)
end

/*
**  Make sure the dll exists.
*/
if (not exists (select *
        from sysobjects o
	where getdllname(o.id)= @dll_name
	and o.type = 'XP'
	and (o.sysstat & 15) = 4))
begin
        /*
	** 18393, "DLL for the extended stored procedure '%1!' is not found."
        */
	raiserror 18393, @dll_name
	return(1)
end

/*
** Now unload the DLL.
*/
dbcc spfreedll(@dll_name) 

if (@@error != 0)
begin
	/*
	** 18392, "sp_freedll failed."
	*/
	raiserror 18392
	return (1)
end

return(0)
go
exec sp_procxmode 'sp_freedll', 'anymode'
go
grant execute on sp_freedll to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpextendedproc')
begin
	drop procedure sp_helpextendedproc
end
go
print "Installing sp_helpextendedproc"
go


create procedure sp_helpextendedproc
	@esp_name  varchar(255) = NULL	/* esp name */
as

declare @obj_id         int
declare @maxlen		int

if @@trancount = 0
begin
        set chained off
end

set transaction isolation level 1

set nocount on

if @esp_name is NULL
begin
        /*
        **  If no @esp_name given, give a little info about all ESPs
        **  in this database.  ESPs are indentified by the following
        **  conditions:
        **      1. The sysobjects row for the object must have a type
        **         of `XP'
        **      2. The object must be a stored procedure, which is
        **         determined by the systat field
        **         of the sysobjects-row for this object:
        **              sysstat & 15  = 4       stored procedure
        **
        **  Note: 0x80f is the mask for sysstats (=2063decimal).
        **        800 is used by Stratus for external tables.
        */
	 select ESP_Name = o.name,
		DLL_Name = getdllname(o.id)
	 into #helpexten1rs
		from sysobjects o
		where   (o.sysstat & 15) = 4
		and     o.type = 'XP'
                /* Call object_id() so that the access permissions
                ** of the current user will be validated.
                */
		and     o.id = object_id(user_name(o.uid) + '.' + o.name)
	 exec sp_autoformat @fulltabname = #helpexten1rs,
		@selectlist = "'ESP NAME' = ESP_Name, 'DLL Name' = DLL_Name",
		@orderby = "order by DLL_Name" 
	 drop table #helpexten1rs 
end
else
begin
	/*
        **  Make sure the @esp_name is local to the current database.
        */
        if @esp_name like "%.%.%"
        begin
		if substring(@esp_name, 1, charindex(".", @esp_name) - 1) != db_name()
		begin
			/* 17460, "Object must be in the current database." */
			raiserror 17460
			return(1)
		end
        end


	/* check that esp_name is a valid identifier */
	select @maxlen = length from syscolumns 
	where id = object_id("sysobjects") and name = "name"
	if valid_name(@esp_name, @maxlen) = 0
	begin
	        /*
	        ** 17240, "'%1!' is not a valid name."
	        */
		raiserror 17240, @esp_name
		return(1)
	end

        if not exists (select *
                       from sysobjects
                       where id = object_id(@esp_name))
        begin
	/*
	** The extended stored procedure '%1!' is not in sysobjects for this user.
	*/
		raiserror 18391, @esp_name
		return(1)
        end

        select @obj_id = object_id(@esp_name)

        select  ESP_Name = o.name,
                DLL_Name = getdllname(o.id)
	into #helpexten2rs
                from    sysobjects o
                where   (o.sysstat & 15) = 4
                and     o.type = 'XP'
                and     o.id = object_id(@esp_name)
	exec sp_autoformat @fulltabname = #helpexten2rs,
		@selectlist = "'ESP Name' = ESP_Name, 'DLL Name' = DLL_Name"
	drop table #helpexten2rs

end

return(0)
go
exec sp_procxmode 'sp_helpextendedproc', 'anymode'
go
grant execute on sp_helpextendedproc to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
**  System Extended Stored Procedures added by Eagle.
**  This file contains generic esps.  Also see nt386 version.
*/

if exists (select * from sysobjects
	where name = "xp_cmdshell")
    drop procedure xp_cmdshell
go

create procedure xp_cmdshell @cmdstr varchar(8192) as external name sybsyesp
go




if exists (select * from sysobjects
	where name = "xp_freedll")
    drop procedure xp_freedll
go

create procedure xp_freedll @ddlname varchar(255) as external name sybsyesp
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_sargs_qpgroup')
begin
	drop procedure sp_aux_sargs_qpgroup
end
go
print "Installing sp_aux_sargs_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_aux_sargs_qpgroup"
**
** none
*/
 
/*
** sp_aux_sargs_qpgroup encapsulates the SARGs settings 
** for the SYATTRIBUTES AP GID lookup by AP name. 
*/

create procedure sp_aux_sargs_qpgroup
@class		int out,
@attribute	int out,
@object_type	char(2) out
as
	select
		@class = 12,
		@attribute = 0,
		@object_type = "qp"

	return 0
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_get_qpgroup')
begin
	drop procedure sp_aux_get_qpgroup
end
go
print "Installing sp_aux_get_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_aux_get_qpgroup"
**
** Warning : there are %1! query plans groups in this database that are named '%2!'. Using the group with ID %3!.
*/
 
/*
** sp_aux_get_qpgroup encapsulates the SYSATTRIBUTES AP GID 
** lookup by AP group name. 
*/

create procedure sp_aux_get_qpgroup
@name	varchar(30),
@id	int out
as
	declare
		@class		int,
		@attribute	int,
		@object_type	char(2),

		@rows		int

	/* get the SARGs */
	exec sp_aux_sargs_qpgroup @class out, @attribute out, @object_type out

	select @id = object from sysattributes
		holdlock
		where	class = @class
			and attribute = @attribute
			and object_type = @object_type
			and object_cinfo = @name

	select @rows = @@rowcount

	if @rows > 1
	begin
		/* 18659, "Warning : there are %1! query plans groups in this database that are named '%2!'. Using the group with ID %3!." */
		raiserror 18659, @rows, @name, @id
	end

return 0
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_add_qpgroup')
begin
	drop procedure sp_add_qpgroup
end
go
print "Installing sp_add_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_add_qpgroup"
**
** 17240, "'%1!' is not a valid name."
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18660, "There is already a query plans group named '%1!' in this database."
*/
 
/*
** sp_add_qpgroup adds a new AP GID - group name 
** association in SYSATTRIBUTES. 
*/

create procedure sp_add_qpgroup
@new_name	varchar(255)
as
	declare
		@gid		int,
		@class		int,
		@attribute	int,
		@object_type	char(2),
		@dbname		char(255)

	set nocount on

	select @dbname = db_name()

	/* Check to see that the @new_name is valid. */
	if ( (@new_name is not null) and (char_length(@new_name) > 30))
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @new_name
		return 1
	end

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230
		return 2
	end

	/*
	** AP group handling may not be done within a transaction, 
	** specifically for sp_add_qpgroup. 
	**
	** Indeed, once a group is created, it can be enabled in 
	** DUMP mode and plans start being captured therein - as 
	** nested internal Xacts. So if the group creation is part 
	** of an user Xact that is rolled back, the APs stay behind, 
	** group-less. 
	**
	** sp_drop_qpgroup and sp_rename_qpgroup don't raise 
	** the same issue, but for coherence they are subject 
	** to the same limitation.
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_add_qpgroup"
		return 1
	end

	/* Don't start a transaction for the user, he does not expect it. */
	set chained off

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	exec sp_aux_sargs_qpgroup @class out, @attribute out, @object_type out

	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	exec sp_aux_get_qpgroup @new_name, @gid out

	if @gid is not null
	begin
		/* 18660, "There is already a query plans group named '%1!' in this database." */
		raiserror 18660, @new_name
		rollback transaction rs_logexec
		return 1
	end

	select @gid = isnull(max(object) + 1, 1) from sysattributes
		holdlock
		where	class = @class
			and attribute = @attribute
			and object_type = @object_type


		insert into sysattributes 
			(class, attribute, object_type, object, object_cinfo)
			values (@class, @attribute, @object_type, @gid, @new_name)

		/*
		** Write the log record to replicate this invocation
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**          because there was an error in writing
			**          the replication log record."
			*/
			raiserror 17756, "sp_add_qpgroup", @dbname
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction rs_logexec
	return 0
go
exec sp_procxmode 'sp_add_qpgroup', 'anymode'
go
grant execute on sp_add_qpgroup to public
go
exec sp_procxmode 'sp_add_qpgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_qpgroup')
begin
	drop procedure sp_drop_qpgroup
end
go
print "Installing sp_drop_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_drop_qpgroup"
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18682, "Cannot drop the default query plans groups ap_stdin and ap_stdout."
** 18639, "The is no query plans group named '%1!' in this database."
** 18651, "Cannot drop the query plans group '%1!', as it is not empty."
*/
 
/*
** sp_drop_qpgroup drops an AP group, provided it's empty. 
** Straightforward SYSATTRIBUTES deletion by ID. If the 
** group is not empty, no SYSQUERYPLANS deletion is made; 
** rather, the drop fails.
*/

create procedure sp_drop_qpgroup
@name	varchar(255)
as
	declare
		@gid		int,
		@class		int,
		@attribute	int,
		@object_type	char(2),
		@dbname		char(255)

	set nocount on

	select @dbname = db_name()

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230
		return 2
	end

	/*
	** AP group handling may not be done within a transaction, 
	** specifically for sp_add_qpgroup. 
	**
	** Indeed, once a group is created, it can be enabled in 
	** DUMP mode and plans start being captured therein - as 
	** nested internal Xacts. So if the group creation is part 
	** of an user Xact that is rolled back, the APs stay behind, 
	** group-less. 
	**
	** sp_drop_qpgroup and sp_rename_qpgroup don't raise 
	** the same issue, but for coherence they are subject 
	** to the same limitation.
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_drop_qpgroup"
		return 1
	end

	/* Don't start a transaction for the user, he does not expect it. */
	set chained off

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	/* it's illegal to drop the default AP groups */
	if @name = "ap_stdin" or @name = "ap_stdout"
	begin
		/* 18682, "Cannot drop the default query plans groups ap_stdin and ap_stdout." */
		raiserror 18682
		return 2
	end

	exec sp_aux_sargs_qpgroup @class out, @attribute out, @object_type out

	exec sp_aux_get_qpgroup @name, @gid out

	if @gid is null
	begin
		/* 18639, "The is no query plans group named '%1!' in this database." */
		raiserror 18639, @name
		return 1
	end

	/* check there are no APs in this group, long shared lock */
	/* 
	** Note: no need to use holdlock for the following select
	** because if there is any row existing, the SP returns
	** immediately. Using holdlock unnecessarilly asks for
	** a lot of row locks configured for the server
	** when there are a lot of qualifying rows.
	*/
	if exists (select * from sysqueryplans
			where gid = @gid)
	begin
		/* 18651, "Cannot drop the query plans group '%1!', as it is not empty." */
		raiserror 18651, @name
		return 2
	end

	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

		delete from sysattributes
			where	class = @class
				and attribute = @attribute
				and object_type = @object_type
				and object = @gid

		/*
		** Write the log record to replicate this invocation
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**          because there was an error in writing
			**          the replication log record."
			*/
			raiserror 17756, "sp_drop_qpgroup", @dbname
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction rs_logexec
	return 0
go
exec sp_procxmode 'sp_drop_qpgroup', 'anymode'
go
grant execute on sp_drop_qpgroup to public
go
exec sp_procxmode 'sp_drop_qpgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_export_qpgroup')
begin
	drop procedure sp_export_qpgroup
end
go
print "Installing sp_export_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_export_qpgroup"
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 17260, "Can't run %1! from within a transaction."
** 17703, "The name supplied is not a user, group, or aliased."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18639, "There is no query plans group named '%1!' in this database."
*/
 
/*
** sp_export_qpgroup exports in an user table (that it creates) 
** the SYSQUERYPLANS section that corresponds to an AP group of 
** a given user. This table has an opaque format (actually the 
** same as SYSQUERYPLANS), and can be used by sp_import_qpgroup, 
** maybe after having been transferred to another database or 
** server. 
*/

create procedure sp_export_qpgroup
@usr	varchar(255),
@group	varchar(255),
@tab	varchar(255)
as
	declare
		@gid		int,
		@uid		int,
		@s_gid		varchar(10),
		@s_uid		varchar(10),
		@dbname		char(30)

	set nocount on

	select @dbname = db_name()

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230
		return 2
	end

	/*
	** AP group handling may not be done within a transaction. 
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_export_qpgroup"
		return 1
	end

	/* Don't start a transaction for the user, he does not expect it. */
	set chained off

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	exec sp_aux_get_qpgroup @group, @gid out

	if @gid is null 
	begin
		/* 18639, "There is no query plans group named '%1!' in this database." */
		raiserror 18639, @group
		return 1
	end

	select @uid = user_id(@usr)

	if @uid is null
	begin
		/* 17703, "The name supplied is not a user, group, or aliased." */
		raiserror 17703
		return 2
	end

	/* prepare the UID and GID as VARCHAR, for EXEC ("...") */
	select @s_uid = convert(varchar(10), @uid)
	select @s_gid = convert(varchar(10), @gid)
	
		/* create the export table and feed it with the APs */
	execute (
		"create table " + @tab + " (
			uid		int,
			gid		int,
			hashkey		int,
			id		int,
			type		smallint,
			sequence	smallint,
			status		int null,
			text		varchar(255)
		)")
		/*
		** This transaction also writes a log record for replicating the
		** invocation of this procedure. If logexec() fails, the transaction
		** is aborted.
		**
		** IMPORTANT: The name rs_logexec is significant and is used by
		** Replication Server.
		*/
		begin transaction rs_logexec

			execute (
				"insert into " + @tab + 
				" select * 
				from sysqueryplans where uid = " + @s_uid +
				"and gid = " + @s_gid
				)
		/*
		** Write the log record to replicate this invocation
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**          because there was an error in writing
			**          the replication log record."
			*/
			exec ( "drop table " +@tab )
			raiserror 17756, "sp_export_qpgroup", @dbname
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction rs_logexec
	return 0
go
exec sp_procxmode 'sp_export_qpgroup', 'anymode'
go
grant execute on sp_export_qpgroup to public
go
exec sp_procxmode 'sp_export_qpgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_import_qpgroup')
begin
	drop procedure sp_import_qpgroup
end
go
print "Installing sp_import_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_import_qpgroup"
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 17260, "Can't run %1! from within a transaction."
** 17703, "The name supplied is not a user, group, or aliased."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18660, "There is already a query plans group named '%1!' in this database."
*/
 
/*
** sp_import_qpgroup inserts in SYSQUERYPLANS the opaque user table 
** created by sp_export_qpgroup. By that , it creates a new group 
** (with the given name) for a specific user. 
*/

create procedure sp_import_qpgroup
@tab	varchar(255),
@usr	varchar(30),
@group	varchar(30)
as
	declare
		@gid	int,
		@uid	int,
		@old_id	int,
		@new_id	int,
		@dbname	char(30)


	set nocount on

	select @dbname = db_name()

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230
		return 2
	end

	/*
	** AP group handling may not be done within a transaction. 
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_import_qpgroup"
		return 1
	end

	/* Don't start a transaction for the user, he does not expect it. */
	set chained off

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	exec sp_aux_get_qpgroup @group, @gid out

	select @uid = user_id(@usr)

	if @uid is null
	begin
		/* 17703, "The name supplied is not a user, group, or aliased." */
		raiserror 17703
		return 2
	end

	if @gid is null
	begin
		/* if the group doesn't exist, add it */
		exec sp_add_qpgroup @group
		exec sp_aux_get_qpgroup @group, @gid out
	end
	else
	begin
		/* if it exists, check that it's empty */
		if exists (select 1
				from sysqueryplans
				where gid = @gid
					and uid = @uid)
		begin
			/* 18660, "There is already a query plans group named '%1!' in this database." */
			raiserror 18660, @group
			return 2
		end
	end

	/*
	** Create 2 work tables, one with the structure of SYSQUERYPLANS, 
	** to hold the APs to be imported, another one to hold the old-new
	** AP id mapping. Note that the first table will be useless when 
	** dynamic cursors will work in TSQL, as @tab could be used instead.
	*/

	select * into #aps
		from sysqueryplans
		where 1 = 0

	create table #ids_map (old_id int, new_id int)

	execute ("insert into #aps 
			select * from " + @tab
	)

	/*
	** For each AP to insert, generate the new ID and update the 
	** old-new AP ID map. 
	*/

	declare ids cursor for select distinct id from #aps

	open ids
	fetch ids into @old_id

	while @@sqlstatus = 0
	begin
		create plan 'select 1' '()' into @group
				and set @new_id

		delete sysqueryplans where id = @new_id
		insert #ids_map values (@old_id, @new_id)

		fetch ids into @old_id
	end

	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

		/* finally, feed SYSQUERYPLANS */
		insert sysqueryplans
			select @uid, @gid, t.hashkey, m.new_id, 
				t.type, t.sequence, t.status, t.text,
				t.dbid, t.qpdate, t.sprocid, t.hashkey2,
				t.key1, t.key2, t.key3, t.key4
			from #aps t, #ids_map m
			where t.id = m.old_id
		
		/*
		** Write the log record to replicate this invocation
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**          because there was an error in writing
			**          the replication log record."
			*/
			raiserror 17756, "sp_import_qpgroup", @dbname
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction rs_logexec
	return 0
go
exec sp_procxmode 'sp_import_qpgroup', 'anymode'
go
grant execute on sp_import_qpgroup to public
go
exec sp_procxmode 'sp_import_qpgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_rename_qpgroup')
begin
	drop procedure sp_rename_qpgroup
end
go
print "Installing sp_rename_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_rename_qpgroup"
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18682, "Cannot drop or rename the default query plans groups ap_stdin and ap_stdout."
** 18639, "The is no query plans group named '%1!' in this database."
** 18660, "There is already a query plans group named '%1!' in this database."
*/
 
/*
** sp_rename_qpgroup changes the name of an AP group, by 
** modifying the SYSATTRIBUTES name/GID association.
*/

create procedure sp_rename_qpgroup
@old_name	varchar(30),
@new_name	varchar(30)
as
	declare
		@gid		int,
		@class		int,
		@attribute	int,
		@object_type	char(2),
		@dbname		char(20)

	set nocount on

	select @dbname = db_name()

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230
		return 2
	end

	/*
	** AP group handling may not be done within a transaction, 
	** specifically for sp_add_qpgroup. 
	**
	** Indeed, once a group is created, it can be enabled in 
	** DUMP mode and plans start being captured therein - as 
	** nested internal Xacts. So if the group creation is part 
	** of an user Xact that is rolled back, the APs stay behind, 
	** group-less. 
	**
	** sp_drop_qpgroup and sp_rename_qpgroup don't raise 
	** the same issue, but for coherence they are subject 
	** to the same limitation.
	*/
	if @@trancount > 0
	begin
		/*
		** 17260, "Can't run %1! from within a transaction."
		*/
		raiserror 17260, "sp_rename_qpgroup"
		return 1
	end

	/* Don't start a transaction for the user, he does not expect it. */
	set chained off

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	exec sp_aux_sargs_qpgroup @class out, @attribute out, @object_type out
	
	/* check the new name is not already in use */
	exec sp_aux_get_qpgroup @new_name, @gid out

	if @gid is not null
	begin
		/* 18660, "There is already a query plans group named '%1!' in this database." */
		raiserror 18660, @new_name
		return 3
	end

	/* it's illegal to rename the default AP groups */
	if @old_name = "ap_stdin" or @old_name = "ap_stdout"
	begin
		/* 18682, "Cannot drop or rename the default query plans groups ap_stdin and ap_stdout." */
		raiserror 18682
		return 4
	end

	/* get the GID */
	exec sp_aux_get_qpgroup @old_name, @gid out

	if @gid is null
	begin
		/* 18639, "The is no query plans group named '%1!' in this database." */
		raiserror 18639, @old_name
		return 1
	end

	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

		/*
		** Update SYSATTRIBUTES with the new name.
		** The SARGs were prepared by sp_aux_sargs_qpgroup.
		*/
		update sysattributes
			set object_cinfo = @new_name
			where	class = @class
				and attribute = @attribute
				and object_type = @object_type
				and object = @gid

		/*
		** Write the log record to replicate this invocation
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**          because there was an error in writing
			**          the replication log record."
			*/
			raiserror 17756, "sp_rename_qpgroup", @dbname
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction rs_logexec
	return 0
go
exec sp_procxmode 'sp_rename_qpgroup', 'anymode'
go
grant execute on sp_rename_qpgroup to public
go
exec sp_procxmode 'sp_rename_qpgroup', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_qplan')
begin
	drop procedure sp_help_qplan
end
go
print "Installing sp_help_qplan"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_help_qplan"	
**
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
*/
 
/*
** sp_help_qplan displays a plan. The display modes can be "brief", 
** "list" and "full". The default display mode is "brief".
*/

create procedure sp_help_qplan
@id	int,
@mode	varchar(20) = "brief"
as
	declare	@uid	int
	declare @retval	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	if @mode = "list"
	begin
		select hashkey, id, 
			substring(text, 1, 20) + "..." as "query",
			(select substring(text, 1, 20) + "..."
				from sysqueryplans
				where	uid = isnull(@uid, uid)
					and id = @id
					and type = 100
					and sequence = 0) as "query_plan"
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 10
				and sequence = 0

		return 0
	end

	if @mode = "brief"
	begin
		select gid, hashkey, id
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 10
				and sequence = 0

		select  case 
				when char_length(text) <= 78 
					then substring(text, 1, 78) 
				else substring(text, 1, 75) + "..."
			end as "query"
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 10
				and sequence = 0

		select  case 
				when char_length(text) <= 78 
					then substring(text, 1, 78) 
				else substring(text, 1, 75) + "..."
			end as "query_plan"
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 100
				and sequence = 0

		return 0
	end

	if @mode = "full"
	begin
		select gid, hashkey, id
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 10
				and sequence = 0

		select text as "query" into #query_text
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 10
			order by sequence

		exec @retval = sp_autoformat #query_text
		drop table #query_text
		if (@retval != 0)
			return 1

		select text as "query_plan" into #plan_text 
			from sysqueryplans
			where   uid = isnull(@uid, uid)
				and id = @id
				and type = 100
			order by sequence

		exec @retval = sp_autoformat #plan_text
		drop table #plan_text
		if (@retval != 0)
			return 1

		return 0
	end

	/* 18640, "Unknown %1! option : '%2!'. Valid options are : %3!." */
	raiserror 18640, "sp_help_qplan", @mode, "'brief', 'list', 'full'"

	return 1
go

go
exec sp_procxmode 'sp_help_qplan', 'anymode'
go
grant execute on sp_help_qplan to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_qpgroup')
begin
	drop procedure sp_help_qpgroup
end
go
print "Installing sp_help_qpgroup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_help_qpgroup"
**
** 18641, "Query plan groups in database '%1!'"
** 18639, "The is no query plans group named '%1!' in this database."
** 18642, "Query plans group '%1!', GID %2!"
** 18643, "sysqueryplans rows consumption, number of query plans per row count"
** 18644, "Query plans that use the most sysqueryplans rows"
** 18645, "There is no hash key collision in this group."
** 18646, "Number of collisions per hash key"
** 18647, "Colliding query plan IDs per hash key"
** 18648, "Query plans in this group"
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
** 18649, "The query plans group is empty."
*/
 
/*
** sp_help_qpgroup displays information about an AP group. The legal 
** modes are : "full", "stats", "hash", "list", "queries", "plans" 
** or "counts".
*/

create procedure sp_help_qpgroup
@name	varchar(255) = null,
@mode	varchar(20) = "full"
as
	declare
		@msg		varchar(1024),
		@uid		int,
		@gid		int,
		@class		int,
		@attribute	int,
		@object_type	char(2)

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	exec sp_aux_sargs_qpgroup @class out, @attribute out, @object_type out

	if @name is null
	begin
		select @name = db_name()

		/* 18641, "Query plan groups in database '%1!'" */
		exec sp_getmessage 18641, @msg out
		print @msg, @name

		select object_cinfo,
			GID = object,
			Plans = count(distinct id)
		into #sphelpqpgroup1rs
			from sysattributes, sysqueryplans
			where	class = @class
				and attribute = @attribute
				and object_type = @object_type
				and uid = isnull(@uid, uid)
				and object *= gid
			group by object_cinfo, gid
		exec sp_autoformat @fulltabname = #sphelpqpgroup1rs,
			@selectlist = "'Group' = object_cinfo, GID, Plans",
			@orderby = "order by 1"
		drop table #sphelpqpgroup1rs

		return 0
	end

	exec sp_aux_get_qpgroup @name, @gid out

	if @gid is null
	begin
		/* 18639, "The is no query plans group named '%1!' in this database." */
		raiserror 18639, @name

		return 1
	end

	/* 18642, "Query plans group '%1!', GID %2!" */
	exec sp_getmessage 18642, @msg out
	print ""
	print @msg, @name, @gid
	print ""

	select count(*) as "Total Rows", count(distinct id) as "Total QueryPlans"
		from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and gid = @gid

	-- group summary modes

	if (@mode = "stats" or @mode = "full")
	begin
		select id, count(*) as cnt
			into #rows
			from sysqueryplans
			where uid = isnull(@uid, uid)
			and gid = @gid
			group by id

		/* 18643, "sysqueryplans rows consumption, number of query plans per row count" */
		exec sp_getmessage 18643, @msg out
		print @msg

		select cnt as "Rows", count(*) as "Plans"
			from #rows
			group by cnt 
			order by cnt desc

		if @@rowcount > 1
		begin
			/* 18644, "Query plans that use the most sysqueryplans rows" */
			exec sp_getmessage 18644, @msg out
			print @msg

			select cnt as "Rows", id as "Plan"
				from #rows
				where cnt > (select avg(cnt) + 1
						from #rows)
				order by cnt desc, id
		end

		if @mode != "full"
			return 0
	end

	if (@mode = "hash" or @mode = "full")
	begin
		select count(distinct hashkey) as "Hashkeys"
			from sysqueryplans
			where	uid = isnull(@uid, uid)
				and gid = @gid
				and type = 10
				and sequence = 0

		select hashkey, count(*) as collisions
			into #colls
			from sysqueryplans o
			where	uid = isnull(@uid, uid)
				and gid = @gid
				and type = 10
				and sequence = 0
				and exists (select * 
						from sysqueryplans
						where	uid = o.uid
							and gid = o.gid
							and hashkey = o.hashkey
							and id != o.id)
			group by hashkey

		if @@rowcount = 0
		begin
			/* 18645, "There is no hash key collision in this group." */
			exec sp_getmessage 18645, @msg out	
			print @msg
		end
		else
		begin
			/* 18646, "Number of collisions per hash key" */
			exec sp_getmessage 18646, @msg out
			print @msg

			select collisions, hashkey from #colls
				order by collisions desc, hashkey

			/* 18647, "Colliding query plan IDs per hash key" */
			exec sp_getmessage 18647, @msg out
			print @msg

			select c.collisions, c.hashkey, q.id
				from #colls c, sysqueryplans q
				where	gid = @gid
					and c.hashkey = q.hashkey
				group by c.collisions, c.hashkey, q.id
				order by c.collisions, c.hashkey, q.id
		end

		if @mode != "full"
			return 0
	end

	if @mode = "full"
		return 0

	-- per plan modes

	/* 18648, "Query plans in this group" */
	exec sp_getmessage 18648, @msg out

	print ""
	print  @msg

	if (@mode = "list")
	begin
		select hashkey, id, 
			(select substring(text, 1, 20) + "..."
				from sysqueryplans i
				where	o.id = i.id
					and type = 10
					and sequence = 0) as "query",
			(select substring(text, 1, 20) + "..."
				from sysqueryplans i
				where	o.id = i.id
					and type = 100
					and sequence = 0) as "plan"
			from sysqueryplans o
			where	uid = isnull(@uid, uid)
				and gid = @gid
			group by hashkey, id
			order by hashkey, id

		goto finish
	end

	if (@mode = "queries")
	begin
		select hashkey, id, 
			(select substring(text, 1, 50) + "..."
				from sysqueryplans i
				where	o.id = i.id
					and type = 10
					and sequence = 0) as "query"
			from sysqueryplans o
			where	uid = isnull(@uid, uid)
				and gid = @gid
			group by hashkey, id
			order by hashkey, id

		goto finish
	end

	if (@mode = "plans")
	begin
		select hashkey, id, 
			(select substring(text, 1, 50) + "..."
				from sysqueryplans i
				where	o.id = i.id
					and type = 100
					and sequence = 0) as "plan"
			from sysqueryplans o
			where	uid = isnull(@uid, uid)
				and gid = @gid
			group by hashkey, id
			order by hashkey, id

		goto finish
	end

	if (@mode = "counts")
	begin
		select count(*) as "Rows",
			sum(char_length(text)) as "Chars", 
			hashkey, id, 
			(select substring(text, 1, 25) + "..."
				from sysqueryplans i
				where	o.id = i.id
					and type = 10
					and sequence = 0) as "query"
			from sysqueryplans o
			where	uid = isnull(@uid, uid)
				and gid = @gid
			group by hashkey, id
			order by 1 desc, 2 desc, hashkey, id

		goto finish
	end

	/* 18640, "Unknown %1! option : '%2!'. Valid options are : %3!." */
	raiserror 18640, "sp_help_qpgroup", @mode, "'full', 'stats', 'hash', 'list', 'queries', 'plans', 'counts'"

	return 1

finish:
	if @@rowcount = 0
	begin
		/* 18649, "The query plans group is empty." */
		exec sp_getmessage 18649, @msg out
		print @msg
	end

	return 0
go

go
exec sp_procxmode 'sp_help_qpgroup', 'anymode'
go
grant execute on sp_help_qpgroup to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_qplan')
begin
	drop procedure sp_drop_qplan
end
go
print "Installing sp_drop_qplan"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_drop_qplan"
**
** 18636, "There is no query plan with the ID %1! in this database."
*/
 
/*
** sp_drop_qplan deletes a plan form SYSQUERYPLANS. 
** Straightforward delete by ID.
*/

create procedure sp_drop_qplan
@id	int
as
	declare	@uid	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	delete from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and id = @id

	if @@rowcount = 0
	begin
		/* 18636, "There is no query plan with the ID %1! in this database." */
		raiserror 18636, @id

		return 1
	end
	
	return 0
go

go
exec sp_procxmode 'sp_drop_qplan', 'anymode'
go
grant execute on sp_drop_qplan to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_find_qplan')
begin
	drop procedure sp_find_qplan
end
go
print "Installing sp_find_qplan"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_find_qplan"
*/
 
/*
** sp_find_qplan does a pattern matching SYSQUERYPLANS lookup. 
** @pattern is used as such, so any leading or trailing wildcards 
** must be explicitly part of it. As TSQL has no TEXT append 
** function, the pattern matching is done row by row. Text 
** crossing row boundaries that would match the pattern is thus 
** missed. Hence, all multi-row APs are signaled for manual 
** checking. Once we have a decent LOB in TSQL, this should be 
** revisited.
*/

create procedure sp_find_qplan
@pattern	varchar(255),
@group		varchar(30) = null
as
	declare
		@msg	varchar(255),
		@uid	int,
		@gid	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	if @group is not null
		exec sp_aux_get_qpgroup @group, @gid out

	/* get the easy ones - where the pattern is immediately found */
	select distinct id
		into #found
		from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and gid = isnull(@gid, gid)
			and text like @pattern

	/* now get the ones that span over rows and didn't match yet */
	select id 
		into #multi
		from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and gid = isnull(@gid, gid)
			and id not in (select id from #found)
		group by gid, id
		having count(*) > 2

	/* now look the pattern up on row boundaries */
	insert #found
		select distinct #multi.id
			from 
				#multi, 
				sysqueryplans prev, 
				sysqueryplans next
			where
				#multi.id = prev.id
				and #multi.id = next.id
				and prev.type = next.type
				and prev.sequence + 1 = next.sequence
				and substring(prev.text, 128, 128)
					+ substring(next.text, 1, 128)
					like  @pattern

	select gid, id, text from sysqueryplans
		where id in (select id from #found)
		order by gid, id, type, sequence

	return 0
go

go
exec sp_procxmode 'sp_find_qplan', 'anymode'
go
grant execute on sp_find_qplan to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_cmp_qplans')
begin
	drop procedure sp_cmp_qplans
end
go
print "Installing sp_cmp_qplans"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_cmp_qplans"
**
** 18636, "There is no query plan with the ID %1! in this database."
** 18692, "The queries are the same."
** 18693, "The queries are different."
** 18694, "The queries are different but have the same hash key."
** 18695, "The query plans are the same."
** 18696, "The query plans are different."
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
*/
 
/*
** sp_cmp_qplans compares 2 plans, and returns : 
**
** 0 - same query/plan
** +1 - different queries
** +2 - different queries and hash collision (does not accumulate with +1)
** +10 - different plans
** 100 - plan ID does not exist
**
** For instance, 2 different APs that belong to 2 different queries
** that collide on the hash key will return 2+10 = 12.
**
** Accepts an @mode parameter, when "quiet" only returns status, 
** when "brief" also gives messages, no "verbose" mode.
*/

create procedure sp_cmp_qplans
@id1	int,
@id2	int,
@mode	varchar(20) = "brief"
as
	declare 
		@uid	int,
		@h1	int,
		@h2	int,
		@query	int,
		@plan	int,
		@msg	varchar(1024)

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	/* check the hash keys first */

	select @h1 = (select distinct hashkey
			from sysqueryplans
			where 
				uid = isnull(@uid, uid)
				and id = @id1)

	select @h2 = (select distinct hashkey
			from sysqueryplans
			where 
				uid = isnull(@uid, uid)
				and id = @id2)

	if @h1 is null
		/* 18636, "There is no query plan with the ID %1! in this database." */
		raiserror 18636, @id1

	if @h2 is null
		/* 18636, "There is no query plan with the ID %1! in this database." */
		raiserror 18636, @id2

	/* fail if either ID is absent */
	if @h1 is null or @h2 is null
		return 100

	if @h1 != @h2
	begin
		select @query = 1
		goto plans
	end

	/* hash collision at least */
	select @query = 2

	if
		(select count(*)
			from sysqueryplans
			where 
				id = @id1
				and type = 10)
		!=
		(select count(*)
			from sysqueryplans
			where 
				id = @id2
				and type = 10)
		goto plans

	if exists (select * 
			from sysqueryplans p1, sysqueryplans p2
			where 
				p1.id = @id1
				and p2.id = @id2
				and p1.type = 10
				and p2.type = 10
				and p1.sequence = p2.sequence
				and isnull(rtrim(p1.text), " ") != isnull(rtrim(p2.text), " "))
		goto plans

	/* same query */
	select @query = 0

plans:

	/* assume different plans */
	select @plan = 10

	if
		(select count(*)
			from sysqueryplans
			where 
				id = @id1
				and type = 100)
		!=
		(select count(*)
			from sysqueryplans
			where 
				id = @id2
				and type = 100)
		goto ret

	if exists (select * 
			from sysqueryplans p1, sysqueryplans p2
			where 
				p1.id = @id1
				and p2.id = @id2
				and p1.type = 100
				and p2.type = 100
				and p1.sequence = p2.sequence
				and isnull(rtrim(p1.text), " ") != isnull(rtrim(p2.text), " "))
		goto ret

	/* same plan */
	select @plan = 0

ret:

	if @mode = "brief"
	begin
		/* query related messages */
		if @query = 0
		begin
			/* 18692, "The queries are the same." */
			exec sp_getmessage 18692, @msg out
		end
		else if @query = 1
		begin
			/* 18693, "The queries are different." */
			exec sp_getmessage 18693, @msg out
		end
		else if @query = 2
		begin
			/* 18694, "The queries are different but have the same hash key." */
			exec sp_getmessage 18694, @msg out
		end
			/* else wrong @query - do nothing */

		print @msg

		/* plan related messages */
		if @plan = 0
		begin
			/* 18695, "The query plans are the same." */
			exec sp_getmessage 18695, @msg out
		end
		else if @plan = 10
		begin
			/* 18696, "The query plans are different." */
			exec sp_getmessage 18696, @msg out
		end
			/* else wrong @plan - do nothing */

		print @msg

	end
	else if @mode != "quiet"
	begin
		/* 18640, "Unknown %1! option : '%2!'. Valid options are : %3!." */
		raiserror 18640, "sp_cmp_qplans", @mode, "'quiet', 'brief'"
	end

	/*
	** 0 - same query/plan
	** +1 - different queries
	** +2 - different queries and hash collision
	** +10 - different plans
	** 100 - plan ID does not exist
	*/
	return @query + @plan

go
go
exec sp_procxmode 'sp_cmp_qplans', 'anymode'
go
grant execute on sp_cmp_qplans to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_copy_qplan')
begin
	drop procedure sp_copy_qplan
end
go
print "Installing sp_copy_qplan"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_copy_qplan"
**
** 18639, "There is no query plans group named '%1!' in this database."
** 18636, "There is no query plan with the ID %1! in this database."
** 18652, "The new query plan would give an association key collision in group '%1!', with the existing query plan %1!."
** 18653, "The new query plan already exists in group '%1!', under the ID %1!."
** 18667, "The new query plan will give a hash collision with the existing query plan %1!, but the copy will be made."
** 18654, "Obtained the unexpected plan comparison return code %1!, when comparing with the query plan %2!. Please contact Sybase Technical Support."
** 18655, "Failed to copy the new query plan."
*/
 
/*
** sp_copy_qplan copies a given AP in a given AP group. The new ID is 
** obtained by a dummy CREATE PLAN "" "". Then the rows are copied 
** as such (but with the new GID and ID). The old hashkey is reused, 
** as it goes with the old association (i.e. query text rows).
** Note, no learning AP(s) or metrics are copied.
*/

create procedure sp_copy_qplan
@src_id		int,
@dest_group	varchar(30)
as
	declare
		@uid		int,
		@src_uid	int,
		@hashkey	int,
		@new_id		int, 
		@dest_gid	int, 
		@coll_id	int,
		@ret		int,
		@rows		int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	exec sp_aux_get_qpgroup @dest_group, @dest_gid out

	if @dest_gid is null
	begin
		/* 18639, "There is no query plans group named '%1!' in this database." */
		raiserror 18639, @dest_group

		rollback tran
		return 1
	end

	/*
	** Search an AP with the same association 
	** key as @src_id in group @dest_gid. 
	*/

	select distinct 
			@src_uid = uid, 
			@hashkey = hashkey
		from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and id = @src_id
			and type = 100

	if @hashkey is null
	begin
		/* 18636, "There is no query plan with the ID %1! in this database." */
		raiserror 18636, @src_id

		return 2
	end

	/* get the collision candidates */
	select distinct id
		into #t
		from sysqueryplans
		where 
			uid = @src_uid
			and gid = @dest_gid
			and hashkey = @hashkey

	declare collide cursor
	for
	select id
		from #t

	open collide
	fetch collide into @coll_id

	while @@sqlstatus = 0
	begin
		/* compare with each collision candidate */
		exec @ret = sp_cmp_qplans @coll_id, @src_id

		if @ret = 10
		begin
			/* 18652, "The new query plan would give an association key collision in group '%1!', with the existing query plan %2!." */
			raiserror 18652, @dest_group, @coll_id

			return 3
		end

		if @ret = 0
		begin
			/* 18653, "The new query plan already exists in group '%1!', under the ID %2!." */
			raiserror 18653, @dest_group, @coll_id

			return 4
		end

		if @ret = 2 or @ret = 12
			/* 18667, "The new query plan will give a hash collision with the existing query plan %1!, but the copy will be made." */
			raiserror 18667, @coll_id
		else
			/* 18654, "Obtained the unexpected plan comparison return code %1!, when comparing with the query plan %2!. Please contact Sybase Technical Support." */
			raiserror 18654, @ret, @coll_id

		fetch collide into @coll_id
	end

	create plan "select 1" "()" into @dest_group and set @new_id 
	delete sysqueryplans
		where id = @new_id

	insert sysqueryplans
		select @src_uid, @dest_gid, 
				@hashkey, @new_id, 
				type, sequence, status, text,
				dbid, qpdate, sprocid, hashkey2,
				key1, key2, key3, key4
			from sysqueryplans
			where id = @src_id
			and type <= 100

	select @rows = @@rowcount

	if @rows = 0
	begin
		/* 18655, "Failed to copy the new query plan." */
		raiserror 18655

		return 5
	end

	return 0
go

go
exec sp_procxmode 'sp_copy_qplan', 'anymode'
go
grant execute on sp_copy_qplan to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_copy_all_qplans')
begin
	drop procedure sp_copy_all_qplans
end
go
print "Installing sp_copy_all_qplans"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_copy_all_qplans"
**
** 18639, "There is no query plans group named '%1!' in this database."
** 18656, "Unrecoverable error while copying the query plan %1!. Keeping all plans copied so far and interrupting the copy."
** 18657, "Recoverable error while copying the query plan %1!. Skipping this plan and continuing the copy."
** 18658, "Error while fetching the next query plan to copy. Keeping all plans copied so far and interrupting the copy."
*/
 
/*
** sp_copy_all_qplans copies all plans in a source group to 
** a destination group. As there could be many of them, rather 
** than having an ACID behavior, the SP attempts to do as much 
** as possible. 
** Note, no learning APs are copied.
*/

create procedure sp_copy_all_qplans
@src_group	varchar(30),
@dest_group	varchar(30)
as
	declare
		@uid		int,
		@src_gid	int,
		@src_id		int, 
		@ret		int,
		@rows		int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	exec sp_aux_get_qpgroup @src_group, @src_gid out

	if @src_gid is null 
	begin
		/* 18639, "There is no query plans group named '%1!' in this database." */
		raiserror 18639, @src_group

		return 1
	end

	/* cursor to scroll through the source APs */
	declare src_ids cursor 
	for 
	select distinct id
		from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and gid = @src_gid
			and type = 100

	open src_ids
	fetch src_ids into @src_id

	while @@sqlstatus = 0
	begin
		/* insert each source AP in the destination group */
		exec @ret = sp_copy_qplan @src_id, @dest_group

		/*
		** @ret == 1 meant no destination group. 
		** When there's an @@error, probably we can't 
		** go on...
		*/
		if @ret = 1 or @@error != 0 
		begin
			/* 18656, "Unrecoverable error while copying the query plan %1!. Keeping all plans copied so far and interrupting the copy." */
			raiserror 18656, @src_id

			return 1
		end

		/*
		** This plan is illegal (key collision, etc)
		** but try to continue. 
		*/
		if @ret != 0 
		begin
			/* 18657, "Recoverable error while copying the query plan %1!. Skipping this plan and continuing the copy." */
			raiserror 18657, @src_id
		end

		fetch src_ids into @src_id
	end

	select @rows = @@rowcount

	if @@sqlstatus = 1
	begin
		/* 18658, "Error while fetching the next query plan to copy. Keeping all plans copied so far and interrupting the copy." */
		raiserror 18658

		return 1
	end

	return 0
go

go
exec sp_procxmode 'sp_copy_all_qplans', 'anymode'
go
grant execute on sp_copy_all_qplans to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_all_qplans')
begin
	drop procedure sp_drop_all_qplans
end
go
print "Installing sp_drop_all_qplans"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_drop_all_qplans"
**
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18639, "There is no query plans group named '%1!' in this database."
*/
 
/*
** sp_drop_all_qplans deletes all APs in a given group. 
** Straightforward SYSQUERYPLANS delete by GID. 
** Note, learning APs should NOT be deleted by this SP.
*/

create procedure sp_drop_all_qplans
@name	varchar(255)
as
	declare
		@uid	int,
		@gid	int,
		@dbname char(255)

	set nocount on

	select @dbname = db_name()

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	exec sp_aux_get_qpgroup @name, @gid out

	if @gid is null
	begin
		/* 18639, "There is no query plans group named '%1!' in this database." */
		raiserror 18639, @name
		return 1
	end

	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

		delete from sysqueryplans
			where 
				uid = isnull(@uid, uid)
				and gid = @gid
				and type <= 100
				and ((type != 10) or
				     (id not in
					(select id from sysqueryplans 
					 where type > 100 and type < 1000
					 group by id)))
		
		/*
		** Write the log record to replicate this invocation
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**          because there was an error in writing
			**          the replication log record."
			*/
			raiserror 17756, "sp_drop_all_qplans", @dbname
			rollback transaction rs_logexec
			return(1)
		end
	commit transaction rs_logexec
	return 0
go
exec sp_procxmode 'sp_drop_all_qplans', 'anymode'
go
grant execute on sp_drop_all_qplans to public
go
exec sp_procxmode 'sp_drop_all_qplans', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_set_qplan')
begin
	drop procedure sp_set_qplan
end
go
print "Installing sp_set_qplan"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_set_qplan"
**
** 18636, "There is no query plan with the ID %1! in this database."
** 18637, "Failed to drop the old query plan with ID %1!, rolling back and aborting."
** 18638, "Failed to set the new query plan with ID %1!, rolling back and aborting."
*/
 
/*
** sp_set_qplan sets a new AP for a given ID, i.e. existing 
** <association key, AP> pair, where the association key is 
** the query SQL text and is unchanged. Note that it's important 
** not to touch the SQL text, as it's hashed to obtain the 
** HASHKEY column in SYSQUERYPLANS. Hence, the association part 
** of a plan can only be installed through the SQL command 
** CREATE PLAN, that also handles hashing. Failing to observe 
** these rules would result in plans that are not found at lookup.
*/

create procedure sp_set_qplan
@id	int,
@plan	varchar(255)
as
	declare	@uid	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	begin tran

	/* check the existence of the destination plan, level 3 shared lock */
	/* 
	** Also force the index to use for the scan because the
	** index on id is always the better one here and needs
	** much less lcoks to hold. Optimizer does not always
	** pick the index automatically without more accurate
	** stats on sysqueryplans.
	*/
	if not exists (select * 
			from sysqueryplans (index ncsysqueryplans) holdlock
			where
				uid = isnull(@uid, uid)
				and id = @id)
	begin
		/* 18636, "There is no query plan with the ID %1! in this database."*/
		raiserror 18636, @id

		rollback tran
		return 1
	end

	/*
	** Delete the old AP (i.e. the type == 100) rows of the plan. 
	** Keep the first one (i.e. sequence == 0), see below the 
	** update.
	*/
	delete from sysqueryplans
		where 
			uid = isnull(@uid, uid)
			and id = @id
			and type = 100
			and sequence > 0

	if @@error != 0
	begin
		/* 18637, "Failed to drop the old query plan with ID %1!, rolling back and aborting." */
		raiserror 18637, @id

		rollback tran
		return 2
	end

	/*
	** As the @plan parameter is varchar(255) (we don't really have 
	** the choice in TSQL, we're sure that it will fit on one row. 
	** So we'll reuse the first one, that we didn't delete above, 
	** rather than having deleted them all and inserting here a new 
	** row. It might be interesting later, when LOBs become first 
	** class types, to do better...
	*/
	update sysqueryplans
		set text = @plan
		where
			uid = isnull(@uid, uid)
			and id = @id
			and type = 100
			and sequence = 0

	if @@error != 0
	begin
		/* 18638, "Failed to set the new query plan with ID %1!, rolling back and aborting." */
		raiserror 18638, @id

		rollback tran
		return 3
	end

	/* success */
	commit tran
	return 0
go

go
exec sp_procxmode 'sp_set_qplan', 'anymode'
go
grant execute on sp_set_qplan to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_cmp_all_qplans')
begin
	drop procedure sp_cmp_all_qplans
end
go
print "Installing sp_cmp_all_qplans"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
 
/*
** Messages for "sp_cmp_all_qplans"
**
** 18639, "There is no query plans group named '%1!' in this database."
** 18661, "If the two query plans groups are large, this might take some time."
** 18666, "Temporary table fetch error. If there are no other error messages and this error persists, please contact Sybase Technical Support."
** 18662, "Query plans that are the same"
** 18663, "Different query plans that have the same association key"
** 18664, "Query plans present only in group '%1!'"
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
*/
 
/*
** sp_cmp_all_qplans is a AP group comparison assistant. 
**
** Valid modes are : 
**	- "counts"	- print only the counts per category;
**	- "brief"	- also print the IDs per category, except 
**			for "same";
**	- "same"	- "counts" + IDs + APs that are the same;
**	- "diff"	- "counts" + IDs + APs that are different;
**	- "first"	- "counts" + IDs + APs that are only in 
**			the first group;
**	- "second"	- "counts" + IDs + APs that are only in 
**			the second group;
**	- "offending"	- "diff" + "first" + "second";
**	- "full"	- "same" + "offending".
**
** The comparison is based on pairs of plans, one from each group, 
** that have the same association key (UID + query text). (Note 
** that the GID is also part of the association key, but it's set 
** by the first 2 parameters.) Plans that cannot be matched in 
** pairs on the association key will be considered as being part 
** of only one group. Plans that are matched, are further compared 
** on the AP texts, to check whether they are the same or different. 
** Note, no learning AP should be considered in comparisons.
**
** Processing is done as follows : 
**	- we accumulate in #common, the APs in the 2 groups that 
**	have at least some corresponding rows of text in common;
**	- we accumulate in #similar pairs of APs from #common 
**	that have, per type, the same number of rows as the common 
**	rows and match at least on the query text;
**	- we put in #same the pairs from #similar that matched 
**	both the query text and on the AP text;
**	- we put in #diff the pairs that have in #similar only 
**	the query text, but not also the AP;
**	- #first and #second are basic set differences between 
**	the relevant part of sysqueryplans and the part of 
**	#similar that contains query text.
*/

create procedure sp_cmp_all_qplans
@group1		varchar(30),
@group2		varchar(30),
@mode		varchar(20) = "counts"
as
	declare
		@msg		varchar(1024),
		@uid		int,
		@gid1		int,
		@gid2		int,
		@id1		int,
		@id2		int

	set flushmessage on
	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1


	select @uid = nullif(user_id(), 1)

	exec sp_aux_get_qpgroup @group1, @gid1 out
	exec sp_aux_get_qpgroup @group2, @gid2 out

	if @gid1 is null
		raiserror 18639, @group1

	if @gid2 is null
		raiserror 18639, @group2

	if @gid1 is null or @gid2 is null
		return 3

	/*
	** Work silently for a while, preparing intermediate results.
	** But warn the audience...
	*/

	/* 18661, "If the two query plans groups are large, this might take some time." */
	exec sp_getmessage 18661, @msg out
	print @msg


	select g1.id as id1, g2.id as id2, g1.type as type, count(*) as cnt
		into #common
		from sysqueryplans g1, sysqueryplans g2
		where
			g1.uid = g2.uid
			and g1.uid = isnull(@uid, g1.uid)
			and g2.uid = isnull(@uid, g2.uid)

			and g1.gid = @gid1
			and g2.gid = @gid2

			and g1.hashkey = g2.hashkey
			and g1.type = g2.type
			and g1.type <= 100
			and g1.sequence = g2.sequence
			and isnull(rtrim(g1.text), " ") = isnull(rtrim(g2.text), " ")
		group by g1.id, g2.id, g1.type
		having count(*) > 0

	select id1, id2, sum(type) as type
		into #similar
		from #common
		where
			cnt = (select count(*)
				from sysqueryplans
				where
					id = #common.id1
					and type = #common.type)
			and
			cnt = (select count(*)
				from sysqueryplans
				where
					id = #common.id2
					and type = #common.type)
		group by id1, id2
		having sum(type) in (10, 110)

	/* for the per type searches */
	create clustered index ci_type on #similar(type)

	/* for the NOT IN */
	create index nci_id1 on #similar(id1)
	create index nci_id2 on #similar(id2)


	/*
	** Done with the computing, let's get out the conclusions.
	*/

	/*
	** Same APs
	*/

	select id1, id2
		into #same
		from #similar
		where type = 110

	/* 18662, "Query plans that are the same" */
	exec sp_getmessage 18662, @msg out
	print @msg

	select count(*) as "count"
		from #same

	/* Don't print the zillion of same APs, except if explicitly requested */

	if @mode in ("same", "full")
	begin
		/* print the same AP pairs of IDs */

		print ""
		print "	%1!    %2!", @group1, @group2

		select id1, id2
			from #same

		/* cursor to print each pair of same APs */

		print ""
		declare same cursor
		for
		select id1, id2
			from #same

		open same
		fetch same into @id1, @id2

		while @@sqlstatus = 0
		begin
			exec sp_help_qplan @id1, full
			exec sp_help_qplan @id2, full

			print "================================================"
			fetch same into @id1, @id2
		end

		if @@sqlstatus = 1
		begin
			/* 18666, "Temporary table fetch error. If there are no other error messages and this error persists, please contact Sybase Technical Support." */
			raiserror 18666

			return 1
		end

	end
	
	/*
	** Different APs
	*/

	select id1, id2
		into #diff
		from #similar
		where type = 10


	/* 18663, "Different query plans that have the same association key" */
	exec sp_getmessage 18663, @msg out
	print @msg

	select count(*) as "count"
		from #diff

	/* print the different AP pairs of IDs */
	if @mode in ("brief", "diff", "offending", "full")
	begin
		print ""
		print "	%1!    %2!", @group1, @group2

		select id1, id2
			from #diff
	end

	/* cursor to print the different APs */
	if @mode in ("diff", "offending", "full")
	begin
		print ""
		declare diff cursor
		for
		select id1, id2
			from #diff

		open diff
		fetch diff into @id1, @id2

		while @@sqlstatus = 0
		begin
			exec sp_help_qplan @id1, full
			exec sp_help_qplan @id2, full

			print "================================================"
			fetch diff into @id1, @id2
		end

		if @@sqlstatus = 1
		begin
			/* 18666, "Temporary table fetch error. If there are no other error messages and this error persists, please contact Sybase Technical Support." */
			raiserror 18666

			return 1
		end
	end


	/*
	** APs that are only in the first group
	*/

	select distinct id
		into #first
		from sysqueryplans
		where
			id not in (select id1 from #similar)
			and gid = @gid1
			and uid = isnull(@uid, uid)
			and type = 100

	/* 18664, "Query plans present only in group '%1!'" */
	exec sp_getmessage 18664, @msg out
	print @msg, @group1

	select count(*) as "count"
		from #first

	if @mode in ("brief", "first", "offending", "full")
	begin
		print ""
		select id
			from #first
	end

	if @mode in ("first", "offending", "full")
	begin
		print ""
		declare first_c cursor
		for
		select id
			from #first

		open first_c
		fetch first_c into @id1

		while @@sqlstatus = 0
		begin
			exec sp_help_qplan @id1, full

			print "================================================"
			fetch first_c into @id1
		end

		if @@sqlstatus = 1
		begin
			/* 18666, "Temporary table fetch error. If there are no other error messages and this error persists, please contact Sybase Technical Support." */
			raiserror 18666

			return 1
		end
	end

	/*
	** Aps that are only in the second group
	*/

	select distinct id
		into #second
		from sysqueryplans
		where
			id not in (select id2 from #similar)
			and gid = @gid2
			and uid = isnull(@uid, uid)
			and type = 100

	/* 18664, "Query plans present only in group '%1!'" */
	/* @msg contains this message, no need to fetch it again */
	/* exec sp_getmessage 18664, @msg out */
	print @msg, @group2

	select count(*) as "count"
		from #second

	if @mode in ("brief", "second", "offending", "full")
	begin
		print ""
		select id
			from #second
	end

	if @mode in ("second", "offending", "full")
	begin
		print ""
		declare second cursor
		for
		select id
			from #second

		open second
		fetch second into @id2

		while @@sqlstatus = 0
		begin
			exec sp_help_qplan @id2, full

			print "================================================"
			fetch second into @id2
		end

		if @@sqlstatus = 1
		begin
			/* 18666, "Temporary table fetch error. If there are no other error messages and this error persists, please contact Sybase Technical Support." */
			raiserror 18666

			return 1
		end
	end

	if @mode not in 
		("counts", "brief", "same", "diff", 
		 "first", "second", "offending", "full"
		)
	begin
		/* 18640, "Unknown %1! option : '%2!'. Valid options are : %3!." */
		raiserror 18640, "sp_cmp_all_qplans", @mode, 
			"'counts', 'brief', 'same', 'diff', 'first', 'second', 'offending', 'full'"

		return 2
	end

	return 0
go

go
exec sp_procxmode 'sp_cmp_all_qplans', 'anymode'
go
grant execute on sp_cmp_all_qplans to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropremotelogin')
begin
	drop procedure sp_dropremotelogin
end
go
print "Installing sp_dropremotelogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_dropremotelogin"    17512
**
** 17260, "Can't run %1! from within a transaction." 
** 17512, "Remote login dropped."
** 17513, "There is no remote user '%1!' mapped to local user '%2!' from the remote server '%3!'."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18780, "Synchronization will not occur because server '%1!' is the companion server."
** 18782, "Unable to find a server with name '%1!' and id '%2!'."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_dropremotelogin
@remoteserver	varchar(255),		/* name of remote server */
@loginame varchar(255) = NULL,		/* user's remote name */
@remotename varchar(255) = NULL		/* user's local user name */
as

declare	@msg	varchar(1024)
declare @suid	int
declare @rname  varchar(255)
declare @lname  varchar(255)
declare @rtn_code int
declare @rowcount_save int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @dummy  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_dropremotelogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_dropremotelogin"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role or sso_role,proc_role also generates an 
** audit record and prints an error message for sa role if both sa role 
** and sso role are not present.
*/


if ( (charindex("sa_role", show_role()) = 0) AND (charindex("sso_role", show_role()) = 0) ) 
begin
	select @dummy = proc_role("sa_role") /* to perform auditing if sa_role fails */
        raiserror 17888, "dropremotelogin"
	return (1)
end


/*
**  If @loginame is NULL then we want to set @suid = -1. Otherwise get
**  it real value.
*/
if @loginame is null
	select @suid = -1
else select @suid = suser_id(@loginame)



/*
**  Delete the remote login.
*/

delete master.dbo.sysremotelogins
	from master.dbo.sysremotelogins l, master.dbo.sysservers s
	where l.remoteserverid = s.srvid
		and s.srvname = @remoteserver
		and l.remoteusername = @remotename
		and l.suid = @suid

/*
** Check @@rowcount when it works
*/
select @rowcount_save = @@rowcount

if (@rowcount_save > 0)
	select @rtn_code = 0
else
	select @rtn_code = 1



if (@rtn_code = 0)
begin
	/*
	** 17512, "Remote login dropped."
	*/
	exec sp_getmessage 17512, @msg output
	print @msg
	return (0)
end
else
begin
	/*
	** 17513, "There is no remote user '%1!' mapped to local user '%2!' from the remote server '%3!'."
	*/
	select @rname = isnull(@remotename, "NULL")
	select @lname = isnull(@loginame, "NULL")
	raiserror 17513, @rname, @lname, @remoteserver

	goto clean_all
end

return (0)

clean_all:

        return (1)

go
exec sp_procxmode 'sp_dropremotelogin', 'anymode'
go
grant execute on sp_dropremotelogin to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropsegment')
begin
	drop procedure sp_dropsegment
end
go
print "Installing sp_dropsegment"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */

/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_dropsegment"        17520
**
** 17260, "Can't run %1! from within a transaction."
** 17281, "The specified device is not used by the database."
** 17520, "There is no such segment as '%1!'."
** 17521, "Can't drop the '%1!'segment completely."
** 17522, "The segment '%1!' is being used."
** 17523, "Segment '%1!' does not reference device '%2!'."
** 17524, "There is only one device mapping for the segment '%1!' -- use sp_dropsegment with no device argument."
** 17525, "Segment dropped."
** 17526, "Segment reference to device dropped."
** 17527, "WARNING: There are no longer any segments referencing device '%1!'.  This device will no longer be used for space allocation."
** 17528, "WARNING: There are no longer any segments referencing devices '%1!'.  These devices will no longer be used for space allocation."
** 17590, "The specified database does not exist." 
** 17715, "The last-chance threshold for database %1! is now %2! pages."
** 17716, "Could not update the last-chance threshold for database %1!"
** 17288, "You must execute this procedure from the database 
** 	  in which you wish to %1! a segment.  Please execute 
**	  'use %2!' and try again."
** 17289, "Set your curwrite to the hurdle of current database."
*/

create procedure sp_dropsegment
@segname	varchar(255),		/* segment name */
@dbname		varchar(255),	/* database name */
@device		varchar(255) = null	/* device name */
as

declare @dbuid	int	/* id of the owner of the database */
declare @dbid	smallint	/* id of the database */
declare @segbit	int		/* this is the bit to turn on in sysusages */
declare @segnum	int		/* this is the segment number*/
declare @lct	int		/* log's last-chance threshold setting */
declare	@msg	varchar(1024)
declare	@procval int
declare @bitdesc varchar(30)	/* bit description for the db */
declare @tempdb_mask	int	/* All database status bit for a tempdb */
declare @isatempdb	int	/* Is this a temp. db ? */
declare	@isamaster	int

select @procval = 0


/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_dropsegment"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/

if (user_id() = 1)
begin
	/* If user has sa role audit this as a successful sa 
	** command execution.
	*/ 
	if charindex("sa_role",show_role()) > 0
		select @procval = proc_role("sa_role") 
end
else 
begin
	/* user_id() is not DBO hence user does not have SA role
	** audit this as a failed sa command execution.
	*/
	select @procval = proc_role("sa_role")  
	return (1)
end

/*
**  There are two drop cases:
**	1) dropping the segment
**	2) dropping a segment reference to a device
**  The sproc does things differently depending on which we're doing.
*/

/*
**  Make ure the database exists
*/
if not exists ( select * from master.dbo.sysdatabases
		where name = @dbname )
begin
	/* 17590, "The specified database does not exist." */
	raiserror 17590
	return (1)
end

/*
**  Make sure that we are in the database specified
**  by @dbname. 
*/
if @dbname != db_name()
begin
	/* 
	** 13232, "drop"
	** 17288, "You must execute this procedure from the database 
	** 	  in which you wish to %1! a segment.  Please execute 
	**	  'use %2!' and try again."
	*/
	declare @action varchar(30)
	select @action = description
	from master.dbo.sysmessages
	where error = 13232 and langid = @@langid
	if @action is null
		select @action = description
		from master.dbo.sysmessages
		where error = 13232 and langid is null
	if @action is null select @action = "drop"
	raiserror 17288, @action, @dbname
	return (1)
end

select @dbid = db_id(@dbname)

/*
** Determine if we are dealing with a temporary database.
*/
select @tempdb_mask = number
	from master.dbo.spt_values
	where type = "D3" and name = "TEMPDB STATUS MASK"

if (@dbid = 2) or exists (select * from master.dbo.sysdatabases
	     	            where dbid = @dbid
	     	            and (status3 & @tempdb_mask) != 0) 
begin
	select @isatempdb = 1
end
else
begin
	select @isatempdb = 0
end

select @isamaster = 0
if (   (@dbid = db_id("master"))
    or (@dbid = db_id("master_companion")))
begin
	select @isamaster = 1
end

/*
**  Check to see if the segment exists.
*/
if not exists (select *
		from syssegments
			where name = @segname)
begin
	/*
	** 17520, "There is no such segment as '%1!'."
	*/
	raiserror 17520, @segname
	return (1)
end

/*
**  Get the segment number of @segname.
*/
select @segbit = segment
	from syssegments 
		where name = @segname

select @segnum = @segbit

/*
**  Now convert the segment number to the right bit for segmap.
*/
if (@segbit < 31)
	select @segbit = power(2, @segbit)
else
	/*
	**  Since this is segment 31, power(2, 31) will overflow
	**  since segmap is an int.  We'll grab the machine-dependent
	**  bit mask from spt_values to clear the right bit.
	*/
	select @segbit = low
		from master.dbo.spt_values
			where type = "E"
				and number = 2

/*
**  Don't allow the segments 'default', 'system', or 'logsegment' to
**  be dropped completely.
*/
if @segname in ("system", "default", "logsegment")
begin
	if @device is null
	begin
		/*
		** 17521, "Can't drop the '%1!'segment completely."
		*/
		raiserror 17521, @segname
		return (1)
	end

	/*
	**  For the case where we are dropping the logsegment from a 
	**  device, the logic below works OK.  If this is the last
	**  device for the the segment, it won't let the segment be
	**  dropped.
	*/
end

/* If we are removing log space and this is not a temporary database ... */ 
if @segbit = 4 and @isatempdb = 0
begin
	/* 
	** ... check single user bit (4096).
	** The database must be in single user mode so that no log allocation
	** or deallocation take place while looking for possibly stranded 
	** objects, and while recalculating the free space counter.
	*/ 
	select @bitdesc = null 
	select @bitdesc = v.name
		from master.dbo.spt_values v, master.dbo.sysdatabases d 
			where d.dbid = @dbid
				and v.type = "D" 
				and d.status & v.number = 4096 
	if @bitdesc is null 
	begin 
		/*
		** 17793, "System Administrator (SA) must set database '%1!' to single-user mode with sp_dboption before using '%2!'."
		*/
		raiserror 17793, @dbname, "sp_dropsegment"
		return(1)  
	end  
end

/*
**  If we are dropping the segment, check to see that the segment isn't
**  being used by anyone.
*/
if @device is null
begin

	/*
	**  Check to see if the segment is being used.
	*/
	if exists (select *
			from sysindexes i, syssegments s, syspartitions p
				where s.name = @segname
					and (i.segment = s.segment or
					     p.segment = s.segment))
	begin
		/*
		** 17522, "The segment '%1!' is being used."
		*/
		raiserror 17522, @segname
		return (1)
	end
end

/*
**  If we are dropping the segment reference, check to see that arguments are
**  reasonable.
*/
if @device is not  null
begin
	/*
	**  Now see if the database even uses the @device
	*/
	if not exists (select *
			from master.dbo.sysusages u, master.dbo.sysdevices d
				where d.name = @device
					and u.vdevno = d.vdevno
					and u.dbid = @dbid)
	begin
		/*
		** 17281, "The specified device is not used by the database."
		*/
		raiserror 17281



		return (1)
	end

	/*
	**  Now check that the segment references the device.
	*/
	if not exists (select *
			from master.dbo.sysusages u, master.dbo.sysdevices d
				where u.segmap & @segbit = @segbit
				and d.name = @device
				and u.vdevno = d.vdevno
				and u.dbid = @dbid
				and ((d.status & 2 = 2) or (d.status2 & 8 = 8)))
	begin
		/*
		** 17523, "Segment '%1!' does not reference device '%2!'."
		*/
		raiserror 17523, @segname, @device
		return (1)
	end

	/*
        **  Now check to see if this is the last unique device reference for the
	**  segment.  If it is then we don't want to drop the reference.
	*/
        select distinct d.name into #temptable
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where u.segmap & @segbit = @segbit
				and u.vdevno = d.vdevno
				and u.dbid = @dbid
                                and ((d.status & 2 = 2) or (d.status2 & 8 =8))

        if (select count(*) from #temptable) <= 1
	begin
		/*
		** 17524, "There is only one device mapping for the segment '%1!' -- use sp_dropsegment with no device argument."
		*/
		raiserror 17524, @segname
		return (1)
	end

        drop table #temptable
end

/*
**  If we're dropping the segment, go ahead drop the segment and
**  clear its bit in sysusages.
*/
if @device is null
begin


	/*
	**  Remove any threshold references
	*/
	if exists (select * from sysobjects where name = "systhresholds")
		delete systhresholds
		from systhresholds t, syssegments s
		where	s.name = @segname
		  and	s.segment = t.segment

	/*
	**  NOTE: Don't update master.dbo.sysusages and syssegments as a xact 
	**  	since it could cause problems for recovery.
	*/



	delete syssegments
		where name = @segname



	/* Encapsulate sysusages/anchors update in a transaction */
	if (@isamaster = 1)
		begin transaction sysusg_upd

	/*
	**  Now clear the segment from device in sysusages.
	*/
	update master.dbo.sysusages
		set segmap = segmap & (~@segbit)
			from master.dbo.sysusages u, master.dbo.sysdevices d
				where u.vdevno = d.vdevno
					and u.dbid = @dbid
					and ((d.status & 2 = 2)
						or (d.status2 & 8 = 8))
end

/*
**  We want to just clear the segment reference from the device.
*/
else
begin


	/* Encapsulate sysusages/anchors update in a transaction */
	if (@isamaster = 1)
		begin transaction sysusg_upd

	update master.dbo.sysusages
		set segmap = segmap & (~@segbit)
			from master.dbo.sysusages u, master.dbo.sysdevices d
				where u.vdevno = d.vdevno
					and u.dbid = @dbid
					and ((d.status & 2 = 2) 
						or (d.status2 & 8 = 8))
					and d.name = @device

	/*
	**  Remove any threshold references that exceed the remaining
	**  size of the segment
	*/
	if exists (select * from sysobjects where name = "systhresholds")
		delete systhresholds
		from systhresholds t, syssegments s
		where	s.name = @segname
		  and	s.segment = t.segment
		  and	t.free_space >= (select sum(size)
					 from master.dbo.sysusages
					 where dbid = @dbid
					   and segmap & @segbit = @segbit)
end

if (@isamaster = 1)
begin
	if (@@error != 0)
	begin
		rollback tran sysusg_upd
		return (1)
	end

	dbcc dbrepair(@dbname, "upd_usg")
	if (@@error != 0)
	begin
		rollback tran sysusg_upd
		return (1)
	end

	commit transaction sysusg_upd
end

/*
**  Now we need to activate the new segment map.
*/
dbcc dbrepair (@dbname, remap, NULL, @segnum, @segname)

/*
** By removing a piece of the log segment, we may have cleared a stranded
** object condition, so we need to look for stranded objects.  We can also 
** take this opportunity to recalculate the log's last-chance threshold.
*/
if @segbit = 4
begin
	dbcc dbrepair (@dbname, findstranded, NULL, @isatempdb)
	select @lct = lct_admin("lastchance", @dbid)
	if @lct > 0
		exec sp_getmessage 17715, @msg out
	else
		exec sp_getmessage 17716, @msg out

	print @msg, @dbname, @lct
end

if @device is null
begin
	/*
	** 17525, "Segment dropped."
	*/
	exec sp_getmessage 17525, @msg output
	print @msg
end
else 
begin
	/*
	** 17526, "Segment reference to device dropped."
	*/
	exec sp_getmessage 17526, @msg output
	print @msg
end

/*
**  If there are no more segment references to the device,
**  print a warning.
*/
if exists (select *
		from master.dbo.sysusages
			where segmap = 0
				and dbid = @dbid)
begin
	declare @nosegs	varchar(255),	/* list of unreferenced devices */
		@curdevice	varchar(30),
		@i	int
	
	select @curdevice = min(d.name)
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where u.vdevno = d.vdevno
				and u.dbid = @dbid
				and ((d.status & 2 = 2) or (d.status2 & 8 = 8))
				and segmap = 0
	select @nosegs = @curdevice, @i = 1
	while (@curdevice is not  null)
	begin
		select @curdevice = min(d.name)
			from master.dbo.sysusages u, master.dbo.sysdevices d
				where u.vdevno = d.vdevno
					and u.dbid = @dbid
					and ((d.status & 2 = 2) 
						or (d.status2 & 8 = 8))
					and segmap = 0
					and d.name > @curdevice
		if @curdevice is not  null
		begin
			select @nosegs = @nosegs + ", " + @curdevice
			select @i = @i + 1
		end
	end

	/*
	**  Get the device names.
	*/
	if @i > 1
		/*
		** 17528, "WARNING: There are no longer any segments referencing devices '%1!'.  These devices will no longer be used for space allocation."
		*/
		exec sp_getmessage 17528, @msg output
	else 
		/*
		** 17527, "WARNING: There are no longer any segments referencing device '%1!'.  This device will no longer be used for space allocation."
		*/
		exec sp_getmessage 17527, @msg output
	print @msg, @nosegs
end
return (0)
go
exec sp_procxmode 'sp_dropsegment', 'anymode'
go
grant execute on sp_dropsegment to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropserver')
begin
	drop procedure sp_dropserver
end
go
print "Installing sp_dropserver"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
** Messages for "sp_dropserver"         17530
**
** 17260, "Can't run %1! from within a transaction." 
** 17270, "There is not a server named '%1!'."
** 17530, "There are still remote logins for the server '%1!'."
** 17531, "Remote logins for remote server '%1!' have been dropped."
** 17532, "Usage: sp_dropserver server [, droplogins]"
** 17533, "Server dropped."
** 17534, "There are still external logins for the server '%1!'."
** 17535, "External logins for remote server '%1!' have been dropped."
** 17536, "Unable to drop server '%1!' because it is referenced in master.dbo.sysdatabases."
** 17537, "Unable to drop server '%1!' because it is referenced by 
**	   transaction coordinator."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'."
** 18782, "Unable to find a server with name '%1!' and id '%2!'."
** 18783, "You cannot drop the companion server '%1!' in the companion mode because it is configured as a node of HA cluster."
** 18785, "Unable to drop the local server '%1!' because it is in HA companion mode."
** 19660, "Unable to drop server '%1!' because it stores information of existing cluster instance '%2!'."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_dropserver
@server	varchar(255),			/* server name */
@droplogins	char(10) = NULL		/* drop all related logins? */
as

declare	@msg	varchar(1024),
	@srvid	smallint,
	@retstat int

declare	@srvclass smallint	/* Class id of the server */
declare	@command varchar(30)	/* Command passed to sp_extengine */
declare	@physname varchar(255)	/* Class name of the external engine class */
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @inst_id int		/* Cluster instance id */
declare @status2 unsigned int	/* To store 'srvstatus2' column value */
declare @insysattributes int    /* Is the rtds provider in sysattributes ? */
declare	@outstr	varchar(255),	/* for SDC dbcc set_scope */
	@scope	varchar(16)	/* for SDC dbcc set_scope */

select @HA_CERTIFIED = 0
select @insysattributes = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_dropserver', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_dropserver"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sso_role") = 0)
	return (1)

/*
**  Check to see if the server exists.
*/
if not exists (select * from master.dbo.sysservers
			where srvname = @server)
begin
	/*
	** 17270, "There is not a server named '%1!'."
	*/
	raiserror 17270, @server
	return (1)
end

/*
** Check to see if this is a rtds provider which
** is registered in sysattributes.
*/
select @srvclass = srvclass from master.dbo.sysservers
	where srvname = @server
if (@srvclass in (12,13,14,15))
	and (exists (select 1 from master.dbo.sysattributes
			where class = 21 and attribute = 10
				and object_type = 'PR'
				and object_cinfo = @server))
        select @insysattributes = 1
else
        select @insysattributes = 0


/*
** Check to see if server stores cluster instance information 
*/
select @status2=srvstatus2 from master.dbo.sysservers where srvname=@server
if ((@status2 & 4) != 0)
begin
	select @inst_id=instance_id(@server)
	if @inst_id is not NULL
	begin
		/*
		** 19660, "Unable to drop server '%1!' 
		** because it stores information of 
		** existing cluster instance '%2!'."
		*/
		raiserror 19660, @server, @inst_id
		return (1)
	end
end

/*
** OMNI: check to see if there is a default location referenced in sysdatabases
*/
if exists (select * from master.dbo.sysdatabases where
		substring(def_remote_loc, 1, 
			  charindex('.', def_remote_loc) - 1) = @server)
begin
	/*
	** 17536, "Unable to drop server '%1!' because it is referenced 
	** in master.dbo.sysdatabases."
	*/
	raiserror 17536, @server
	return (1)
end



/* Start a transaction */
begin transaction dropserver

/* 
** Do more consistency checks to ensure that transaction coordinator
** is not using the server entry being dropped.
*/

/*
** Lock syscoordinations to synchronize with dtm service. This type of
** locking on syscoordinations should be done only in extreme case like 
** dropserver as this will potentially block dtm services.
*/
lock table sybsystemdb.dbo.syscoordinations in share mode



if exists (select * from sybsystemdb.dbo.syscoordinations c,
	   master.dbo.sysservers s
	   where s.srvname = @server and 
	   	s.srvid = c.participant and c.owner = 1)
begin
	rollback transaction dropserver

	/*
	** 17537, "Unable to drop server '%1!' because it is 
	** 	   referenced by transaction coordinator."
	*/
	raiserror 17537, @server
	return (1)
end


/* Check to see if there are any related logins in sysremotelogins. */
if (@droplogins is NULL)
begin
	if exists (select *
		from master.dbo.sysremotelogins l,
			master.dbo.sysservers s
		where s.srvid = l.remoteserverid
			and s.srvname = @server)
	begin
		rollback transaction dropserver
		/*
		** 17530, "There are still remote logins for the server '%1!'."
		*/
		raiserror 17530, @server
		return (1)
	end

	/*
	** OMNI: Check to see if there are any related external logins
	*/
	if exists (select * from master.dbo.sysattributes a,
			master.dbo.sysservers s
			where s.srvid = a.object_info1 and
			s.srvname = @server and
			a.class = 9 and a.attribute = 0)
	begin
		rollback transaction dropserver
		/*
		** 17534, "There are still external logins for the 
		**	   server '%1!'."
		*/
		raiserror 17534, @server
		return (1)
	end



end

/*
**  If @droplogins is true then drop any associated logins
*/
else if @droplogins = "droplogins"
begin
		delete master.dbo.sysremotelogins
			from master.dbo.sysremotelogins l,
				master.dbo.sysservers s
			where s.srvid = l.remoteserverid
				and s.srvname = @server

		if (@@rowcount > 0)
		begin


			/*
			** 17531, "Remote logins for remote server '%1!' 
			**	  have been dropped."
			*/
			exec sp_getmessage 17531, @msg output
			print @msg, @server
		end

		/*
		** OMNI: Drop any external logins as well
		*/
		delete master.dbo.sysattributes 
			from master.dbo.sysattributes a,
				master.dbo.sysservers s
			where s.srvname = @server
				and s.srvid = a.object_info1
				and a.class = 9 and a.attribute = 0

		if (@@rowcount > 0)
		begin
		

			/*
			** 17535, "External logins for remote server '%1!'
			** have been dropped."
			*/
			exec sp_getmessage 17535, @msg output
			print @msg, @server
		end

		/* Continue below and drop the server */
end

/*
**  Bad argument to @droplogins.
*/
else
begin
	/*
	** 17532, "Usage: sp_dropserver server [, droplogins]"
	*/
	rollback tran dropserver
	raiserror 17532
	return (1)
end

/*
** Hang up the connection to the server if there is one
*/
dbcc connection_hangup(@server)		



/*
** Fetch the srvid for this server
*/
select @srvid = srvid
from master.dbo.sysservers
	where srvname = @server

/*
** If the server belongs to the ejb class make sure the server is stopped
** before the entry from sysserver is deleted
*/

select @srvclass = srvclass , @physname = srvnetname
	from master.dbo.sysservers 
	where srvname = @server

if @srvclass = 10
begin
	select @command = "STOP"
	/*
	** We go ahead and stop the ejb server when the sp_dropserver command
	** is executed on an ejb server
	*/
	dbcc extengine(@physname, @srvclass, @command)
end

/*
**  Drop the server.
*/
delete master.dbo.sysservers
	where srvname = @server
if (@@error != 0)
begin
	rollback tran dropserver
	return (1)
end

/*
** Drop the rtds provider registered in sysattributes
*/
if (@insysattributes = 1)
	delete master.dbo.sysattributes
	where class = 21 and attribute = 10
		and object_type = 'PR'
		and object_cinfo = @server



/*
** For SDC, update cluster-wide in-memory SRVDES with data from
** just-updated SYSSERVERS table. Before dbcc cis, the dbcc command scope
** needs to be set to cluster.
*/
if (@@clustermode = "shared disk cluster")
begin
	select @scope = NULL
	select @outstr = "dbcc set_scope_in_cluster('scope')"
	if (charindex("instance", @outstr) != 0)
	begin
		/* save the scope to be restored later */
		select @scope = "instance"
		dbcc set_scope_in_cluster('cluster')
	end
end

/*
** Tag in-memory copy as
** unusable.
*/

dbcc cis ("srvdes", @srvid)

/* restore dbcc command scope */
if (@@clustermode = "shared disk cluster")
begin
	if (@scope = "instance")
	begin
		dbcc set_scope_in_cluster('instance')
	end
end

commit transaction dropserver

/*
** 17533, "Server dropped."
*/
exec sp_getmessage 17533, @msg output
print @msg

return (0)

clean_all:

	return (1)

go
exec sp_procxmode 'sp_dropserver', 'anymode'
go
grant execute on sp_dropserver to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dumpoptimize')
begin
	drop procedure sp_dumpoptimize
end
go
print "Installing sp_dumpoptimize"
go


/*
** This procedure configures the amount of data dumped by the Backup Server
** during the 'dump database' command. It sends bs_optimize RPC to the local
** Backup Server, passing all the parameters to the stored procedure as it is.
** The parsing of all the options is done by the Backup Server. 
**
** This can be issued only by users with SA role or oper_role or by the 
** Database owner.
*/

/*
** Messages for "sp_dumpoptimize"
**
** 17260, "Can't run %1! from within a transaction."
** 19958, "Backup Server policy is set to '%1!'."
*/

create procedure sp_dumpoptimize 
@opt1	varchar(255) = NULL,	/* First optimization parameter */
@opt2	varchar(255) = NULL	/* Second optimization parameter */
as

declare @bs_name        varchar(255)	/* BS name */
declare @bs_policy      varchar(255)
declare @msg		varchar(1024)	/* Display BS policy */
begin

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_dumpoptimize"
	return (1)
end


/* 
** Only the Database Owner (DBO) or accounts with either SA role or oper_role
** can execute this procedure. 
**
** If user does not have either the sa role or the oper_role or they are not the
** database owner, we cannot continue any further.
*/
if ( (user_id() != 1) and (proc_role("oper_role") = 0) 
			and (proc_role("sa_role") = 0) )
        return (1)

select @bs_policy = srvnetname from master..sysservers where srvname = "SYB_BACKUP"

/*
** If the Multiple Backup server feature is enabled with Backup server policy
** as $dedicated or $roundrobin, execute bs_optimize for all the active
** Backup servers within cluster.
*/
if ((lower(@bs_policy) = "$dedicated") or (lower(@bs_policy) = "$roundrobin"))
begin
	/* 19958, "Backup Server policy is set to '%1!'." */
	exec sp_getmessage 19958, @msg output
	print @msg, @bs_policy
	
	declare instancenames cursor for
	select srvname from master..sysservers where srvstatus2 = 4

	open instancenames

	fetch instancenames into @bs_name

	while (@@sqlstatus = 0)
	begin
		select @bs_name = @bs_name + "_BS"
		
		/* 19959, "Attempting to execute RPC for Backup Server '%1!'." */
		exec sp_getmessage 19959, @msg output
		print @msg, @bs_name
		
		exec (@bs_name + '...bs_optimize @opt1, @opt2')
		fetch instancenames into @bs_name
	end
	close instancenames
end
else
begin
	/* Issue the bs_optimize RPC to the local Backup Server */
	exec SYB_BACKUP...bs_optimize @opt1, @opt2

end
	return (0)
end

go
exec sp_procxmode 'sp_dumpoptimize', 'anymode'
go
grant execute on sp_dumpoptimize to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_querysmobj')
begin
	drop procedure sp_querysmobj
end
go
print "Installing sp_querysmobj"
go


/*
** This procedure performs queries Backup objects backed up at Storage Manager.
** It sends bs_querysmobj RPC to the Backup Server, passing all the 
** parameters to the stored procedure as it is. The parsing of all the 
** options is done by the Backup Server. The actual Query operation is 
** performed by Backup Server using the syb_queryobj() API call of the 
** API interface supplied as an argument.
**
** This can be issued only by users with SA role or oper_role.
*/

/*
** Messages for "sp_querysmobj"
**
** 17260, "Can't run %1! from within a transaction."
** 18255, "%1! cannot be NULL."
** 19980, "You are not authorized to execute this stored procedure. 
** Only the System Administrator (SA) or a user with oper_role 
** authorization can execute this stored procedure."
**
*/

create procedure sp_querysmobj 
@sm_api_name	varchar(30) = NULL,	/* SM Interface Stream name*/
@output_fname	varchar(255) = NULL,	/* Output filename path */
@server_name	varchar(30) = NULL,	/* Server Instance name */
@database_name	varchar(30) = NULL,	/* Database name */
@object_name	varchar(255) = NULL,	/* Archive object name */
@dump_type	varchar(30) = NULL,	/* Database dump type */
@until_time	varchar(30) = NULL,	/* Until point in time */
@bs_name	varchar(30) = NULL	/* Backup Server name */
as

begin

declare @status		int		/* RPC status */
declare @bs_rpc		varchar(255)	/* RPC site and proc name */

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_querysmobj"
	return (1)
end


/* 
** Only the accounts with either SA role or oper_role can execute this 
** procedure. 
**
** If user does not have either the sa role or the oper_role, we cannot 
** continue any further.
*/
if ( (proc_role("oper_role") = 0) and (proc_role("sa_role") = 0) )
begin
	raiserror 19980
        return (1)
end

/*
** Check for mandatory parameters supplied.
**
*/
if (@sm_api_name is NULL)
begin
	raiserror 18255, "Storage Manager API module name"
	return (1)
end

if (@output_fname is NULL)
begin
	raiserror 18255, "Query output filename"
	return (1)
end

if (@server_name is NULL)
begin
	raiserror 18255, "Server name"
	return (1)
end

/* Select SYB_BACKUP as default Backup Server */
if (@bs_name is NULL)
begin
	select @bs_rpc = 'SYB_BACKUP...bs_querysmobj'
end
else
begin
	select @bs_rpc = @bs_name + '...bs_querysmobj' 
end

exec @status = @bs_rpc @sm_api_name, @output_fname, @server_name, @database_name, @object_name, @dump_type, @until_time, @bs_name

return (@status)

end

go
exec sp_procxmode 'sp_querysmobj', 'anymode'
go
grant execute on sp_querysmobj to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_deletesmobj')
begin
	drop procedure sp_deletesmobj
end
go
print "Installing sp_deletesmobj"
go


/*
** This procedure deletes Backup objects backed up at Storage Manager.
** It sends bs_deletesmobj RPC to the Backup Server, passing all the 
** parameters to the stored procedure as it is. The parsing of all the 
** options is done by the Backup Server. The actual Query operation is 
** performed by Backup Server using the syb_deleteobj() API call of the 
** API interface supplied as an argument.
**
** This can be issued only by users with SA role or oper_role.
*/

/*
** Messages for "sp_deletesmobj"
**
** 17260, "Can't run %1! from within a transaction."
** 18255, "%1! cannot be NULL."
** 19980, "You are not authorized to execute this stored procedure.
** Only the System Administrator (SA) or a user with oper_role
** authorization can execute this stored procedure."
**
*/

create procedure sp_deletesmobj 
@sm_api_name	varchar(30) = NULL,	/* SM Interface Stream name*/
@server_name	varchar(30) = NULL,	/* Server Instance name */
@database_name	varchar(30) = NULL,	/* Database name */
@object_name	varchar(255) = NULL,	/* Archive object name */
@dump_type	varchar(30) = NULL,	/* Database dump type */
@until_time	varchar(30) = NULL,	/* Until point in time */
@bs_name	varchar(30) = NULL	/* Backup Server name */
as

begin

declare @status		int		/* RPC status */
declare @bs_rpc		varchar(255)	/* RPC site and proc name */

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_deletesmobj"
	return (1)
end


/* 
** Only the accounts with either SA role or oper_role can execute this
** procedure.
**
** If user does not have either the sa role or the oper_role, we cannot
** continue any further.
*/
if ( (proc_role("oper_role") = 0) and (proc_role("sa_role") = 0) )
begin
	raiserror 19980
        return (1)
end

/*
** Check for mandatory parameters supplied.
**
*/
if (@sm_api_name is NULL)
begin
	raiserror 18255, "Storage Manager API module name"
	return (1)
end

if (@server_name is NULL)
begin
	raiserror 18255, "Server name"
	return (1)
end

/* Select SYB_BACKUP as default Backup Server */
if (@bs_name is NULL)
begin
	select @bs_rpc = 'SYB_BACKUP...bs_deletesmobj'
end
else
begin
	select @bs_rpc = @bs_name + '...bs_deletesmobj'
end

/* Issue bs_deletesmobj RPC to Backup Server */
exec @status = @bs_rpc @sm_api_name, @server_name, @database_name, @object_name, @dump_type, @until_time, @bs_name

return (@status)

end
go
exec sp_procxmode 'sp_deletesmobj', 'anymode'
go
grant execute on sp_deletesmobj to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_estspace')
begin
	drop procedure sp_estspace
end
go
print "Installing sp_estspace"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*
** Messages for "sp_estspace"
** 17461, "Object does not exist in this database."
** 18054, "Table contains text/image type columns but length for these columns not specified in the argument list.
*/

create procedure sp_estspace

/*	A procedure to estimate the disk space requirements of a table
**	and its associated indexes
**	Written by Malcolm Colton with assistance from Hal Spitz
*/
	(@table_name	varchar(511)=null, /* name of table to estimate */
	 @no_of_rows	float = 0,	  /* number of rows in the table */
	 @fill_factor	float = null,	/* the fill factor */
	 @cols_to_max	varchar(2060) =null, 
					/* variable length columns for which
					to use the maximum rather than 50% of 
					the maximum length. It can hold
					at most 8 column names. */
	 @textbin_len	float = null, /* len of all text & binary data/row */
	 @iosec		float = 30,
	 @pagesize	varchar(30) = null)
as

declare @msg	varchar(120)

if @@trancount = 0
begin
        set chained off
end

set transaction isolation level 1

/*	Give usage statement if @table_name is null */

if @table_name is null or @no_of_rows <= 0 or @fill_factor < 0 or @fill_factor > 100 
begin
	print 'USAGE:'
	print 'sp_estspace table_name, no_of_rows, fill_factor, cols_to_max, textbin_len, iosec'
	print 'where '
	print '      table_name  is the name of the table,'
	print '      no_of_rows  is the number of rows in the table (>0),' 
	print '      fill_factor is the index fill factor. Values range from' 
	print '                   0 to 100. (default = 0,in which case internal'
	print '                   fill factor will be used)' 
	print '      cols_to_max is a list of the variable length columns for which'
	print '                   to use the maximum length instead of the average'
	print '			  (default = null)'
	print '      textbin_len is length of all the text and binary fields per'
	print '                   row ( default =  0).' 
	print '      iosec       is the number of I/Os per second on this machine'
	print '                   (default = 30)'
	print 'Examples: sp_estspace titles, 10000, 50, "title, notes", null, 25'
	print '          sp_estspace titles, 50000'
	print '          sp_estspace titles, 50000, null, null, null, 40'
	return
end

declare	@sum_fixed	int,
	@sum_var	int,
	@sum_avgvar	int,
	@table_id	int,
	@num_var	int,
	@data_pages	float,
	@sysstat	smallint,
	@temp		float,
	@temp1		float,
	@index_id	int,
	@last_id	int,
	@i		int,
	@level_pages	float,
	@key		varchar(255),
	@usertype	tinyint,
	@type		tinyint,
	@level		smallint,
	@vartype	smallint,
	@more		bit,
	@next_level	float,
	@rows_per_page	int,
	@row_len	int,
	@length		int,
	@index_name	varchar(255),
	@page_size	int,
	@page_K		int,
	@index_type	varchar(20),
	@mrpg		smallint,
	@factor		float,
	@status2	int,
	@sysstat2	int,
	@table_type	varchar(3),
	@maxcols_in_key	int,
	@status		int,
        @unit_loc       int          /* The position of the unit in the
                                     ** pagesize parameter string.
                                     */

select	@sum_fixed=0,
	@sum_var=0,
	@sum_avgvar=0,	
	@table_id=0,
	@num_var=0,
	@data_pages=0,
	@row_len=0,
	@sysstat=0,
	@sysstat2 = 0,
	@maxcols_in_key = 31  /* max. columns allowed in an index */

set nocount on

/* set the default fill_factor */
if @fill_factor is null
	select @fill_factor = 0 

/* Make sure table exists */

select  @sysstat = sysstat,
	@table_id = id,
	@sysstat2 = sysstat2
		from sysobjects where id = object_id(@table_name)

if @sysstat & 7 not in (1,3)
begin
	/* 17461, "Object does not exist in this database." */
	raiserror 17461
	return  (1)
end

/* Get the lock scheme for the table */
if @sysstat & 15 in (1, 3)
begin
	/*
        ** the bits 0x2000, 0x4000 & 0x8000 represents any
        ** explicit lock scheme bits that can be set, so
        ** get them out ( 0x2000 + 0x4000 + 0x8000 = 57344)
        */
        select @sysstat2 = (@sysstat2 & 57344)

        if (@sysstat2 in (0, 8192, 16384, 32768))
        begin
                if ( @sysstat2 = 8192 or @sysstat2 = 0)
                begin
                        /* Lock scheme is Allpages */
			select @table_type = "AP"
                end
                if ( @sysstat2 = 16384 or @sysstat2 = 32768)
                begin
                        /* Lock scheme is Data only */
                        select @table_type = "DOL"
                end
        end
        else
        begin
                /* 17579, Lock scheme Unknown or Corrupted */
		raiserror 17579
		return (1)
	end
end

/* If the user provided a pagesize, use it */
if (@pagesize is not NULL)
begin
        /*
        ** Did the user provide a unit with the pagesize parameter?
        ** The units accepted are kilobytes, anything else is a usage error.
        */
        select @unit_loc = patindex("%[kK]%", @pagesize)

        if (@unit_loc = 0)
        begin
                select @page_size = convert(int, @pagesize)
		select @page_K = @page_size / 1024
        end
        else
        begin
                exec @status = sp_aux_getsize @pagesize, @page_K output

                if (@status = 0)
                begin
                        /*
                        ** Invalid syntax
                        ** 18940 "Error: Specified pagesize '%1!' is
                        ** invalid. Valid values are '2048', '4096' '8192',
                        ** '16384', or '2k', '4k', '8k', '16k'.  Unit
                        ** specifiers can also be 'K'."
                        */
                        raiserror 18940, @pagesize
                        return (1)
                end

                /* sp_aux_getsize returns value in K unit. */
                select @page_size = @page_K * 1024

        end

        if (@page_size != 2048 and @page_size != 4096 and
            @page_size != 8192 and @page_size != 16384)
        begin

                /*
                ** Invalid syntax
                ** 18940 "Error: Specified pagesize '%1!' is
                ** invalid. Valid values are '2048', '4096' '8192',
                ** '16384', or '2k', '4k', '8k', '16k'.  Unit
                ** specifiers can also be 'K'."
                */
                raiserror 18940, @pagesize
                return (1)
        end

end
else
begin

	/* Get machine page size if user did not specify one */
	select 	@page_size = low
		from master.dbo.spt_values
			where type = 'E'
			and number = 1
	select @page_K = @page_size / 1024
end


if @table_type = "AP"
	select @page_size = @page_size - 32
else
	select @page_size = @page_size - 44

if @fill_factor !=0
	select @fill_factor = @fill_factor / 100.0

/* Get the max_rows_per_page value */
select @mrpg = maxrowsperpage
	from sysindexes
		where id=@table_id and indid in (0,1)

/* Allpages tables are limited to 255 rows per page */
if @table_type = 'AP' and (@mrpg = 0 or @mrpg > 255 )
	select @mrpg = 255

/* max_rows_per_page option is not valid for DOL tables */
if (@table_type = 'DOL')
begin
	select @mrpg = 0
end

/* Create tables for results */

create table #results
	(name	varchar(255),
	 type	varchar(12),
	 idx_level	smallint,
	 pages	float,
	 Kbytes float)

create table #times
	(name 		varchar(255),
	 type	 	varchar(12) null,
	 tot_pages	float null,
	 time_mins	float 	null)


/* Create table of column info for the table to be estimated */ 

select length, type, name
	into #col_table
		from syscolumns
			where id = @table_id


/* check if text/image lenth specified if these fields exist in the table */
if ( @textbin_len is null )
begin
	if exists( select name from syscolumns where id = @table_id and
			(type = 35 or type = 34 ))
	
	begin
		/* 18054, "Table contains text/image type columns but length for 
		** these columns not specified in the argument list.
		*/
		raiserror 18054
		return  (1)
	end
end
	
	
/* Look up the important values from this table */

/* get fixed length columns (those with types other than 39, 37 (varbinary)) */
select @sum_fixed = isnull(sum(length),0)
	from #col_table
		where type not in (37,39)

/* get var. length columns that have to use the entire size */
select @num_var = isnull(count(*),0), @sum_var = isnull(sum(length),0)
	from #col_table
		where type in (37,39)
			and charindex(name, @cols_to_max) > 0

/* get var. length columns for which average size is used */ 
select @num_var = @num_var + isnull(count(*),0), 
       @sum_avgvar = isnull(sum(length / 2),0)
	from #col_table
		where type in (37,39)
			and charindex(name, @cols_to_max) = 0

/* Calculate the data page requirements */
set arithabort numeric_truncation off

/* variables used for DOL tables */
declare @data_fixed_ovhd 	smallint,
	@data_var_ovhd		smallint,
	@data_len		int,	/* length of the data portion */
	@dol_ind_fixed_ovhd	smallint,
	@dol_ind_var_ovhd	smallint,
	@dol_ind_data_len	int,	/* length of row in index*/
	@next_level_rows	float

select @data_len = @sum_fixed + @sum_var + @sum_avgvar
/* If the table is DOL */
if (@table_type = "DOL")
begin
	/*
	** Overhead if there are no variable length columns:
	** 2 bytes each for row number, status, varcount, row offset table
	** entry.
	**
	** Overhead if variable length columns are present:
	** 2 bytes each for row number, status, varcount, row offset table
	** entry and rowlength.
	** offset table size is 2 bytes per varcol, no adjust table.
	*/
	select @data_fixed_ovhd = 8.0,
		@data_var_ovhd = 10.0 + (2 * @num_var) 
end
else
begin
	/*
	** Overhead if there are no variable length columns:
	** 1 byte each for varcount and row number and 2 bytes for row
	** offset table entry.
	**
	** Overhead if variable length columns are present:
	** 1 byte each for varcount and row number, and 2 bytes for 
	** row offset table entry and rowlength.
	** offset table size is 1 byte per varcol + 1 byte for end of 
	** data offset. Adjust table size is rowlength/256 + 1.
	*/
	select @data_fixed_ovhd = 4.0,
		@data_var_ovhd = 6.0 + (@num_var + 1) + (@data_len/256 + 1)
end
if @num_var = 0 
	select @row_len = @data_fixed_ovhd + @data_len 
else
	select @row_len = @data_var_ovhd + @data_len
/*
** For tables marked for 'incremental transfer', add additional 8 bytes
** for the per row timestamp used for the transfer.
*/
declare @xfer_stat int
select @xfer_stat = number
        from master.dbo.spt_values
        where type = 'O3' and name = "incremental transfer on"

if exists (select 1 from sysobjects 
	   where id = @table_id and (sysstat3 & @xfer_stat = @xfer_stat))
begin
	select @row_len = @row_len + 8
end

/*
** For DOL datapages, the min. row length should be 10 (2bytes each for row 
** number and status + 6 bytes of space for (possible) forwarding address) 
** In the above computation of rowlength we have included the row offset 
** table entry of 2 bytes, we need 10 bytes minimum length excluding these
** 2 bytes.
*/
if @table_type = "DOL"
begin
	if (@row_len - 2) < 10
		select @row_len = 12
end

/* Allow for fill-factor if set to other than zero */

if @fill_factor = 0	
begin
	select @temp = convert(float, @no_of_rows) * 
		( convert(float, @row_len) / convert(float, @page_size) )
end
else
begin
	select @temp = convert(float, @no_of_rows) / 
		(convert(float, @page_size) * convert(float, @fill_factor) )
	select @temp = convert(float, @row_len) * @temp
end

/* 
** If there is maxrowsperpage and it creates less number of pages than
** without it, then use it.
*/
if @mrpg != 0
begin
	select @temp1 = convert(float, @no_of_rows) /
				convert(float, @mrpg)
	if @temp < @temp1
		select @temp = @temp1
end

/* Now add in allocation pages */
select @temp = @temp +(@temp / 256.0)
select @data_pages = @temp + 1.0
if @data_pages < 8.0
	select @data_pages = 8.0

insert #results values 
	(@table_name, 'data', 0, @data_pages, @data_pages * @page_K)

/* calculate the pages for text and length */

/* text/bin pages write multiples of 450 bytes per page */
if ( @textbin_len is not  null )
begin
	select @temp = ceiling( @textbin_len/ (floor(@page_size/450.0)*450.0))
	select @temp = @temp * @no_of_rows
	insert #results values 
		(@table_name, 'text/image', 0, @temp, @temp * @page_K)
end

/* See if the table has any indexes */

select @index_id = min(indid)
	from sysindexes 
		where id = @table_id
			and indid > 0 and indid < 255

if @index_id is null	/* We've finished if there are no indexes */
begin
	select @msg = @table_name + ' has no indexes'
	print @msg

	select name, type, idx_level, 'Pages' = str(pages,12,0), 'Kbytes' = str(Kbytes,12,0)
	into #results_1
	from #results

	exec sp_autoformat @fulltabname = #results_1

	select Total_Mbytes = str(sum(Kbytes)/1024.0,17,2)
		from #results

	drop table #results_1
	drop table #results
	return
end

select 	@sum_fixed = 0,
	@sum_var = 0,
	@num_var = 0,
	@temp = 0

/* For each index, calculate the important variables
** use them to calculate the index size, and print it */

while @index_id is not  null
begin
	select @index_name = name , @mrpg = maxrowsperpage,
		@status2 = status2
		from sysindexes
			where id = @table_id
			and indid = @index_id
	if @index_id = 1
	begin
		select @index_type = 'clustered'
	end
	else
	if @index_id > 1
	begin
		if (@status2 & 512 = 512)
		begin
			select @index_type = 'clustered'
		end
		else
		begin
			select @index_type = 'nonclustered'
		end
	end

	select 	@num_var = 0,
		@sum_var = 0,
		@sum_fixed = 0
	
	if (@table_type = "DOL")
	begin
		select @mrpg = 0
	end

	select @i = 1

	/* Look up each of the key fields for the index */

	while @i <= @maxcols_in_key
	begin
		select @key = index_col(@table_name, @index_id, @i)

		if @key is null
			break
		else			/* Process one key field */
		begin
			select @type = type, @length = length, @vartype = offset
				from syscolumns
					where id = @table_id
					and name = @key

			if @vartype < 0
				select @num_var = @num_var + 1
			else
				select @sum_fixed = @sum_fixed + @length

			/* varchar, varbinary: check if in @cols_to_max */
			if (@type = 37 or @type = 39)	
			begin
				if charindex(@key, @cols_to_max) = 0
				   select @sum_var = @sum_var + (@length / 2)
				else
				   select @sum_var = @sum_var + @length
			end
		end

		select @i = @i + 1	/* Get next key field in this index */
	end

	/* Calculate the space used by this index */

	/* 
	** For indexes of DOL TABLES, we assume the following: 
	** No suffix compression is done, Assumes that all the
	** keys in the index are unique and there is no difference
	** between clustered and nonclustered index
	*/
	select @dol_ind_fixed_ovhd = 9
	select @dol_ind_var_ovhd = 9 + (2 * @num_var) 
	select @dol_ind_data_len = @sum_fixed + @sum_var
	if @table_type = "DOL"
	begin
		if @num_var = 0
			select @row_len = @dol_ind_fixed_ovhd+@dol_ind_data_len
		else
			select @row_len = @dol_ind_var_ovhd + @dol_ind_data_len
	end
	else	/* AP locked object */
	begin
		if @index_id = 1
		begin
			if @num_var = 0
				select @row_len = 5 + @sum_fixed
			else
				select @row_len = @sum_fixed+@sum_var+@num_var+8
		end
		else
		begin
			if @num_var = 0
				select @row_len = 7 + @sum_fixed
			else
				select @row_len =@sum_fixed+@sum_var+@num_var+11
		end
	end

	/* Allow for fill-factor if set to other than zero */

	if @fill_factor = 0 or @index_id = 1
	begin
		select @rows_per_page =  @page_size / @row_len - 2
	end
	else
	begin
		select @rows_per_page = @page_size / @row_len * @fill_factor 
	end

	/* at lease one row per page */
	if @rows_per_page < 1
		select @rows_per_page = 1

	/* Prestage index building information */
	select @more = 1, @level = 0

	/* For DOL indexes, estimate the #levels and #pages */
	if @table_type = "DOL"
	begin
		while @more = 1
		begin
			if @level = 0
			begin
				if @mrpg != 0
					select @rows_per_page = @mrpg
				select @level_pages = @no_of_rows /
						convert(float, @rows_per_page)
				select @next_level_rows = @level_pages
			end
			else if @level > 255
			begin
				/* This index is too big to build */
				raiserror 19414, @index_name
				goto kill_proc
			end
			else
			begin
				select @level_pages = @next_level_rows /
						convert(float, @rows_per_page)
				select @next_level_rows = @level_pages
			end

			/* Account for allocation/oam pages */
			select @level_pages = @level_pages +
						(@level_pages / 256.0) + 1.0
			/* Insert the row into the results table */
			insert #results values
				(@index_name, @index_type, @level,
					@level_pages, 
					floor(@level_pages) * @page_K)
			select @level = @level + 1
			if @next_level_rows <= @rows_per_page
				select @more = 0
		end
		/* Account for the root page */
		insert #results values
		(@index_name, @index_type, @level, 1, @page_K)
	end
	else
	begin	/* AP locked object */
		if @rows_per_page > 256
			select @rows_per_page = 256
		/* 
		** For clustered indexes, the first level of index is 
		** based on the number of data pages. 
		** For nonclustered, it is the number of data rows
		*/

		if @index_id = 1
			select @next_level = @data_pages
		else
			select @next_level = @no_of_rows
		while @more = 1
		begin
			if @index_id != 1 and @level = 0  and @mrpg != 0
				select @rows_per_page = @mrpg

			/* 
			**  No fill factor for non-leaf nodes, 
			**  recalculate rows/page 
			*/
			if @index_id != 1 and @level = 1 
			begin
				select @row_len = @row_len + 4 
				select @rows_per_page = @page_size/@row_len - 2
				if @rows_per_page > 256
					select @rows_per_page = 256
			end

			if @level > 255
			begin
				/* This index is too big to build */
				raiserror 19414, @index_name
				goto kill_proc
			end

			/* 
			**  calculate the number of pages at a single index 
			**  level 
			*/
			select @temp = @next_level / 
					convert(float, @rows_per_page)

			/* Add in a factor for allocation pages */
			select @temp = @temp + (@temp / 256.0) + 1.0
			
			select @level_pages = @temp
			
			insert #results values
				(@index_name, @index_type, @level, @level_pages, 
					floor(@level_pages) * @page_K)
			
			select @next_level = @level_pages
			select @level = @level + 1

			/* see if we can fit the next level in 1 page */
			if @rows_per_page >= @next_level 
				select @more = 0
		end
		/* Account for single root page */
		if @level_pages > 1
			insert #results values
			(@index_name, @index_type, @level, 1, @page_K)
	end


	/* Now look for next index id for this table */

	select @last_id = @index_id
	select @index_id = null
	select @index_id = min(indid)
		from sysindexes 
			where id = @table_id
			and indid > @last_id
			and indid < 255

end

	select name, type, idx_level, 'Pages' = str(pages,12,0), 'Kbytes' = str(Kbytes,12,0)
	into #results_2
	from #results

exec sp_autoformat @fulltabname = #results_2

	drop table #results_2

select Total_Mbytes = str(sum(Kbytes)/1024.0,17,2)
from #results

/* Get ready to calculate creation times for the indexes */

insert #times (name, tot_pages)
	select name, sum(pages) 
	from #results
	where type != 'data'
	group by name

/* Get index type from #results */
update #times
	set #times.type = #results.type
	from #times, #results
	where #times.name = #results.name

/* Add data pages to size of clustered index */
update #times
	set tot_pages=tot_pages + @data_pages
	where type = 'clustered'

/* Calculate for clustered index */

select @factor = ceiling( (log(@data_pages) / 2.07944) - 1.8813 )
update #times
	set time_mins = ( (2 * @factor) + 1) * @data_pages / 60 / @iosec
	where type = 'clustered'

/* Calculate for non-clustered index */

update #times
	set time_mins = ( (2 * @factor * tot_pages) + @data_pages )
		/ 60 / @iosec
	where time_mins is null

select name, type, 'total_pages'=str(tot_pages,12,0),'time_mins'=str(time_mins,12,0)
into #times_1
from #times

exec sp_autoformat @fulltabname = #times_1

drop table #times_1

kill_proc:

drop table #results
drop table #col_table
drop table #times

return
go
exec sp_procxmode 'sp_estspace', 'anymode'
go
grant execute on sp_estspace to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_extendsegment')
begin
	drop procedure sp_extendsegment
end
go
print "Installing sp_extendsegment"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */
/*	5.0	14.2	11/12/91	sproc/src/extendsegment */

/*
** Messages for "sp_extendsegment"      17550
**
** 17260, "Can't run %1! from within a transaction."
** 17520, "There is no such segment as '%1!'."
** 17281, "The specified device is not used by the database."
** 17283, "'%1!' is reserved exclusively as a log device."
** 17280, "No such device exists -- run sp_helpdb to list the devices for the current database."
** 17550, "Segment extended."
** 17551, "Device '%1!' is now exclusively used by '%2!'"
** 17715, "The last-chance threshold for database %1! is now %2! pages."
** 17716, "Could not update the last-chance threshold for database %1!"
** 17552, "This command has been ignored.  Extending the log segment on device '%1!' would leave no space for creating objects in database '%2!'."
** 17590, "The specified database does not exist." 
** 17288, "You must execute this procedure from the database 
** 	  in which you wish to %1! a segment.  Please execute 
**	  'use %2!' and try again."
** 17289, "Set your curwrite to the hurdle of current database."
** 19572, "A segment with a virtually hashed table exists of device %1!."
** 19571, "You cannot extend a segment with a virtually hashed table on device %1!, because this device has other segments."
*/

create procedure sp_extendsegment
@segname	varchar(30),	/* segment name */
@dbname		varchar(30),	/* database name */
@devname	varchar(30)	/* device name to put segment on */
as

declare @dbid	smallint	/* id of the database */
declare @segbit	int		/* this is the bit to turn on in sysusages */
declare @lct	int		/* log new last-chance threshold value */
declare	@msg	varchar(1024)
declare @new_msg varchar(100)
declare @returncode int
declare @procval int
declare @bitdesc varchar(30)	/* bit description for the db */
declare @tempdb_mask   int	/* All database status bit for a tempdb */
declare @isatempdb	int	/* Is this a temp. db ? */
declare @isamaster      int
declare @segmap		int	/* segment map */
declare @tmp_segmap	int
declare @segid		int	/* id of the segment */
declare @status		int	/* status of the segment */

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
 	*/
	raiserror 17260, "sp_extendsegment"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  if user  had SA role he would be the dbo hence check only
**  whether user is DBO.
*/
if (user_id() = 1)
begin
        /* If user has sa role audit this as a successful sa
        ** command execution.
        */
        if charindex("sa_role",show_role()) > 0
                select @procval = proc_role("sa_role")
end
else
begin
        /* user_id() is not DBO hence user does not have SA role
        ** audit this as a failed sa command execution.
        */
        select @procval = proc_role("sa_role")
        return (1)
end

/*
**  Make ure the database exists
*/
if not exists ( select * from master.dbo.sysdatabases
		where name = @dbname )
begin
	/* 17590, "The specified database does not exist." */
	raiserror 17590
	return (1)
end

/*
**  Make sure that we are in the database specified
**  by @dbname. 
*/
if @dbname != db_name()
begin
	/* 
	** 13233, "update"
	** 17288, "You must execute this procedure from the database 
	** 	  in which you wish to %1! a segment.  Please execute 
	**	  'use %2!' and try again."
	*/
	declare @action varchar(30)
	select @action = description
	from master.dbo.sysmessages
	where error = 13233 and langid = @@langid
	if @action is null
		select @action = description
		from master.dbo.sysmessages
		where error = 13233 and langid is null
	if @action is null select @action = "update"
	raiserror 17288, @action, @dbname
	return (1)
end

select @dbid = db_id(@dbname)

/*
**  Check to see if the segment exists.
*/
if not exists (select *
		from syssegments
			where name = @segname)
begin
	/*
	** 17520, "There is no such segment as '%1!'."
	*/
	raiserror 17520, @segname
	return (1)
end

/*
**  See if the device exists.
*/
if not exists (select *
		from master.dbo.sysdevices
			where name like @devname)
begin
	/*
	** 17280, "No such device exists -- run sp_helpdb to list the devices for the current database."

	*/
	raiserror 17280



	return (1)
end

/*
**  Now see if the @dbname uses the @devname
*/

if not exists (select *
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = @dbid)
begin
	/*
	** 17281, "The specified device is not used by the database."
	*/
	raiserror 17281
	return (1)
end

/*
**  Check to see if the device is marked as a log device.
**  If so, print error.
*/
if exists (select *
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = @dbid
				and segmap = 4)
begin
	/*
	** 17283, "'%1!' is reserved exclusively as a log device."
	*/
	raiserror 17283, @devname
	return (1)
end

/*
** Get segment map of device on which segment is extended.
*/
select @segmap=segmap
	from master.dbo.sysusages u, master.dbo.sysdevices d
		where d.name = @devname
			and u.vstart between d.low and d.high
			and u.dbid = db_id(@dbname)
select @status=status 
	from syssegments where name = @segname

/*
** Keep only the status bit regarding whether
** vhash table is there or not on this segment.
*/
select @status = @status & 2

if @status = 2
begin
	/*
	** vhash table is there on this segment. This is an
	** exclusive segment. It can only be extended on a 
	** device having no other segment. Thus, segmap 
	** should be 0.
	*/
	if @segmap > 0
	begin
		/*
		** 19571, You cannot extend a segment with a virtually hashed table on device %1!,
		** because this device has other segments.
		*/
		raiserror 19571, @devname
		return (1)
	end
end
else if @segmap > 0
begin
	/*
	** This is not an exclusive segment. Also there
	** are other segments on the device. Thus, we
	** need to check that none of these is an
	** exclusive segment.
	*/
	select @tmp_segmap = @segmap - 1
	select @tmp_segmap = @segmap & @tmp_segmap
	if @tmp_segmap = 0
	begin
		/*
		** Only one bit is set in segmap.
		** Thus, there is only one segment
		** existing on device. Now we need
		** to check if that segment has vhash
		** table. As if it has a vhash table
		** it will be a exclusive segment and
		** another segment cannot be created
		** on this device.
		*/
		select @segid=log(@segmap)/log(2)
		if exists (select * from syssegments
				where segment=@segid and 2 = status & 2)
		begin
			/*
			** 19572, A segment with a virtually hashed table exists of device %1!.
			*/
			raiserror 19572, @devname
			return (1)
		end
	end
end
/*
**  Get the segment number for @segname.
*/
select @segbit = segment
	from syssegments
		where name = @segname

/*
** Determine if we are dealing with a temporary database.
*/
select @tempdb_mask = number
	from master.dbo.spt_values
	where type = "D3" and name = "TEMPDB STATUS MASK"

if (@dbid = 2) or exists (select * from master.dbo.sysdatabases
	     	            where dbid = @dbid
	     	            and (status3 & @tempdb_mask) != 0)
begin
	select @isatempdb = 1
end
else
begin
	select @isatempdb = 0
end

select @isamaster = 0
if (   (@dbid = db_id("master"))
    or (@dbid = db_id("master_companion")))
begin
	select @isamaster = 1
end



/* Encapsulate sysusages/anchor update in a transaction */
if (@isamaster = 1)
	begin transaction sysusg_upd

/*
**  If @segbit is 2 then it's the logsegment and the logsegment
**  doesn't share devices with other segments.  In this case,
**  don't OR the @segbit in but just set segmap to 4.
**  Also, if we are extending the log space and this is not 
**  a temporary database ...
*/
if @segbit = 2 and  @isatempdb = 0
begin
	/* 
	** ... check single user bit (4096).
	** Database must be in single user mode so that no log allocation
	** or deallocation take place while recalculing the free space counter
	*/ 
	select @bitdesc = null 
	select @bitdesc = v.name
		from master.dbo.spt_values v, master.dbo.sysdatabases d 
			where d.dbid = @dbid
				and v.type = "D" 
				and d.status & v.number = 4096 
	if @bitdesc is null 
	begin 
		/*
		** 17793, "System Administrator (SA) must set database '%1!' to single-user mode with sp_dboption before using '%2!'."
		*/
		raiserror 17793, @dbname, "sp_extendsegment"
		return(1)  
	end  

	/*
	** Extending the logsegment means we won't be able to
	** create any more objects on this device. (See comment above.)
	** Do it only if non-log space is available on other devices.
	*/
	if not exists (select *
		from master.dbo.sysdevices d,
			master.dbo.sysusages u
		where u.vdevno = d.vdevno
			and u.dbid = @dbid
			and u.segmap != 4
			and d.name != @devname
			and d.cntrltype = 0)
	begin
		/*
		** 17552, "This command has been ignored.  Extending the log
		** segment on device '%1!' would leave no space for creating
		** objects in database '%2!'."
		*/
		raiserror 17552, @devname, @dbname
		return (1)
	end

	update master.dbo.sysusages
		set segmap = 4
			from master.dbo.sysusages u,
				master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = @dbid
end

else
begin
	if (@segbit < 31)
		select @segbit = power(2, @segbit)
	else
		/*
		**  Since this is segment 31, power(2, 31) will
		**  overflow since segmap is an int.  We'll grab the
		**  machine-dependent bit mask from spt_values to set
		**  the right bit.
		*/
		select @segbit = low
			from master.dbo.spt_values
				where type = "E"
					and number = 2
	/*
	**  Add the segment to @devname in sysusages.
	*/
	update master.dbo.sysusages
		set segmap = segmap | @segbit
			from master.dbo.sysusages u,
				master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = @dbid
end

/* End the transaction */
if (@isamaster = 1)
begin
	if (@@error != 0)
	begin
		rollback transaction sysusg_upd
		return (1)
	end

	dbcc dbrepair(@dbname, "upd_usg")
	if (@@error != 0)
	begin
		rollback transaction sysusg_upd
		return (1)
	end

	commit transaction sysusg_upd
end

/*
**  Get the segment number for @segname.
*/
select @segbit = segment
	from syssegments
		where name = @segname

/*
**  Now we need to activate the new segment map.
*/
dbcc dbrepair (@dbname, remap, NULL, -1, @segname)

/*
** If we are adding log space, we might be going onto a segment that
** used to contain user data, so we need to look for stranded objects.
*/
if @segbit = 2
begin
	dbcc dbrepair (@dbname, findstranded, NULL, @isatempdb)
end

/*
** Now that dbrepair has remapped the database, we can
** recalculate the log's last-chance threshold.
*/
if @segbit = 2
begin
	select @lct = lct_admin("lastchance", @dbid)
	if @lct > 0
	begin
		exec sp_getmessage 17715, @msg out
		print @msg, @dbname, @lct
	end
	else
	begin
		raiserror 17716, @dbname, @lct
	end
end

/*
** 17550, "Segment extended."
*/
exec sp_getmessage 17550, @msg output
print @msg

/*
**  If we are extending the logsegment, print out a message about what it
**  means to do so.
*/
if @segbit = 2
begin
	/*
	** 17551, "Device '%1!' is now exclusively used by '%2!'"
	*/
	exec sp_getmessage 17551, @msg output
        print @msg, @devname, @segname
end

return (0)
go
exec sp_procxmode 'sp_extendsegment', 'anymode'
go
grant execute on sp_extendsegment to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_fixindex')
begin
	drop procedure sp_fixindex
end
go
print "Installing sp_fixindex"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 22:45:51 2006 
*/
/*
** raiserror Messages for fixindex [Total 15]
**
** 17260, "Can't run %1! from within a transaction."
** 17461, "Object does not exist in this database."
** 17734, "There is no index named '%1!' for table '%2!'."
** 18055, "Procedure should be used on system tables only."
** 18056, "Cannot re-create index on this table."
** 18091, "The target index does not exist."
** 18301, "Database name '%1!' is not the current database."
** 19380, "Error in accessing the table %1!."
** 19596, "Database '%1!' can not be put into single user mode as it is a temporary database. Set %2! to '%3!' for rebuilding the index."
** 19597, "Database '%1!' is a user database. %2! is only used for temporary database."
** 19598, "Index name '%2!' (ID = %3!) is not the name of an index on '%1!'. Use a valid index name or index id."
** 19599, "You must specify either index name or index id but not both."
** 19600, "%1! cannot be used to rebuild a text/image column."
** 19601, "In procedure '%1!', %2! command failed to rebuild the index on table '%3!'."
** 19602, "sp_fixindex database, systemcatalog [, ind_id | null] [,index_name | null] [, true | false]."
*/
/*
** sp_getmessage Messages for fixindex [Total 3]
**
** 17431, "true"
** 17432, "false"
** 18336, "Permission denied. Your curwrite label must be set at the hurdle of the affected database."
*/
/*
** End spgenmsgs.pl output.
*/
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
**	Description:	allow the SA to force a drop and then a
**			create index on system catalogs.
**
**	Usage:	
**
**	sp_fixindex  database, systemcatalog [, ind_id | null] 
**			[,index_name | null] [, true | false]
**
** Note on flags passed to reindex and dbrepair
** ============================================
** 	REINDEX will take the following flags (options) 
**	and it is an integer (reindex_flags).
**
**		1	Do not force single user mode for rebuild of 
**			system table's index.
**		2	Skip rebuild of APL clustered index.
**		4	Do not raise exception during checktable.
**		8	Do not print dbcc complete message.
**		16	Force rebuild of indexes including APL clustered idx.
**
**	The following options are used by DBREPAIR 
**	with REPAIRINDEX (dbrepair_flags).
**
**		1	Drop system table index
**		2	Create system table index
**		4	Check for special bit that marks the object to be
**			re-indexed. This bit is read from SYSOBJECTS. If
**			this option is set and the special bit is missing
**			in SYSOBJECTS then index will not be rebuilt.
**		8	Reports the information about the number of rows and
**			pages that are going to be processed. 
**		16	Check the database is already in "single user" mode
**			for rebuilding the index. This option should not be
**			used for rebuilding indexes in tempdb.
**		32	Check index (using checktable) to decide on the
**			index rebuild. If checktable returns TRUE then 
**			DBREPAIR will not rebuilt any index.
**
** Note about the @force_option
** ============================
**	@force_option is used to rebuild the catalog indices in temporary 
**	databases. It will take either "false" (for user database) or 
**	"true" (for tempdb)
*/

create procedure sp_fixindex
		@dbname		varchar(255),
		@tabname	varchar(255),  		/* system table name */
		@indid		int	= NULL,		/* index id value    */
		@index_name	varchar(255) = NULL,
		@force_option	varchar(10) = NULL
as --{
	declare	 @ramboix 		smallint	/* mask for rambo indx*/
		,@objtype 		char(2)
		,@lcl_indid		int
		,@reindex_flags		int
		,@dbrepair_flags 	int
		,@default_ind_val 	int
		,@dbcc_dbr_dropi	int
		,@dbcc_dbr_cri		int
		,@dbcc_dbr_chk_ramboix	int
		,@dbcc_dbr_report	int
		,@dbcc_dbr_sngusr_mode	int
		,@dbcc_ridx_skip_sngusr	int
		,@dbcc_ridx_force_rbld	int
		,@dbcc_error		int
		,@tempdb_mask		int
		,@lcl_index_name	varchar(255)
		,@dbcc_cmd		varchar(255)
		,@true			varchar(255)
		,@false			varchar(255)


	/* 
	** check if user has SA role, proc_role will also do auditing
	** if required. proc_role will also print error message if required.
	*/
        if (proc_role("sa_role") = 0)
	begin
                return (1)
	end

	/*
	** Check if there is already an active transaction. It there
	** is one then return (do not allow sp_fixindex inside a
	** transaction).
	*/
	if (@@trancount > 0)
	begin
		raiserror 17260, "sp_fixindex"
		return (1)
	end

	/*
	** Make sure that we are in the database specified
	** by @dbname.
	*/
	if @dbname != db_name()
	begin
		raiserror 18301, @dbname
		return (1)
	end

	exec sp_getmessage 17431, @true out
	exec sp_getmessage 17432, @false out

	if (     (@force_option is NOT NULL)
	     and (lower(@force_option) not in ("true", "false", @true, @false)))
	begin
		raiserror 19602
		return (1)
	end

	/*
	** Note on selectivity of dbrepair_flags and reindex_flags.
	**
	** It is mandatory to put user database in "single user mode"
	** and this is not possible for tempdb. Due to this "single user
	** mode" requirement is ignored for tempdb USE 1 for reindex
	** to ignore the "single user mode" and DO NOT USE 16 for
	** dbrepair with REPAIRINDEX option.
	**
	** The main motivation of this procedure is to rebuild the
	** index on the catalogs. It is required to force the index
	** rebuild in both (reindex and dbrepair) case.
	*/

	select   @lcl_indid  = @indid
		,@default_ind_val = NULL
		,@dbcc_dbr_dropi = 1
		,@dbcc_dbr_cri = 2
		,@dbcc_dbr_chk_ramboix = 4
		,@dbcc_dbr_report = 8
		,@dbcc_dbr_sngusr_mode = 16
		,@dbcc_ridx_skip_sngusr = 1
		,@dbcc_ridx_force_rbld = 16
		,@dbcc_error = 0
		,@dbcc_cmd = "GENERIC"

	/*
	** Initialize the default flags to be passed to DBCC commands
	*/
	
	select	 @reindex_flags = @dbcc_ridx_force_rbld
		,@dbrepair_flags = (   @dbcc_dbr_dropi
				     | @dbcc_dbr_cri
				     | @dbcc_dbr_chk_ramboix
				     | @dbcc_dbr_report
				     | @dbcc_dbr_sngusr_mode )

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/*
	** Check whether the current database is tempdb or a user
	** tempdb and set appropriate options. 
	**
	** As 'tempdb' can not be put into "single user" mode additional
	** flags should be passed to "reindex and dbrepair" for rebuilding 
	** the catalogs.
	**
	** @force_option should be used only for tempdb. If this option
	** is used for user database return fail.
	*/

	select @tempdb_mask = number
		from master.dbo.spt_values
		where type = "D3" and name = "TEMPDB STATUS MASK"

	if (    (@dbname = 'tempdb')
	     OR (exists (select 1
			from master.dbo.sysdatabases
			where name = @dbname AND ((status3 & @tempdb_mask) != 0))))
	begin

		if (@force_option not in ("true", @true))
		begin
			raiserror 19596, @dbname, "@force_option", "true"
			return (1)
		end

		select    @reindex_flags = (   @dbcc_ridx_force_rbld
					  | @dbcc_ridx_skip_sngusr)
			, @dbrepair_flags = (   @dbcc_dbr_dropi
				     	    | @dbcc_dbr_cri
				     	    | @dbcc_dbr_chk_ramboix
				     	    | @dbcc_dbr_report)
	end
	else if (@force_option in ("true", @true))
	begin
		raiserror 19597, @dbname, "@force_option"
		return (1)
	end

	select @objtype = type 
	from sysobjects 	
	where name = @tabname

	/* check if the table name is valid */
	if (@objtype is null)
	begin
		raiserror 17461
		return (1)
	end

	/* check if the table is a system table */
	if (@objtype != "S") 
	begin
		raiserror 18055
		return (1)
	end

	/*
	** Explicitly disallow sysindexes, and disallow any
	** table that has no indexes.
	*/
	if @tabname = "sysindexes"
	or not exists (select 1
			from sysindexes 
			where id = object_id(@tabname)
			and indid > 0)	
	begin
		raiserror 18056
		return (1)
	end

	/*
	** Client can specify either @indid or @index_name but not both.
	**
	**	(a) If @indid is valid then rebuild the corresponding
	**	    index.
	**	(b) If @indid is NULL and @index_name is specified then
	**	    rebuild the index associated with @index_name.
	**	(c) If both @indid and @index_name are not NULL and if
	**	    @indid is not associated with @index_name then an error
	**	    will be raised.
	**	    index associated with @indid will be rebuilt.
	**	(d) If both @indid and @index_name are NULL then all the
	**	    indices on @tabname will be rebuilt.
	*/

	if (@lcl_indid is NOT NULL)
	begin --{

		if (@lcl_indid = 0)
		begin
			raiserror 19598, @tabname, @tabname, 0
			return (1)
		end

		if (@lcl_indid = 255)
		begin
			raiserror 19600, "sp_fixindex"
			return (1)
		end

		select @lcl_index_name = name	
		from sysindexes
		where id = object_id(@tabname) and indid = @lcl_indid

		if (     (@index_name is NOT NULL)
		     and (@lcl_index_name != @index_name))
		begin
			raiserror 19599
			return (1)
		end

		if (@lcl_index_name is NULL)	
		begin
			raiserror 18091
			return (1)
		end

	end --}
	else if (@index_name is NOT NULL)
	begin --{

		/*
		** If the index name is given then retrieve the
		** index id from SYSINDEXES.
		*/
		select @lcl_indid = indid
		from sysindexes
		where id = object_id(@tabname) 
		      and name=@index_name
		      and indid > 0 and indid < 255

		/*
		** If index name is suplied we should get a valid
		** index id i.e @lcl_indid should be non NULL
		*/

		if (@lcl_indid is NULL)
		begin
			raiserror 17734, @index_name, @tabname
			return (1)
		end
	end --}


	/*
	**	At this point we are sure that the table has an index
	**	of requested type, so all there is to be done is to
        **      set the ramboix bit for this object.
        */

	begin tran set_sysobjects_sysstat

        select @ramboix = 4096
        update sysobjects set sysstat = sysstat | @ramboix
        where name = @tabname
 
 	if (@@error != 0)
	begin
		raiserror 19380, 'sysobjects'
		rollback set_sysobjects_sysstat
		return (@@error)
	end

	commit tran set_sysobjects_sysstat

        checkpoint @dbname

	/*
	** If indid is default indid (i.e NULL) then the whole table should
	** be rebuilt. Otherwise rebuild only the index associated with
	** @lcl_indid.
	*/
	if (@lcl_indid is NULL)
	begin
		select @dbcc_cmd = "DBCC REINDEX"
		dbcc reindex(@tabname, @reindex_flags)
	end
	else
	begin
		select @dbcc_cmd = "DBCC DBREPAIR"
		dbcc dbrepair(@dbname, REPAIRINDEX, @tabname, 
				@lcl_indid, @dbrepair_flags)
	end

	/*
	** Remember the result of DBCC commands.
	*/
	select @dbcc_error = @@error

	/*
	**	Processing successfully done, so turn off the ramboix
	**	bit, after telling the user that all is fine.
	*/

	begin tran unset_sysobjects_sysstat

	update sysobjects set sysstat = sysstat & ~@ramboix
	where name = @tabname

	if (@@error != 0)
	begin
		raiserror 19380, 'sysobjects'
		rollback unset_sysobjects_sysstat
		return (@@error)
	end

	commit tran unset_sysobjects_sysstat
 
	checkpoint @dbname

	if (@dbcc_error != 0)
	begin
		raiserror 19601, "sp_fxindex", @dbcc_cmd, @tabname
		return (@dbcc_error)
	end

	return (0)
-- }
go
exec sp_procxmode 'sp_fixindex', 'anymode'
go
grant execute on sp_fixindex to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_fkeys')
begin
	drop procedure sp_fkeys
end
go
print "Installing sp_fkeys"
go

/* sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** note: there is one raiserror message: 18040
**
** messages for "sp_fkeys"               18039, 18040
**
** 17461, "Object does not exist in this database." 
** 18040, "Catalog procedure %1! can not be run in a transaction.", sp_fkeys
** 18043 " Primary key table name or foreign key table name or both must be 
** given"
** 18044, "%1! table qualifier must be name of current database." [Primary
** key | Foreign key]
**
*/
CREATE PROCEDURE sp_fkeys
			   @pktable_name		varchar(257) = null,
			   @pktable_owner		varchar(32) = null,
			   @pktable_qualifier	varchar(32) = null,
			   @fktable_name		varchar(257) = null,
			   @fktable_owner		varchar(32) = null,
			   @fktable_qualifier	varchar(32) = null 
as
declare @ftabid int, @ptabid int, @keycnt int, @i int
declare @fokey1 int,  @fokey2 int,  @fokey3 int,  @fokey4 int,  @fokey5  int
declare @fokey6 int,  @fokey7 int,  @fokey8 int,  @fokey9 int,  @fokey10 int
declare @fokey11 int, @fokey12 int, @fokey13 int, @fokey14 int, @fokey15 int
declare @refkey1 int, @refkey2 int, @refkey3 int, @refkey4 int, @refkey5  int
declare @refkey6 int, @refkey7 int, @refkey8 int, @refkey9 int, @refkey10 int
declare @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
declare @refkey15 int, @refkey16 int, @fokey16 int, @status int
declare @msg varchar(1024)
declare @msg2 varchar(1024)
declare @ordpkey	int


	set nocount on

	if (@@trancount = 0)
	begin
		set chained off
	end
	else
	begin
		/* if inside a transaction */
		/* catalog procedure sp_fkeys can not be run in a transaction.*/
		raiserror 18040, "sp_fkeys"
		return (1)
	end

	set transaction isolation level 1

	if (@pktable_name is null) and (@fktable_name is null)
	begin	
		/* If neither primary key nor foreign key table names given */
		/* 
		** 18043 "Primary key table name or foreign key table name 
		** or both must be given"
		*/
		raiserror 18043
		return (1)
	end

	if @fktable_qualifier is not null
	begin
		if db_name() != @fktable_qualifier
		begin	
			/* If qualifier doesn't match current database */
			/* 18044 "%1! Table qualifier must be name of current database"
			** 18050 "Foreign key"
			*/
			exec sp_getmessage 18050, @msg2 output
			raiserror 18044, @msg2
			return (1)
		end
	end
	else
	begin
		/*
		** Now make sure that foreign table qualifier is pointing to the
		** current database in case it is not specified.
		*/
		select @fktable_qualifier = db_name()
	end

	if @pktable_qualifier is not null
	begin
		if db_name() != @pktable_qualifier
		begin	
			/* If qualifier doesn't match current database */
			/* 18044 "%1! Table qualifier must be name of current database"
			** 18051 "Primary Key"
			*/
			exec sp_getmessage 18051, @msg2 output
			raiserror 18044, @msg2
			return (1)
		end
	end
	else
	begin
		/*
		** Now make sure that primary table qualifier is pointing to the
		** current database in case it is not specified.
		*/
		select @pktable_qualifier = db_name()
	end


	create table #pid (pid int, uid int, name varchar(30))
	create table #fid (fid int, uid int, name varchar(30))

	/* we will sort by fkey		*/
	/* unless pktable is null	*/

	select @ordpkey = 0

	if @pktable_name is not null
	begin 

		if (@pktable_owner is null)
		begin
			/* 
			** owner is NULL, so default to the current user
			** who owns this table, otherwise default to dbo
			** who owns this table.
			*/
			insert into #pid 
			select id, uid, name
			from sysobjects 
			where name = @pktable_name and uid = user_id()
			and type in ("S", "U")
			
			/* 
			** If the current user does not own the table, see
			** if the DBO of the current database owns the table.
			*/

			if ((select count(*) from #pid ) = 0)
			begin
				insert into #pid 
				select id, uid, name
				from sysobjects 
				where name = @pktable_name and uid = 1
				and type in ("S", "U")
			end
		end
		else
		begin
			insert into #pid
			select id, uid, name
			from sysobjects
			where name = @pktable_name 
			and uid = user_id(@pktable_owner)
			and type in ("S", "U")
		end
	end
	else 
	begin
		if (@pktable_owner is null)
		begin
		/* 
		** If neither pktable_name nor pktable_owner is specified,
		** then we are interested in every user or system table.
		*/
			insert into #pid 
			select id, uid, name
			from sysobjects 
			where type in ("S", "U")
		end
		else
		begin
			insert into #pid
			select id, uid, name
			from sysobjects
			where  uid = user_id(@pktable_owner)
			and type in ("S", "U")
		end
	end
		
	if @fktable_name is not null
	begin 
		/* sort by pkey	*/
		select @ordpkey = 1

		if (@fktable_owner is null)
		begin
			/* 
			** owner is NULL, so default to the current user
			** who owns this table, otherwise default to dbo
			** who owns this table.
			*/
			insert into #fid 
			select id, uid, name
			from sysobjects 
			where name = @fktable_name and uid = user_id()
			and type in ("S", "U")

			/* 
			** If the current user does not own the table, see
			** if the DBO of the current database owns the table.
			*/

			if ((select count(*) from #pid ) = 0)
			begin
				insert into #fid 
				select id, uid, name
				from sysobjects 
				where name = @fktable_name and uid = 1
				and type in ("S", "U")
			end
		end
		else
		begin
			insert into #fid
			select id, uid, name
			from sysobjects
			where name = @fktable_name 
			and uid = user_id(@fktable_owner)
			and type in ("S", "U")
		end
	end
	else
	begin
		if (@fktable_owner is null)
		begin
		/* 
		** If neither fktable_name nor fktable_owner is specified,
		** then we are interested in every user table or systme 
		** table.
		*/			
			insert into #fid 
			select id, uid, name
			from sysobjects 
			where type in ("S", "U")
		end
		else
		begin
			insert into #fid
			select id, uid, name
			from sysobjects
			where  uid = user_id(@fktable_owner)
			and type in ("S", "U")
		end
	end

	if (((select count(*) from #fid ) = 0) or
		((select count(*) from #pid) = 0))
	begin
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end

	create table #fkey_res( pktable_qualifier varchar(32),
				pktable_owner       varchar(32),
				pktable_name       varchar(257),
				pkcolumn_name      varchar(257),
				fktable_qualifier varchar(32),
				fktable_owner       varchar(32),
				fktable_name       varchar(257),
				fkcolumn_name       varchar(257),
				key_seq           smallint,	
				update_rule smallint, 
				delete_rule smallint)
	create table #pkeys(seq int,  keys varchar(30) null)
	create table #fkeys(seq int, keys varchar(30) null)

	/*
	** Since there are possibly multiple rows in sysreferences
	** that describe foreign and primary key relationships among
	** two tables, so we declare a cursor on the selection from
	** sysreferences and process the output at row by row basis.
	*/
		
	declare curs_sysreferences cursor
	for
	select tableid, reftabid, keycnt,
	fokey1, fokey2, fokey3, fokey4, fokey5, fokey6, fokey7, fokey8, 
	fokey9, fokey10, fokey11, fokey12, fokey13, fokey14, fokey15,
	fokey16, refkey1, refkey2, refkey3, refkey4, refkey5,
	refkey6, refkey7, refkey8, refkey9, refkey10, refkey11,
	refkey12, refkey13, refkey14, refkey15, refkey16
	from sysreferences
	where tableid in (
		select fid from #fid)
	and reftabid in (
		select pid from #pid)
	and frgndbname is NULL and pmrydbname is NULL
	for read only

	open  curs_sysreferences

	fetch  curs_sysreferences into @ftabid, @ptabid, @keycnt,@fokey1, 
	@fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8, 
	@fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15, 
	@fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6, 
	@refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12, 
	@refkey13, @refkey14, @refkey15, @refkey16

	while (@@sqlstatus = 0)
	begin
		/*
		** For each row of sysreferences which describes a foreign-
		** primary key relationship, do the following.
		*/

		/*
		** First store the column names that belong to primary keys
		** in table #pkeys for later retrieval.
		*/

		delete #pkeys
		insert #pkeys values(1, col_name(@ptabid,@refkey1))
		insert #pkeys values(2, col_name(@ptabid,@refkey2))
		insert #pkeys values(3, col_name(@ptabid,@refkey3))
		insert #pkeys values(4, col_name(@ptabid,@refkey4))
		insert #pkeys values(5, col_name(@ptabid,@refkey5))
		insert #pkeys values(6, col_name(@ptabid,@refkey6))
		insert #pkeys values(7, col_name(@ptabid,@refkey7))
		insert #pkeys values(8, col_name(@ptabid,@refkey8))
		insert #pkeys values(9, col_name(@ptabid,@refkey9))
		insert #pkeys values(10, col_name(@ptabid,@refkey10))
		insert #pkeys values(11, col_name(@ptabid,@refkey11))
		insert #pkeys values(12, col_name(@ptabid,@refkey12))
		insert #pkeys values(13, col_name(@ptabid,@refkey13))
		insert #pkeys values(14, col_name(@ptabid,@refkey14))
		insert #pkeys values(15, col_name(@ptabid,@refkey15))
		insert #pkeys values(16, col_name(@ptabid,@refkey16))
	
		/*
		** Second store the column names that belong to foreign keys
		** in table #fkeys for later retrieval.
		*/
		
		delete #fkeys
		insert #fkeys values(1, col_name(@ftabid,@fokey1))
		insert #fkeys values(2, col_name(@ftabid,@fokey2))
		insert #fkeys values(3, col_name(@ftabid,@fokey3))
		insert #fkeys values(4, col_name(@ftabid,@fokey4))
		insert #fkeys values(5, col_name(@ftabid,@fokey5))
		insert #fkeys values(6, col_name(@ftabid,@fokey6))
		insert #fkeys values(7, col_name(@ftabid,@fokey7))
		insert #fkeys values(8, col_name(@ftabid,@fokey8))
		insert #fkeys values(9, col_name(@ftabid,@fokey9))
		insert #fkeys values(10, col_name(@ftabid,@fokey10))
		insert #fkeys values(11, col_name(@ftabid,@fokey11))
		insert #fkeys values(12, col_name(@ftabid,@fokey12))
		insert #fkeys values(13, col_name(@ftabid,@fokey13))
		insert #fkeys values(14, col_name(@ftabid,@fokey14))
		insert #fkeys values(15, col_name(@ftabid,@fokey15))
		insert #fkeys values(16, col_name(@ftabid,@fokey16))
	
		/* 
		** For each column of the current foreign-primary key relation,
		** create a row into result table: #fkey_res.
		*/

		select @i = 1
		while (@i <= @keycnt)
		begin
			insert into #fkey_res 
				select @pktable_qualifier,
				(select user_name(uid) from #pid where pid = @ptabid),
				object_name(@ptabid),
				(select keys from #pkeys where seq = @i),
				@fktable_qualifier,
				(select user_name(uid) from #fid where fid = @ftabid),
				object_name(@ftabid), 
				(select keys from #fkeys where seq = @i),@i,
				1, 1
			select @i = @i + 1
		end
		
		/* 
		** Go to the next foreign-primary key relationship if any.
		*/

		fetch  curs_sysreferences into @ftabid, @ptabid, @keycnt,@fokey1, 
		@fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8, 
		@fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15, 
		@fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6, 
		@refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12, 
		@refkey13, @refkey14, @refkey15, @refkey16
	end

	close curs_sysreferences
	deallocate cursor curs_sysreferences

	/*
	** Everything is now in the result table #fkey_res, so go ahead
	** and select from the table now.
	*/

	/* if @ordpkey = 0 sort by fkey */
	/* else sort by pkey		*/

	if @ordpkey = 0
	begin
		exec sp_autoformat @fulltabname = #fkey_res,
			@selectlist = "pktable_qualifier, pktable_owner, pktable_name,pkcolumn_name, fktable_qualifier, fktable_owner,fktable_name, fkcolumn_name, key_seq, update_rule, delete_rule",
			@orderby = "order by fktable_name,fktable_owner,key_seq, fktable_qualifier"
	end
	else
	begin
		exec sp_autoformat @fulltabname = #fkey_res,
			@selectlist = "pktable_qualifier, pktable_owner, pktable_name,pkcolumn_name, fktable_qualifier, fktable_owner,fktable_name, fkcolumn_name, key_seq, update_rule, delete_rule",
			@orderby = "order by pktable_name,pktable_owner,key_seq, pktable_qualifier"
	end
go
exec sp_procxmode 'sp_fkeys', 'anymode'
go
grant execute on sp_fkeys to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_metrics')
begin
	drop procedure sp_help_metrics
end
go
print "Installing sp_help_metrics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_help_metrics"
**
** 19347, "Usage: sp_metrics [ 'command', [ '@arg1', [ '@arg2' ] ] ]"
** 19348, "help - get help on a command"
** 19349, "flush - flush all metrics from memory to system tables"
** 19350, "drop - drop a metric ID or a group of metrics"
** 19351, "backup - move the metrics in the default group to a backup group"       
** 19418, "filter - delete metrics records based on filtering condition"
** 19459, "show - display the number of records in each metrics group"
** 19352, "Usage: sp_metrics 'help' [, 'command' ]"
** 19353, "Usage: sp_metrics 'flush'"
** 19354, "Usage: sp_metrics 'drop', '@gid'  [, '@id' ]"
** 19355, "Usage: sp_metrics 'backup', '@gid'"
** 19419, "Usage: sp_metrics 'filter', '@gid' [, '@predicate' ]"
** 19460, "Usage: sp_metrics 'show'"
** 19356, "'%1!' is an unsupported command. Check command and retry sp_metrics"
*/

/*
** sp_help_metrics displays usage information for qpmetrics
** related stored procedures
*/
create procedure sp_help_metrics
	@cmdtype varchar(30)	= NULL
as
declare @msg		varchar(250)

if (@cmdtype is NULL)
begin
	exec sp_getmessage 19347, @msg output print @msg
	print " "
	print "Command list:"

	exec sp_getmessage 19348, @msg output print @msg
	exec sp_getmessage 19349, @msg output print @msg
	exec sp_getmessage 19350, @msg output print @msg
	exec sp_getmessage 19351, @msg output print @msg
	exec sp_getmessage 19418, @msg output print @msg
	exec sp_getmessage 19459, @msg output print @msg
	print " "

	return 0
end

if (@cmdtype = 'help')
begin
	exec sp_getmessage 19352, @msg output print @msg
	return 0
end

if (@cmdtype = 'flush')
begin
	exec sp_getmessage 19353, @msg output print @msg
	return 0
end

if (@cmdtype = 'drop')
begin
	exec sp_getmessage 19354, @msg output print @msg
	return 0
end

if (@cmdtype = 'backup')
begin
	exec sp_getmessage 19355, @msg output print @msg
	return 0
end

if (@cmdtype = 'filter')
begin
	exec sp_getmessage 19419, @msg output print @msg
	return 0
end

if (@cmdtype = 'show')
begin
	exec sp_getmessage 19460, @msg output print @msg
	return 0
end

raiserror 19356, @cmdtype

return 1
go
exec sp_procxmode 'sp_help_metrics', 'anymode'
go
grant execute on sp_help_metrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_metrics')
begin
	drop procedure sp_drop_metrics
end
go
print "Installing sp_drop_metrics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_drop_metrics"
**
** 19344, "No qpmetrics record with id = '%1!' exists in this database."
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 19345, "No qpmetrics group with group id = '%1!' exists in this database."
*/

/*
** sp_drop_metrics delete a qpmetrics record from SYSQUERYMETRICS
** or delete a whole group qpmetrics (sa only).
*/

create procedure sp_drop_metrics
@gid	int = NULL,
@id	int = NULL
as
	declare @uid	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	select @uid = nullif(user_id(), 1)

	if @id is not null
	begin
		delete from sysqueryplans
			where
				uid = isnull(@uid, uid)
				and id = @id

		if @@rowcount = 0
		begin
			/* 19344, "No qpmetrics record with id = '%1!' exists in this database." */
			raiserror 19344, @id

			return 1
		end
	end
	else
	begin
		if user_id() != 1 and charindex("sa_role", show_role()) = 0
		begin
			/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
			raiserror 17230

			return 2
		end
		else
		begin
			if @gid <= 0 or not exists (select 1 from sysqueryplans where gid = - @gid)
			begin
				/* 19345, "No qpmetrics group with group id = '%1!' exists in this database." */
				raiserror 19345, @gid

				return 3
			end
			else
			begin
				delete from sysqueryplans
					where
						gid = - @gid
			end
		end
	end

	return 0
go
exec sp_procxmode 'sp_drop_metrics', 'anymode'
go
grant execute on sp_drop_metrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_backup_metrics')
begin
	drop procedure sp_backup_metrics
end
go
print "Installing sp_backup_metrics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_backup_metrics"
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 19346, "qpmetrics group '%1!' is invalid or a group with this group ID already exists in this database."
**
*/

/*
** sp_backup_metrics move all qpmetrics from the default running group
** to another backup group in SYSQUERYMETRICS (sa only).
*/

create procedure sp_backup_metrics
@gid	int
as
	declare @uid	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	select @uid = nullif(user_id(), 1)

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230

		return 1
	end
	else
	begin
		if @gid <= 0 or exists (select 1 from sysqueryplans where gid = - @gid)
		begin
			/* 19346, "qpmetrics group '%1!' is invalid or a group with this group ID already exists in this database." */
			raiserror 19346, @gid

			return 2
		end
		else
		begin
			update sysqueryplans
			set gid = - @gid
				where
					gid = -1
		end
	end

	return 0
go
exec sp_procxmode 'sp_backup_metrics', 'anymode'
go
grant execute on sp_backup_metrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_show_metrics')
begin
	drop procedure sp_show_metrics
end
go
print "Installing sp_show_metrics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** sp_show_metrics
**
** Display information in metrics groups
** Requires Galaxy or later
**
*/

create procedure sp_show_metrics
as

select gid 'Group ID', count(*) '#Metrics'
from sysquerymetrics
where sequence = 0
group by gid
order by gid

return (0)
go
exec sp_procxmode 'sp_show_metrics', 'anymode'
go
grant execute on sp_show_metrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_filter_metrics')
begin
	drop procedure sp_filter_metrics
end
go
print "Installing sp_filter_metrics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_filter_metrics"
**
** 19417, "predicate '%1!' is an invalid filter condition."
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 19345, "No qpmetrics group with group id = '%1!' exists in this database."
*/

/*
** sp_filter_metrics delete qpmetrics records from SYSQUERYMETRICS
** based on the inputed predicate and gid (sa only).
*/

create procedure sp_filter_metrics
@pgid	varchar(30) = NULL,
@pred	varchar(600) = NULL
as
	declare @gid	int
	declare @filter_cmd	varchar(1000)

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	if user_id() != 1 and charindex("sa_role", show_role()) = 0
	begin
		/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
		raiserror 17230

		return 1
	end
	else
	begin
		select @gid = convert(integer, @pgid)

		if @gid <= 0 or not exists (select 1 from sysqueryplans where gid = - @gid)
		begin
			/* 19345, "No qpmetrics group with group id = '%1!' exists in this database." */
			raiserror 19345, @gid

			return 2
		end
		else
		begin
			/* Now do the pruning based on the filtering condition */
			select @filter_cmd =
				" delete sysqueryplans from sysqueryplans, sysquerymetrics where "
			select @filter_cmd = @filter_cmd + "sysqueryplans.gid = - @gid and "
			select @filter_cmd = @filter_cmd + "sysqueryplans.id = sysquerymetrics.id and "
			select @filter_cmd = @filter_cmd + "( " + @pred + " )"
			exec(@filter_cmd)
			
			/* 19417, "predicate '%1!' is an invalid filter condition" */
			if (@@error != 0)
			begin
				raiserror 19417, @pred

				return 3
			end
		end
	end

	return 0
go
exec sp_procxmode 'sp_filter_metrics', 'anymode'
go
grant execute on sp_filter_metrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_flushmetrics')
begin
	drop procedure sp_flushmetrics
end
go
print "Installing sp_flushmetrics"
go

/*
** sp_flushmetrics
**
** Dump metrics in memory to system catalog
** Requires Galaxy or later
**
*/

create procedure sp_flushmetrics
as

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

dbcc traceon(3604)
dbcc flushmetrics
dbcc traceoff(3604)

return (0)
go
exec sp_procxmode 'sp_flushmetrics', 'anymode'
go
grant execute on sp_flushmetrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_metrics')
begin
	drop procedure sp_metrics
end
go
print "Installing sp_metrics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_metrics"
**
** 19357, "Syntax error. Extra arguments passed to '%1!' command. Run: sp_metrics 'help', '%1!' for usage information."
** 19356, "'%1!' is an unsupported command. Check command and retry sp_metrics"
** 19421, "Syntax error. '%1!' should be a string representation of an integer, such as '100'."
*/

/*
** sp_metrics
**
**	Top-level user-interface procedure for QP metrics procedures.
**
**	This procedure is the command-control for the entire interface. It
**	receives the command from the user, parses it, and then calls other
**	sub-procs to execute on each command.
**
** Returns:
**	0	- All checks are ok. Execution is ok.
**	1	- Some errors (arguments, usage) or permission(s) issues.
*/
create procedure sp_metrics 
	@command	varchar(30)	= NULL
      , @arg1		varchar(30)	= NULL
      , @arg2		varchar(600)	= NULL
as

declare @retval		int	/* From called sub-procedure.*/
	, @param1	int
	, @param2	int
	, @param_len	int
	, @loopcount	int
	, @param_bit	char(1)

select @retval = 1 	/* Expect failure. */

set transaction isolation level 1
if @@trancount = 0
begin
	set chained off
end
set nocount on

/*
** Allow non-sa users (or even non-dbo users) to run without any
** arguments, at least so that the dbo can get some help info before
** working on a particular command. (It is difficult to further restrict
** this to regular users when we have absolutely no arguments.)
** Remaining permissions checks will be done shortly hereafter.
*/
if (@command IS NULL)
begin
	exec @retval = sp_help_metrics
	return @retval
end

/*
** ****************************************************************
** No top-level permissions checks are being done in this procedure
** as the permissions vary depending on the command being run and
** granularity of the operation. Permission checking will be
** implemented by each sub-command's procedure.
** ****************************************************************
*/
if (@command = 'flush')
begin
	if (@arg1 is NOT NULL or @arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail.*/
		raiserror 19357, @command
		return 1
	end

	exec @retval = sp_flushmetrics
end
else if (@command = 'backup')
begin
	if (@arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail. */
		raiserror 19357, @command
		return 1
	end

	select @loopcount = 0
	select @param_len = char_length(@arg1)
	while (@loopcount <= @param_len)
	begin
		select @param_bit = substring(@arg1, @loopcount, 1)
		if NOT (@param_bit >= '0' and @param_bit <= '9')
		begin
			raiserror 19421, '@arg1'
			return 1
		end
		select @loopcount = @loopcount + 1
	end

	select @param1 = convert(integer, @arg1)
	exec @retval = sp_backup_metrics @param1
end
else if (@command = 'drop')
begin
	select @loopcount = 0
	select @param_len = char_length(@arg1)
	while (@loopcount <= @param_len)
	begin
		select @param_bit = substring(@arg1, @loopcount, 1)
		if NOT (@param_bit >= '0' and @param_bit <= '9')
		begin
			raiserror 19421, '@arg1'
			return 1
		end
		select @loopcount = @loopcount + 1
	end

	select @loopcount = 0
	select @param_len = char_length(@arg2)
	while (@loopcount <= @param_len)
	begin
		select @param_bit = substring(@arg2, @loopcount, 1)
		if NOT (@param_bit >= '0' and @param_bit <= '9')
		begin
			raiserror 19421, '@arg2'
			return 1
		end
		select @loopcount = @loopcount + 1
	end

	select @param1 = convert(integer, @arg1)
	select @param2 = convert(integer, @arg2)
	exec @retval = sp_drop_metrics @param1, @param2
end
else if (@command = 'filter')
begin
	select @loopcount = 0
	select @param_len = char_length(@arg1)
	while (@loopcount <= @param_len)
	begin
		select @param_bit = substring(@arg1, @loopcount, 1)
		if NOT (@param_bit >= '0' and @param_bit <= '9')
		begin
			raiserror 19421, '@arg1'
			return 1
		end
		select @loopcount = @loopcount + 1
	end

	exec @retval = sp_filter_metrics @arg1, @arg2
end
else if (@command = 'show')
begin
	if (@arg1 is NOT NULL or @arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail.*/
		raiserror 19357, @command
		return 1
	end

	exec @retval = sp_show_metrics
end
else if (@command = 'help')
begin
	if (@arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail. */
		raiserror 19357, @command
		return 1
	end
	exec @retval = sp_help_metrics @arg1
end
else
begin
	raiserror 19356, @command
	return 1
end

set nocount off

return @retval
go
exec sp_procxmode 'sp_metrics', 'anymode'
go
grant execute on sp_metrics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_query_tuning')
begin
	drop procedure sp_help_query_tuning
end
go
print "Installing sp_help_query_tuning"
go

/*
** Generated by spgenmsgs.pl on Tue Dec 19 13:40:33 2006 
*/
/*
** raiserror Messages for help_query_tuning [Total 1]
**
** 19618, "Unsupported command '%1!'. Check command and retry sp_query_tuning."
*/
/*
** sp_getmessage Messages for help_query_tuning [Total 9]
**
** 19348, "help - get help on a command"
** 19619, "Usage: sp_query_tuning [ 'command' [, '@arg1' [, '@arg2' [, '@arg3' ] ] ] ]"
** 19620, "flush - flush all query_tuning metrics from memory to system tables"
** 19621, "drop - drop a query_tuning object or a query_tuning ID or a group of query_tuning objects"
** 19622, "show - display the query_tuning status in each query_tuning group"
** 19623, "Usage: sp_query_tuning 'help' [, 'command' ]"
** 19624, "Usage: sp_query_tuning flush"
** 19625, "Usage: sp_query_tuning 'drop', '@gid' [, '@id' [, '@lrnid' ] ]"
** 19626, "Usage: sp_query_tuning show, ase125_better_plans|ase15_better_plans|query_tuning_objects|aborted_query_tuning_plans"
*/
/*
** End spgenmsgs.pl output.
*/

/*
** sp_help_query_tuning displays usage information for query_tuning optimizer
** related stored procedures
*/
create procedure sp_help_query_tuning
	@cmdtype varchar(30)	= NULL
as
declare @msg		varchar(250)

if (@cmdtype is NULL)
begin
	exec sp_getmessage 19619, @msg output print @msg
	print " "
	print "Command list:"

	exec sp_getmessage 19348, @msg output print @msg
	exec sp_getmessage 19620, @msg output print @msg
	exec sp_getmessage 19621, @msg output print @msg
	exec sp_getmessage 19622, @msg output print @msg
	print " "

	return 0
end

if (@cmdtype = 'help')
begin
	exec sp_getmessage 19623, @msg output print @msg
	return 0
end

if (@cmdtype = 'flush')
begin
	exec sp_getmessage 19624, @msg output print @msg
	return 0
end

if (@cmdtype = 'drop')
begin
	exec sp_getmessage 19625, @msg output print @msg
	return 0
end

if (@cmdtype = 'show')
begin
	exec sp_getmessage 19626, @msg output print @msg
	return 0
end

raiserror 19618, @cmdtype

return 1
go
exec sp_procxmode 'sp_help_query_tuning', 'anymode'
go
grant execute on sp_help_query_tuning to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_flush_query_tuning')
begin
	drop procedure sp_flush_query_tuning
end
go
print "Installing sp_flush_query_tuning"
go

/*
** Generated by spgenmsgs.pl on Tue Dec 19 13:41:30 2006 
*/
/*
** raiserror Messages for flush_query_tuning [Total 0]
*/
/*
** sp_getmessage Messages for flush_query_tuning [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

/*
** sp_flush_query_tuning
**
** Dump query_tuning metrics in memory to system catalog
** Requires Galaxy or later
**
*/

create procedure sp_flush_query_tuning
as

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

dbcc traceon(3604)
dbcc flushmetrics
dbcc traceoff(3604)

return (0)
go
exec sp_procxmode 'sp_flush_query_tuning', 'anymode'
go
grant execute on sp_flush_query_tuning to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_query_tuning')
begin
	drop procedure sp_drop_query_tuning
end
go
print "Installing sp_drop_query_tuning"
go

/*
** Generated by spgenmsgs.pl on Tue Dec 19 13:42:46 2006 
*/
/*
** raiserror Messages for drop_query_tuning [Total 3]
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 19627, "No query_tuning object with id = '%1!' exists in this database."
** 19628, "No query_tuning group with group id = '%1!' exists in this database."
*/
/*
** sp_getmessage Messages for drop_query_tuning [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

/*
** sp_drop_query_tuning delete records from SYSQUERYPLANS associated with
** a particular query_tuning object or a query_tuning group (sa only).
*/

create procedure sp_drop_query_tuning
@gid	int = NULL,
@id	int = NULL
as
	declare @uid	int

	set nocount on

	/* Don't start a transaction for the user, he does not expect it. */
	if @@trancount = 0
	begin
		set chained off
	end

	/* Don't hold long READ locks, the user might not appreciate it. */
	set transaction isolation level 1

	select @uid = nullif(user_id(), 1)

	if @id is not null
	begin
		delete from sysqueryplans
			where
				uid = isnull(@uid, uid)
				and id = @id

		if @@rowcount = 0
		begin
			/* 19627, "No learning record with id = '%1!' exists in this database." */
			raiserror 19627, @id

			return 1
		end
	end
	else
	begin
		if user_id() != 1 and charindex("sa_role", show_role()) = 0
		begin
			/* 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure." */
			raiserror 17230

			return 2
		end
		else
		begin
			if @gid <= 0 or not exists (select 1 from sysqueryplans sq1 where gid = @gid and exists (select 1 from sysqueryplans sq2 where sq2.id=sq1.id and sq2.type>100))
			begin
				/* 19628, "No learning group with group id = '%1!' exists in this database." */
				raiserror 19628, @gid

				return 3
			end
			else
			begin
				delete from sysqueryplans
				where
					gid = @gid and
					id in (select id from sysqueryplans where type>100 group by id)	
			end
		end
	end

	return 0
go
exec sp_procxmode 'sp_drop_query_tuning', 'anymode'
go
grant execute on sp_drop_query_tuning to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_show_query_tuning')
begin
	drop procedure sp_show_query_tuning
end
go
print "Installing sp_show_query_tuning"
go

/*
** Generated by spgenmsgs.pl on Tue Dec 19 13:43:49 2006 
*/
/*
** raiserror Messages for show_query_tuning [Total 0]
*/
/*
** sp_getmessage Messages for show_query_tuning [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

/*
** sp_show_query_tuning
**
** Display information in query_tuning groups
** Requires Galaxy or later
**
*/

create procedure sp_show_query_tuning
	@showtype varchar(30)	= NULL
as
declare @msg		varchar(250)
declare @uid	int

set nocount on

/* 
** sa is allowed to query all query_tuning entries (including uid 0 entry). 
** Regular user can only query the rows with the same uid.
*/
if user_id() != 1 and charindex("sa_role", show_role()) = 0
begin
	select @uid = user_id()
end
else
begin
	select @uid = null
end

if (@showtype = 'query_tuning_objects')
begin
	select gid 'Group ID', count(*) 'Query Tuning Objects'
	from sysqueryplans
	where ((type > 100 and type < 1000) or type > 1000)
	  and uid = isnull(@uid, uid)
	group by gid
	order by gid

	return 0
end

if (@showtype = 'ase125_better_plans')
begin
	select id, sequence, text
	from sysqueryplans sq1
	where type < 100 
	  and uid = isnull(@uid, uid)
	  and id in
		(select id from sysqueryplans sq2
		 where sq2.id = sq1.id 
		   and sq2.type > 1000
		   and (sq2.status & 2) != 0
		   and not exists 
			(select id from sysqueryplans sq3
			 where sq3.id = sq2.id
			   and sq3.type > 1000
			   and (sq3.status is NULL or (sq3.status & 2) = 0)
			   and convert(int, substring(sq3.text, charindex('t3', sq3.text) + 3, charindex('l1', sq3.text) - charindex('t3', sq3.text) - 4)) < convert(int, substring(sq2.text, charindex('t3', sq2.text) + 3, charindex('l1', sq2.text) - charindex('t3', sq2.text) - 4)))
		  and exists
			(select id from sysqueryplans sq4
			 where sq4.id = sq2.id
			   and sq4.type > 1000
			   and (sq4.status is NULL or (sq4.status & 2) = 0)
			   and convert(int, substring(sq4.text, charindex('t3', sq4.text) + 3, charindex('l1', sq4.text) - charindex('t3', sq4.text) - 4)) > convert(int, substring(sq2.text, charindex('t3', sq2.text) + 3, charindex('l1', sq2.text) - charindex('t3', sq2.text) - 4))))

	return 0
end

if (@showtype = 'ase15_better_plans')
begin
	select id, sequence, text
	from sysqueryplans sq1
	where type < 100 
	  and uid = isnull(@uid, uid)
	  and id in
		(select id from sysqueryplans sq2
		 where sq2.id = sq1.id 
		   and sq2.type > 1000
		   and (sq2.status is NULL or (sq2.status & 2) = 0)
		   and not exists 
			(select id from sysqueryplans sq3
			 where sq3.id = sq2.id
			   and sq3.type > 1000
			   and (sq3.status & 2) != 0
			   and convert(int, substring(sq3.text, charindex('t3', sq3.text) + 3, charindex('l1', sq3.text) - charindex('t3', sq3.text) - 4)) < convert(int, substring(sq2.text, charindex('t3', sq2.text) + 3, charindex('l1', sq2.text) - charindex('t3', sq2.text) - 4)))
		   and exists
			(select id from sysqueryplans sq4
			 where sq4.id = sq2.id
			   and sq4.type > 1000
			   and (sq4.status & 2) != 0
			   and convert(int, substring(sq4.text, charindex('t3', sq4.text) + 3, charindex('l1', sq4.text) - charindex('t3', sq4.text) - 4)) > convert(int, substring(sq2.text, charindex('t3', sq2.text) + 3, charindex('l1', sq2.text) - charindex('t3', sq2.text) - 4))))

	return 0
end

return 1
go
exec sp_procxmode 'sp_show_query_tuning', 'anymode'
go
grant execute on sp_show_query_tuning to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_query_tuning')
begin
	drop procedure sp_query_tuning
end
go
print "Installing sp_query_tuning"
go

/*
** Generated by spgenmsgs.pl on Tue Dec 19 13:25:48 2006 
*/
/*
** raiserror Messages for query_tuning [Total 3]
**
** 19421, "Syntax error. '%1!' should be a string representation of an integer, such as '100'."
** 19617, "Syntax error. Extra arguments passed to '%1!' command. Run: sp_query_tuning 'help', '%1!' for usage information."
** 19618, "Unsupported command '%1!'. Check command and retry sp_query_tuning."
*/
/*
** sp_getmessage Messages for query_tuning [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

/*
** sp_query_tuning
**
**	Top-level user-interface procedure for query_tuning optimizer procedures.
**
**	This procedure is the command-control for the entire interface. It
**	receives the command from the user, parses it, and then calls other
**	sub-procs to execute on each command.
**
** Returns:
**	0	- All checks are ok. Execution is ok.
**	1	- Some errors (arguments, usage) or permission(s) issues.
*/
create procedure sp_query_tuning 
	@command	varchar(30)	= NULL
      , @arg1		varchar(30)	= NULL
      , @arg2		varchar(600)	= NULL
as

declare @retval		int	/* From called sub-procedure.*/
	, @param1	int
	, @param2	int
	, @param_len	int
	, @loopcount	int
	, @param_bit	char(1)

select @retval = 1 	/* Expect failure. */

set transaction isolation level 1
if @@trancount = 0
begin
	set chained off
end
set nocount on

/*
** Allow non-sa users (or even non-dbo users) to run without any
** arguments, at least so that the dbo can get some help info before
** working on a particular command. (It is difficult to further restrict
** this to regular users when we have absolutely no arguments.)
** Remaining permissions checks will be done shortly hereafter.
*/
if (@command IS NULL)
begin
	exec @retval = sp_help_query_tuning
	return @retval
end

/*
** ****************************************************************
** No top-level permissions checks are being done in this procedure
** as the permissions vary depending on the command being run and
** granularity of the operation. Permission checking will be
** implemented by each sub-command's procedure.
** ****************************************************************
*/
if (@command = 'flush')
begin
	if (@arg1 is NOT NULL or @arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail.*/
		raiserror 19617, @command
		return 1
	end

	exec @retval = sp_flush_query_tuning
end
else if (@command = 'drop')
begin
	select @loopcount = 0
	select @param_len = char_length(@arg1)
	while (@loopcount <= @param_len)
	begin
		select @param_bit = substring(@arg1, @loopcount, 1)
		if NOT (@param_bit >= '0' and @param_bit <= '9')
		begin
			raiserror 19421, '@arg1'
			return 1
		end
		select @loopcount = @loopcount + 1
	end

	select @loopcount = 0
	select @param_len = char_length(@arg2)
	while (@loopcount <= @param_len)
	begin
		select @param_bit = substring(@arg2, @loopcount, 1)
		if NOT (@param_bit >= '0' and @param_bit <= '9')
		begin
			raiserror 19421, '@arg2'
			return 1
		end
		select @loopcount = @loopcount + 1
	end

	select @param1 = convert(integer, @arg1)
	select @param2 = convert(integer, @arg2)
	exec @retval = sp_drop_query_tuning @param1, @param2
end
else if (@command = 'show')
begin
	if (@arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail.*/
		raiserror 19617, @command
		return 1
	end

	exec @retval = sp_show_query_tuning @arg1
end
else if (@command = 'help')
begin
	if (@arg2 is NOT NULL)
	begin
		/* Report on extra arguments, and fail. */
		raiserror 19617, @command
		return 1
	end
	exec @retval = sp_help_query_tuning @arg1
end
else
begin
	raiserror 19618, @command
	return 1
end

set nocount off

return @retval
go
exec sp_procxmode 'sp_query_tuning', 'anymode'
go
grant execute on sp_query_tuning to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_flushstats')
begin
	drop procedure sp_flushstats
end
go
print "Installing sp_flushstats"
go

/*
** Messages for "sp_flushstats" 
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
*/

create procedure sp_flushstats
@objname varchar(767) = NULL			/* object name we're after */
as

declare @objid	int
declare	@dbid int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

select @dbid = db_id()

if @objname is NULL
begin
	
	declare cs cursor for
		select O.id
			from sysobjects O
			where O.sysstat & 15 in (1, 3)
	open cs
	fetch cs into @objid

	dbcc traceon(3604)

	while @@sqlstatus = 0
	begin
		dbcc flushstats(@dbid, @objid)
		fetch cs into @objid
	end

	dbcc traceoff(3604)

	close cs
	deallocate cursor cs
	return (0)
end
	
/*
**  Make sure the @objname is local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return  (1)
end

/*
**  Now check to see if the @objname is in sysobjects.
*/
select @objid = object_id(@objname)

if not exists (select *
	from sysobjects
		where id = @objid
		and sysstat & 15 in (1,3))
begin
	/* 17461, "No table as specified exists in this database." */
	raiserror 17461
	return  (1)
end


	dbcc traceon(3604)

dbcc flushstats(@dbid, @objid)

	dbcc traceoff(3604)


return (0)
go
exec sp_procxmode 'sp_flushstats', 'anymode'
go
grant execute on sp_flushstats to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_foreignkey')
begin
	drop procedure sp_foreignkey
end
go
print "Installing sp_foreignkey"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */

/*
** Messages for "sp_foreignkey"         17560
**
** 17390, "Table or view name must be in 'current' database."
** 17560, "Foreign key table doesn't exist."
** 17561, "Primary key table doesn't exist."
** 17562, "Only the owner of the table may define a foreign key."
** 17563, "The table does not have a column named '%1!'."
** 	  ** substitute in "@col[1-8]" for the arg.
** 17564, "Primary key does not exist with the same number of columns as the foreign key."
** 17565, "Primary key does not exist."
** 17566, "Datatypes of the column '%1!' in the keys are different." 
** 	  ** substitute in "@col[1-8]" for the arg.
** 17567, "New foreign key added."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_foreignkey 
@tabname  varchar(767),		/* name of table that we are doing */
@pktabname varchar(767),		/* name of table with primary key */
@col1     varchar(255), 		/* column name of table we are doing */
@col2     varchar(255) = NULL,
@col3     varchar(255) = NULL,
@col4     varchar(255) = NULL,
@col5     varchar(255) = NULL,
@col6     varchar(255) = NULL,
@col7     varchar(255) = NULL,
@col8     varchar(255) = NULL
as

declare @uid int		/* id of owner of the talbe */
declare @cnt    int		/* how many columns are in foreign key */

declare @pkey1 int		/* colids of the foreign key */
declare @pkey2 int
declare @pkey3 int
declare @pkey4 int
declare @pkey5 int
declare @pkey6 int
declare @pkey7 int
declare @pkey8 int

declare @fkey1 int		/* colids of the primary key */
declare @fkey2 int
declare @fkey3 int
declare @fkey4 int
declare @fkey5 int
declare @fkey6 int
declare @fkey7 int
declare @fkey8 int

declare @msg   varchar(1024)
declare @dbname varchar(30)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see that the tabname is local.
*/
if @tabname like "%.%.%"
begin
	if substring(@tabname, 1, charindex(".", @tabname) - 1) != db_name()
	begin
		/*
		** 17390, "Table or view name must be in 'current' database."
		*/
		raiserror 17390
		return (1)
	end
end
if @pktabname like "%.%.%"
begin
	if substring(@pktabname, 1, charindex(".", @pktabname) - 1) != db_name()
	begin
		/*
		** 17390, "Table or view name must be in 'current' database."
		*/
		raiserror 17390
		return (1)
	end
end

/*
**  See if we can find the objects.  They must be a system table, user table,
**  or view.  The low 3 bits of sysobjects.sysstat indicate what the 
**  object type is -- it's more reliable than using sysobjects.type which
**  could change.
*/
if not exists (select *
	from sysobjects
		where id = object_id(@tabname)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3))	/* user table */
/*
**  If either of the tables don't exist, quit.
*/
begin
    /*
    ** 17560, "Foreign key table doesn't exist."
    */
    raiserror 17560
    return (1)
end 
if not exists (select *
	from sysobjects
		where id = object_id(@pktabname)
			and (sysstat & 7 = 1
				or sysstat & 7 = 2
				or sysstat & 7 = 3))
begin
    /*
    ** 17561, "Primary key table doesn't exist."
    */
    raiserror 17561
    return (1)
end 

/*
**  Only the owner of the table can define it's foreign keys.
*/
select @uid = uid
	from sysobjects
		where id = object_id(@tabname)
			and (sysstat & 7 = 1            /* system table */
				or sysstat & 7 = 2      /* view */
				or sysstat & 7 = 3)     /* user table */

if @uid != user_id()
begin
	/*
        ** 17562, "Only the owner of the table may define a foreign key."
	*/
	raiserror 17562
	return (1)
end

/*
**  Now check to see that the foreign key columns exist.
**
**  Algorithm is "if key exists
**			set @fkey[n] to colid
**			incr cnt
**			unless there is no colid
**			then raise an error
**		  cascade to next key
*/
select @cnt = 1, @fkey1 = colid
	from syscolumns
		where name = @col1 
			and id = object_id(@tabname)
if @fkey1 is NULL
begin
	/*
	** 17563, "The table does not have a column named '%1!'."
	*/
	raiserror 17563, @col1
	return (1)
end

-- we know we have at least 1 col in fk
if @col2 is not NULL
begin
	select @cnt = @cnt + 1, @fkey2 = colid
		from syscolumns
			where name = @col2 
				and id = object_id(@tabname)
	if @fkey2 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col2
		return (1)
	end
end
else goto foreign_ok -- we know we have at least 1 col in fk
-- we know we have at least 2 col in fk

if @col3 is not NULL
begin
	select @cnt = @cnt + 1, @fkey3 = colid
		from syscolumns
			where name = @col3 
				and id = object_id(@tabname)
	if @fkey3 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col3
		return (1)
	end
end
else goto foreign_ok -- we didn't have a third key
-- we know we have at least 3 col in fk

if @col4 is not NULL
begin
	select @cnt = @cnt + 1, @fkey4 = colid
		from syscolumns
			where name = @col4 
				and id = object_id(@tabname)
	if @fkey4 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col4
		return (1)
	end
end
else goto foreign_ok -- we didn't have a forth key
-- you get the idea by now of the algorithm!

if @col5 is not NULL
begin
	select @cnt = @cnt + 1, @fkey5 = colid
		from syscolumns
			where name = @col5 
				and id = object_id(@tabname)
	if @fkey5 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col5
		return (1)
	end
end
else goto foreign_ok

if @col6 is not NULL
begin
	select @cnt = @cnt + 1, @fkey6 = colid
		from syscolumns
			where name = @col6 
				and id = object_id(@tabname)
	if @fkey6 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col6
		return (1)
	end
end
else goto foreign_ok

if @col7 is not NULL
begin
	select @cnt = @cnt + 1, @fkey7 = colid
		from syscolumns
			where name = @col7 
				and id = object_id(@tabname)
	if @fkey7 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col7
		return (1)
	end
end
else goto foreign_ok

if @col8 is not NULL
begin
	select @cnt = @cnt + 1, @fkey8 = colid
		from syscolumns
			where name = @col8 
				and id = object_id(@tabname)
	if @fkey8 is NULL
	begin
		/*
		** 17563, "The table does not have a column named '%1!'."
		*/
		raiserror 17563, @col8
		return (1)
	end
end


/*
**  If we made it this far then all the columns for the foreign key are ok.
*/
foreign_ok:

/*
**  Now let's check out the primary key that the foreign key is on.
**  There must be the same number of columns in the key and the
**  base types of the columns must agree.
*/
select @pkey1 = key1, @pkey2 = key2, @pkey3 = key3, @pkey4 = key4,
	@pkey5 = key5, @pkey6 = key6, @pkey7 = key7, @pkey8 = key8
		from syskeys
	where id = object_id(@pktabname)
		and type = 1
		and keycnt = @cnt

/*
**  If @pkey1 is null then there is no such primary key or the number of
**  columns in the primary key are not the same as the number of columns
**  in the foreign key.
*/
if @pkey1 is  NULL
begin
	if exists (select *
			from syskeys
		where id = object_id(@pktabname)
			and type = 1)
	begin
		/*
		** 17564, "Primary key does not exist with the same number of columns as the foreign key."
		*/
		raiserror 17564
	end
	else
	begin
		/*
		** 17565, "Primary key does not exist."
		*/
		raiserror 17565
	end
	return (1)
end

/*
**  Since we have the right number of columns in the foreign and primary keys,
**  check that their base datatypes agree. 
*/
if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey1
			and a.id = object_id(@tabname)
			and b.colid = @pkey1
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
begin
	/*
	** 17566, "Datatypes of the column '%1!' in the keys are different."
	*/
	raiserror 17566, @col1
	return (1)
end

/*
** Now the algorithm becomes existence of col[n] requires
** key to match PK [n]
**
** again we cascade until we reach a null col[n] OR n = 8
**
** A null col[n] means we did not specify the key (by logic above)
** and hence we can progress to insert the FK.
** A non-null col[n] means we have a key, but is it of the right type?
** If not, raise error and return 1
** Else; we have a key, its column types match the corresponding PK column
** so do we have any more key columns to check?
*/
if (@col2 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey2
			and a.id = object_id(@tabname)
			and b.colid = @pkey2
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this.
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col2
		return (1)
	end
end -- here we need to check another key

if (@col3 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey3
			and a.id = object_id(@tabname)
			and b.colid = @pkey3
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this!
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col3
		return (1)
	end
end -- here we need to check another key

if (@col4 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey4
			and a.id = object_id(@tabname)
			and b.colid = @pkey4
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this.
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col4
		return (1)
	end
end -- here we need to check another key

if (@col5 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey5
			and a.id = object_id(@tabname)
			and b.colid = @pkey5
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this.
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col5
		return (1)
	end
end -- here we need to check another key

if (@col6 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey6
			and a.id = object_id(@tabname)
			and b.colid = @pkey6
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this.
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col6
		return (1)
	end
end -- here we need to check another key

if (@col7 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey7
			and a.id = object_id(@tabname)
			and b.colid = @pkey7
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this.
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col7
		return (1)
	end
end -- here we need to check another key

if (@col8 is NULL)
begin
/* our work is done! */
	goto doinsert 
end
else /* we must check this key for consistency */
begin
	if not exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.colid = @fkey8
			and a.id = object_id(@tabname)
			and b.colid = @pkey8
			and b.id = object_id(@pktabname)
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
	begin -- it failed! Don't insert this.
		/*
		** 17566, "Datatypes of the column '%1!'
		** in the keys are different."
		*/
		raiserror 17566, @col8
		return (1)
	end
end 

/*
**  Everything is consistent so add the foreign key to syskeys.
*/
doinsert:
/*
** Before we insert a new foreign key relationship, check if a duplicate
** one exists. If so, fail this new insert. We are allowed to only have
** one foreign key relationship defined for a set of tables on the same
** set of columns.
*/
if exists (select 1 from syskeys
	   where id 		= object_id(@tabname)
	     and type 		= 2
	     and depid		= object_id(@pktabname)
	     and keycnt		= @cnt
	     and size		= 0
	     and key1		= @fkey1
	     and key2		= @fkey2
	     and key3		= @fkey3
	     and key4		= @fkey4
	     and key5		= @fkey5
	     and key6		= @fkey6
	     and key7		= @fkey7
	     and key8		= @fkey8

	     and depkey1	= @pkey1
	     and depkey2	= @pkey2
	     and depkey3	= @pkey3
	     and depkey4	= @pkey4
	     and depkey5	= @pkey5
	     and depkey6	= @pkey6
	     and depkey7	= @pkey7
	     and depkey8	= @pkey8
	  )
begin
	raiserror 17569, @tabname, @pktabname
	return(1)
end

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction	
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

insert syskeys (id, type, depid, keycnt, size, key1, key2, key3, key4, key5,
	key6, key7, key8, depkey1, depkey2, depkey3, depkey4, depkey5,
	depkey6, depkey7, depkey8, spare1)
values (object_id(@tabname), 2, object_id(@pktabname), @cnt, 0, @fkey1, 
	@fkey2, @fkey3, @fkey4, @fkey5,
	@fkey6, @fkey7, @fkey8, @pkey1, @pkey2, @pkey3, @pkey4, @pkey5,
	@pkey6, @pkey7, @pkey8, 0)

if @@error != 0
begin
	rollback transaction rs_logexec
	return (1)
end

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_foreignkey", @dbname
			
	rollback transaction rs_logexec
	return(1)
end

commit transaction
	
/* 
** 17567, "New foreign key added."
*/
exec sp_getmessage 17567, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_foreignkey', 'anymode'
go
grant execute on sp_foreignkey to public
go
exec sp_procxmode 'sp_foreignkey', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpcomputedcolumn')
begin
	drop procedure sp_helpcomputedcolumn
end
go
print "Installing sp_helpcomputedcolumn"
go

/*
** Internal routine to be called by some external system stored procedures
** to display the text of computed columns or functional index keys.
** 
** Messages for "sp_helpcomputedcol"           
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database." 
** 17761, "Object '%1!' is not a table."
** 19334, "Warning: Configuration Parameter 'allow select on syscomments.text'
**	   is set to 0. Only the object owner or user with sa_role can access 
**	   the text. The text for the computed column(s) cannot be 
**	   displayed."
** 19335, "Warning: Configuration Parameter 'allow select on syscomments.text'
**	   is set to 0. Only the object owner or user with sa_role can access 
**	   the text. The text for the functional index key(s) cannot be 
**	   displayed."
** 19336, "Table '%1!' does not have any computed columns."
** 19337, "Text is encrypted"
** 19338, "Object has the following functional index keys"
** 19339, "Object has the following computed columns"
**
** Parameters
**	@objname	- name of the table object
**	@mode		- Mode in which this proc is invoked:
**			   null	- invoked as a standalone proc
**			   0	- invoked to display computed column info
**			   1	- invoked to display functional index key info 
*/

create procedure sp_helpcomputedcolumn
@objname varchar(767),
@mode int = null
as
declare @count int, @total int, @row_id int, @config_parm int
declare @msg varchar(1024)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
set nocount on


/*
** Do necessary error checking if invoked as a standalone proc
*/
if @mode is null
begin
	/*
	**  Make sure the @objname is local to the current database.
	*/
	if @objname like "%.%.%" and
		substring(@objname, 1, charindex(".", @objname) - 1) 
			!= db_name()
	begin
		/* 17460, "Object must be in the current database." */
		raiserror 17460
		return (1)
	end

	/*
	**  See if @objname exists.
	*/
	if (object_id(@objname) is NULL)
	begin
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end

	/* 
	** See if this is a table object
	*/
	if not exists (select 1 from sysobjects 
				where id = object_id(@objname) and
				sysstat & 15 in (1,3))
	begin
		/* 17761, "Object '%1!' is not a table." */
		raiserror 17761, @objname
		return (1)
	end
end


/*
** Create temporary table to stored computed column info 
*/
create table #helpcpc (colname varchar(255), computedcol int, 
			property varchar(15) null, row_id numeric identity)

/* 
** Get info on computed columns
*/
if @mode != 1
begin
	insert into #helpcpc(colname, computedcol, property) 
		select name, 
		       computedcol, 
		       case when (status2 & 32 = 32) then "materialized"
			    else "virtual" end
		from syscolumns where 
		id = object_id(@objname) and 
		computedcol is not null and 
		status3 & 1 != 1 
		order by colid
end
/*
** Get Info on functional index keys
*/
else
begin
	insert into #helpcpc(colname, computedcol) 
		select name, computedcol from syscolumns where 
		id = object_id(@objname) and 
		computedcol is not null and 
		status3 & 1 = 1 
		order by colid
end

/* 
** If nothing to display
*/
if not exists (select 1 from #helpcpc)
begin
	if @mode is null
	begin
		/* Tell the user that there is no computed column */
        	exec sp_getmessage 19336, @msg output
		print @msg, @objname
	end

	drop table #helpcpc
	return (0)
end

/*
** Display the header
*/
if @mode != 1
begin
	exec sp_getmessage 19339, @msg output
end
else
begin
	exec sp_getmessage 19338, @msg output
end
print @msg
print ""

/*
** If the configuration parameter 'allow select on syscomments.text' 
** is set to 0, then the user can access the text ONLY in the 
** following cases
** 
**	1. if the user has sa_role
**	2. if the object is owned by the user
**
*/
select @config_parm = value 
	from master.dbo.syscurconfigs 
where config = 258

if @config_parm = 0 and user_id() != 1
begin
	/*
	** The object needs to be owned by the user
	*/
	if not exists (select name from sysobjects 
				where uid = user_id() 
				and id = object_id(@objname))
	begin
		/* 
		** Inform the user the text cannot be displayed and 
		** print the rest info before return
		*/
		if @mode != 1
		begin
        		exec sp_getmessage 19334, @msg output
			print @msg
			exec sp_autoformat #helpcpc, "'Column_Name' = colname,
				Property = property"
		end
		else
		begin
			exec sp_getmessage 19335, @msg output
			print @msg
			exec sp_autoformat #helpcpc, 
				"'Internal_Index_key_Name' = colname"
		end
		
		drop table #helpcpc
		return(0)
	end
end

/*
** Now display the text
*/
create table #helptxt (text varchar(255), row_id numeric (10) identity)
create table #helpname (colname varchar(255), property varchar(15) null)

select @count = 1
select @total = max(row_id) + 1 from #helpcpc
while @count < @total
begin
	insert into #helpname(colname, property)
	select colname, property from #helpcpc where row_id = @count

	if @mode != 1
	begin	
		exec sp_autoformat #helpname, "'Column_Name' = colname, 
				Property = property"
	end
	else
	begin
		exec sp_autoformat #helpname, 
			"'Internal_Index_Key_Name' = colname"
	end
	
	/*
	** See if the object is hidden (SYSCOM_TEXT_HIDDEN will be set)
	*/	
	if exists (select 1 from syscomments m, #helpcpc h where
			(m.status & 1 = 1) and 
			m.id = h.computedcol and 
			h.row_id = @count)
	begin
        	exec sp_getmessage 19337, @msg output
		print @msg
		print ""
		delete #helpname
		select @count = @count + 1
		continue
	end

	insert #helptxt (text) select text from syscomments, #helpcpc
	where row_id = @count and id = computedcol order by colid2, colid

	print ""
	if @mode != 1
	begin
		exec sp_autoformat #helptxt, "Text = text"
	end
	else
	begin
		select @row_id = min(row_id) from #helptxt
		update #helptxt set text = right(text, char_length(text)-4)
		where row_id = @row_id

		select @row_id = max(row_id) from #helptxt
		update #helptxt set text = left(text, char_length(text)-13)
		where row_id = @row_id
		exec sp_autoformat #helptxt, "Expression = text"
	end
	print ""

	select @count = @count + 1
	delete #helpname
	delete #helptxt
end 

drop table #helpcpc, #helpname, #helptxt

return (0)
go
exec sp_procxmode 'sp_helpcomputedcolumn', 'anymode'
go
grant execute on sp_helpcomputedcolumn to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpconstraint')
begin
	drop procedure sp_helpconstraint
end
go
print "Installing sp_helpconstraint"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
** 17761, "Object is not a table." 
** 18024, "Object does not have any declarative constraints."
** 18243, "Total Number of Referential Constraints: %1!"
** 18449, "Details:"
** 18244, "-- Number of references made by this table: %1!"
** 18245, "-- Number of references to this table: %1!"
** 18246, "-- Number of self references of this table: %1!"
** 18247, "Formula for Calculation:"
** 18450, "Total Number of Referential Consraints"
** 18451, "= Number of references made by this table"
** 18452, "+ Number of references to this table"
** 18453, "- Number of self references within this table"
*/

/*
** Type of declarative constraints returned by this routine are as follows :
**	DEFAULT		     - report the defaults on a column
**	PRIMARY KEY	     - implies clustered index
**	UNIQUE  KEY	     - implies non-clustered index; if no clustered
**			       index exists, this will be clustered
**	CHECK CONSTRAINT     - check constraint, either column or table
**	REFERENCE CONSTRAINT - foreign key/ referential constraint
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/
CREATE PROCEDURE sp_helpconstraint
@objname varchar(767) = NULL,		/* table to report constraints on */
@propt   varchar(10) = "terse"	/* print option :
				** "detail" - full print
				** not supplied or otherwise - terse print
				*/
AS

DECLARE @indid int			/* the index id of an index */
DECLARE @keys varchar(1024)		/* string to build up index key in */
DECLARE @inddesc varchar(1065)		/* string to build up index desc in */
DECLARE @clust int, @nonclust int	/* flag if clust/non-clust index*/
DECLARE @msg varchar(1024)
DECLARE @stridx int			/* Index of * */
DECLARE @colcnt int
DECLARE @indstat   int			/* status of sysindexes  */
DECLARE @indstat2  int			/* status2 of sysindexes */
DECLARE @pmytabid  int			/* flag/id of referencing table */
DECLARE @cnstrname varchar(255)
DECLARE @foreign_keys varchar(512)
DECLARE @refrncd_keys varchar(512)
DECLARE @frgntab varchar(287), @pmrytab varchar(287)
DECLARE @matchtype varchar(11)		/* Match type of RI */
DECLARE @type char(2)			/* Object type */

/* Declarations for sysreferences table cursor fetch */
DECLARE @indexid int, @constrid int, @tableid int, @reftabid int, @keycnt int
DECLARE @fokey1 int,  @fokey2 int,  @fokey3 int,  @fokey4 int,  @fokey5  int
DECLARE @fokey6 int,  @fokey7 int,  @fokey8 int,  @fokey9 int,  @fokey10 int
DECLARE @fokey11 int, @fokey12 int, @fokey13 int, @fokey14 int, @fokey15 int
DECLARE @refkey1 int, @refkey2 int, @refkey3 int, @refkey4 int, @refkey5  int
DECLARE @refkey6 int, @refkey7 int, @refkey8 int, @refkey9 int, @refkey10 int
DECLARE @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
DECLARE @refkey15 int, @refkey16 int, @fokey16 int, @status int
DECLARE @frgndbid int, @pmrydbid int
DECLARE @frgndbname varchar(30), @pmrydbname varchar(30)
/* Declarations for counts */
DECLARE @total_ref int, @refing int, @ref int, @self_ref int
DECLARE @ref_word varchar(30)
IF @@trancount = 0
BEGIN
	SET chained off
END

SET transaction isolation level 1

if @objname is NULL
BEGIN
	select obj.id, obj.name, Num_referential_constraints =
		(select count(*) from sysreferences 
			where reftabid = obj.id and pmrydbname is NULL)
		+
		(select count(*) from sysreferences 
			where tableid = obj.id and frgndbname is NULL 
			and not (reftabid = obj.id and pmrydbname is NULL))
	
	from sysobjects obj
	where ( obj.sysstat2 & 3  != 0 ) and ( obj.type = "U" )
	order by Num_referential_constraints desc
	return (0)
END
/*
**  Check to see that the object names are local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
BEGIN
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
END

/*
**  Check to see the the table exists and in the same scan, find if
**  the table has any check constraints/foreign-key constraints, or
**  is being referenced by other tables.
*/
SELECT  @colcnt = 0
SELECT  @colcnt = id,			/* Flag for row in sysobjects found */
	@clust    = (sysstat  & 16),	/* Flag for clustered index */
        @nonclust = (sysstat  & 32),	/* Flag for non-clustered index */
        @constrid = ckfirst,		/* Flag for table check constraint */
	@keycnt   = (sysstat2 & 4),	/* Flag for > 1 table check constr */
	@pmytabid = (sysstat2 & 2),	/* Flag for foreign key constraint */
	@reftabid = (sysstat2 & 1),	/* Flag for referenced table constr*/
	@type	  = type		/* Object type indicator */
FROM sysobjects
WHERE id = object_id(@objname) 

/*
**  If table doesn't exist, return.
*/
IF (@colcnt = 0)
BEGIN
	/* 17461, "Object does not exist in this database." */
	raiserror 17461, @objname
	return (1)
END

/*
** If the object is not a table, return.
*/
IF (@type not in ('S','U'))
BEGIN
	/* 17761, "Object is not a table." */     
	raiserror 17761, @objname                 
	return (1)                                
END                                               

/*    Get number of columns in this table. */
SELECT @colcnt = count(*)
FROM syscolumns
WHERE id = object_id(@objname)

/*    Check if no columns have any constraints or default */
IF (@colcnt = (SELECT count(*)
	       FROM syscolumns
	       WHERE id = object_id(@objname)
		   AND domain = 0	/* No column check constraint */
		   AND cdefault = 0))	/* No defaults */
BEGIN
	SELECT @colcnt = 0
END

/*
**  If no constraints on this table, return.
*/
IF (@clust = 0			/* No clustered index */
    AND @nonclust = 0		/* No non-clustered index */
    AND @constrid = 0		/* No table check constraints */
    AND @pmytabid = 0		/* No foreign key constraints */
    AND @reftabid = 0		/* No references to this table */
    AND @colcnt   = 0)		/* No column default or check constraints */
BEGIN
	/* 18024, "Object does not have any constraints." */
	raiserror 18024
	RETURN (1)
END

/*
** Template for the table we will output.
**	    id   : this may not be useful?
**	    ermsg: message number assigned by user for this constraint
**	    name : this will contain name as given by user or system
**	    colno: number of columns involved in constraint
**	    type : one of (reference constraint, check constraint)
**	    msg  : one of (user defined, system standard)
**	    text : actual text of this constraint	    
** save the info in a temporary table that we'll print out at the end.
** Note that the row length of the table could go beyond the allowed row
** length for a 2K page server if we store the complete message and also
** keep enough space for the constraint description. 
** Hence we will store/display only 500 bytes of the constraint message.
*/
CREATE TABLE #spconstrtab (
       constraint_id	int,
       constraint_name	varchar(255),
       constraint_colno int,
       constraint_ermsg int,
       constraint_type	varchar(25),
       constraint_msg	varchar(500) null,
       constraint_desc	varchar(1065) null, 
       constraint_created datetime null) lock allpages

/*
**  Check if the object has any defaults
*/
IF (@colcnt > 0)
BEGIN
INSERT INTO #spconstrtab
       SELECT	o.id, o.name, 1, 0,
		"default value",
		NULL,
		m.text, NULL
       FROM syscolumns c, sysobjects o, syscomments m
       WHERE c.id = object_id(@objname)
	     AND c.cdefault = o.id
	     AND o.id = m.id
END

/*
**  See if the object has any check constraints
**  There may be more than one entry in sysconstraints for the object.
**  Note :  We only handle 1 line of text, need to improve for more lines.
*/
IF (@colcnt > 0 OR @constrid > 0)
BEGIN
INSERT INTO #spconstrtab
       SELECT	o.id, o.name, 1, c.error,
		"check constraint",
		"standard system error message number : 548",
		m.text, NULL
       FROM sysconstraints c, sysobjects o, syscomments m
       WHERE c.tableid = object_id(@objname)
	     AND c.constrid = o.id
	     AND o.id = m.id
	     AND (o.sysstat & 15 = 7)
END

/*
**  Now we search for UNIQUE and PRIMARY KEY (only declarative) constraints
*/
DECLARE curs_sysindexes
CURSOR FOR
	SELECT keycnt, indid, status, status2
	FROM   sysindexes
	WHERE  id = object_id(@objname)
	       AND indid > 0
	       AND status2 & 2 = 2
FOR READ ONLY

OPEN curs_sysindexes

FETCH curs_sysindexes
INTO  @keycnt, @indexid, @indstat, @indstat2

WHILE (@@sqlstatus = 0)
BEGIN
	/*
	**  First we'll figure out what the keys are.
	*/
	DECLARE @i int
	DECLARE @thiskey varchar(255)

	SELECT @keys = "", @i = 1

	SET NOCOUNT ON

	WHILE @i <= @keycnt
	BEGIN
		SELECT @thiskey = index_col(@objname, @indexid, @i)

		IF @thiskey IS NULL
		BEGIN
			GOTO keysdone
		END

		IF @i > 1
		BEGIN
			SELECT @keys = @keys + ", "
		END
			
		SELECT @keys = @keys + convert(varchar(30), index_col(@objname, @indexid, @i))

		/*
		**  Increment @i so it will check for the next key.
		*/
		SELECT @i = @i + 1

	END

	/*
	**  When we get here we now have all the keys.
	*/
	keysdone:
		SET NOCOUNT OFF

	/*
	** Check if we have a PRIMARY KEY constraint or a UNIQUE constraint
	** Note that we are only dealing with declarative indexes
	*/
	IF (@indstat & 2048 = 2048)
	BEGIN
		SELECT @inddesc = "PRIMARY KEY "
	END
	ELSE
	BEGIN
		SELECT @inddesc = "UNIQUE "
	END

	/*
	**  Get the keys involved in the declarative constraint
	*/
	SELECT @inddesc = @inddesc + "INDEX (" + @keys + ")"

	/*
	**  clustered or nonclustered index
	**  Note that the system by default creates an index
	*/
	IF @indexid = 1
	BEGIN
		SELECT @inddesc = @inddesc + " : CLUSTERED"
	END
	IF @indexid > 1
	BEGIN
		IF (@indstat2 & 512 = 512)
		BEGIN
			/* clustered index on data only locked table */
			SELECT @inddesc = @inddesc + " : CLUSTERED"
		END
		ELSE
		BEGIN
			SELECT @inddesc = @inddesc + " : NONCLUSTERED"
		END
	END

	/*
	**  Display if this key is referenced by other table
	*/
	IF (@indstat2 & 1 = 1)
	BEGIN
		SELECT @inddesc = @inddesc + ", FOREIGN REFERENCE"
	END

	/*
	**  Now we have the whole description for the index so we'll
	**  add the goods to the temporary table.
	*/
	INSERT INTO #spconstrtab
	       SELECT indid, name, @i - 1, 0,
		      "unique constraint",
		      "standard system error message number : 2601",
		      @inddesc, crdate
	       FROM sysindexes i
	       WHERE id = object_id(@objname)
		   AND indid = @indexid

FETCH curs_sysindexes
INTO  @keycnt, @indexid, @indstat, @indstat2

END

CLOSE curs_sysindexes

/*
** Now we obtain the referential dependency information
** The search for matching tableid or reftabid applies to objects in
** this database only (null frgndbname/pmrydbname tells us).
*/
DECLARE curs_sysreferences
CURSOR FOR
       SELECT constrid, tableid, reftabid, keycnt, status, frgndbid, pmrydbid,
       	      fokey1, fokey2, fokey3, fokey4, fokey5, fokey6,
	      fokey7, fokey8, fokey9, fokey10, fokey11, fokey12,
	      fokey13, fokey14, fokey15, fokey16,
	      refkey1, refkey2, refkey3, refkey4, refkey5, refkey6,
	      refkey7, refkey8, refkey9, refkey10, refkey11, refkey12,
	      refkey13, refkey14, refkey15, refkey16,
	      frgndbname, pmrydbname
       FROM   sysreferences
       WHERE  (tableid  = object_id(@objname)
               AND (frgndbname is NULL
                    OR db_id(frgndbname) = db_id()))
          OR  (reftabid = object_id(@objname)
               AND (pmrydbname is NULL
                    OR db_id(pmrydbname) = db_id()))

FOR READ ONLY

OPEN curs_sysreferences

FETCH curs_sysreferences
INTO @constrid, @tableid, @reftabid, @keycnt, @status, @frgndbid, @pmrydbid,
     @fokey1, @fokey2, @fokey3, @fokey4, @fokey5, @fokey6,
     @fokey7, @fokey8, @fokey9, @fokey10, @fokey11, @fokey12,
     @fokey13, @fokey14, @fokey15, @fokey16,
     @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6,
     @refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12,
     @refkey13, @refkey14, @refkey15, @refkey16,
     @frgndbname, @pmrydbname

/*
** Initialize the count first. 
*/
SELECT @total_ref = 0
SELECT @refing = 0
SELECT @ref = 0
SELECT @self_ref = 0

WHILE (@@sqlstatus = 0)
BEGIN

/*
** Set the Database id's from the Database names
*/
SELECT @pmrydbid = db_id()
SELECT @frgndbid = db_id()
IF @frgndbname is not NULL
	SELECT @frgndbid = db_id(@frgndbname)
IF @pmrydbname is not NULL
	SELECT @pmrydbid = db_id(@pmrydbname)

/*
**   Check if either primary or dependent dbids are from this database.
**   If both are not, that means we have an invalid entry here.
**   Otherwise prefix the database name to the tablename.
**   Only look up table names if dbid is non-null (i.e., database exists),
**   otherwise object_name will default to current database.
*/
SELECT  @pmrytab = "*"
SELECT  @frgntab = "*"
IF @pmrydbid is not NULL
	SELECT  @pmrytab = object_name(@reftabid, @pmrydbid)
IF @frgndbid is not NULL
	SELECT  @frgntab = object_name(@tableid,  @frgndbid)

/*
** Need to enhance this ...
*/
IF @frgndbid != db_id()
BEGIN
	SELECT @frgntab = @frgndbname + ".." + @frgntab
END
ELSE
BEGIN
	IF @pmrydbid != db_id()
		SELECT @pmrytab = @pmrydbname + ".." + @pmrytab
END

/* 
** Accumulate the count here.
*/

IF ((@frgndbname is NULL ) OR (@pmrydbname is NULL))
BEGIN

	SELECT @ref_word = ") REFERENCES "

	IF  (@tableid = object_id(@objname) AND @frgndbname is NULL)
	BEGIN
		SELECT @refing = @refing + 1
	END

	IF  (@reftabid = object_id(@objname) AND @pmrydbname is NULL)
	BEGIN
		SELECT @ref = @ref + 1
	END

	/* Is it a self_referencing entry?*/
	IF ( (@reftabid = @tableid)  AND (@frgndbname is NULL) AND 
			(@pmrydbname is NULL) )
	BEGIN
		SELECT @self_ref = @self_ref + 1
		SELECT @ref_word = ") SELF REFERENCES "
	END
END

SELECT @foreign_keys = isnull(convert(varchar(30), col_name(@tableid, @fokey1 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey2 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey3 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey4 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey5 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey6 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey7 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey8 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey9 , @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey10, @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey11, @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey12, @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey13, @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey14, @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey15, @frgndbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@tableid, @fokey16, @frgndbid)), "*")

SELECT  @refrncd_keys = isnull(convert(varchar(30), col_name(@reftabid, @refkey1 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey2 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey3 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey4 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey5 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey6 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey7 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey8 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey9 , @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey10, @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey11, @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey12, @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey13, @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey14, @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey15, @pmrydbid)), "*") + ", "
	+ isnull(convert(varchar(30), col_name(@reftabid, @refkey16, @pmrydbid)), "*")

/* trim the list of key-columns */
SELECT @stridx = patindex("%, *%", @foreign_keys) 
IF @stridx > 0
BEGIN
	SELECT @foreign_keys = substring(@foreign_keys, 1, @stridx - 1)
END
 
SELECT @stridx = patindex("%, *%", @refrncd_keys) 
IF @stridx > 0
BEGIN
	SELECT @refrncd_keys = substring(@refrncd_keys, 1, @stridx - 1)
END
 
SELECT @cnstrname = isnull(object_name(@constrid, @frgndbid), "*")

/*
**  Display if match type of this foreign key constraint is full
*/
IF (@status & 2 = 2)
BEGIN
	SELECT @matchtype = " MATCH FULL"
END
ELSE
BEGIN
	SELECT @matchtype = NULL
END

IF db_id() = @frgndbid
BEGIN
       INSERT INTO #spconstrtab
	      SELECT  @constrid, @cnstrname, @keycnt, c.error,
		      "referential constraint",
		      "standard system error message number : 547",
		      @frgntab + " FOREIGN KEY (" + @foreign_keys +
		      @ref_word + @pmrytab + "(" + @refrncd_keys + ")" +
		      @matchtype,
		      NULL
	      FROM sysconstraints c
	      WHERE c.constrid = @constrid
END
ELSE
BEGIN
       INSERT INTO #spconstrtab
	      SELECT  @constrid, @cnstrname, @keycnt, 0,
		      "referential constraint",
		      "standard system error message number : 547",
		      @frgntab + " FOREIGN KEY (" + @foreign_keys +
		      @ref_word + @pmrytab + "(" + @refrncd_keys + ")" +
		      @matchtype,
		      NULL
END

FETCH curs_sysreferences
INTO @constrid, @tableid, @reftabid, @keycnt, @status, @frgndbid, @pmrydbid,
     @fokey1, @fokey2, @fokey3, @fokey4, @fokey5, @fokey6,
     @fokey7, @fokey8, @fokey9, @fokey10, @fokey11, @fokey12,
     @fokey13, @fokey14, @fokey15, @fokey16,
     @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6,
     @refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12,
     @refkey13, @refkey14, @refkey15, @refkey16,
     @frgndbname, @pmrydbname

END

CLOSE curs_sysreferences

/*
**	Now we setup the error message, if user defined.
** 
**      constraint_msg and constraing_desc together can not be stored 
**	for a 2K server, so the description will be truncated to 
**	500 bytes. 
*/
UPDATE #spconstrtab
SET constraint_msg = u.description
FROM sysusermessages u, #spconstrtab c
WHERE c.constraint_ermsg >= 20000
      AND u.error = c.constraint_ermsg

/* 
**  Update constraint_created with crdate from sysobjects 
*/

UPDATE #spconstrtab
SET constraint_created = crdate
FROM sysobjects o, #spconstrtab c
WHERE c.constraint_id = o.id
AND c.constraint_created is null

/*
**	Now prettyprint the results
*/

/*
**	First check if #spconstrtab is empty
*/

IF not exists (SELECT * FROM #spconstrtab) 
BEGIN
	/* 18024, "Object does not have declarative constraints." */
        exec sp_getmessage 18024, @msg output
        print @msg
	RETURN (1)
END
IF @propt NOT LIKE "detail%"
BEGIN
	DECLARE @len1 int, @len2 int, @len3 int

	SELECT @len1 = max(datalength(constraint_name)) FROM #spconstrtab
	SELECT @len2 = max(datalength(constraint_desc)) FROM #spconstrtab

	IF (@len1 < 15 and @len2 < 60)
	BEGIN
		SELECT
			name = convert(char(15), constraint_name),
			definition = convert(char(60), constraint_desc),
			created = convert(char(19), constraint_created, 100)
		FROM #spconstrtab
		ORDER BY constraint_type
	END
	ELSE IF (@len2 < 60)
	BEGIN
		SELECT
			name = constraint_name,
			definition = convert(char(60), constraint_desc),
			created = convert(char(19), constraint_created, 100)
		FROM #spconstrtab
		ORDER BY constraint_type
	END
	ELSE
	BEGIN
		select
			'name' = constraint_name,
			'definition' = constraint_desc,
			'created' = convert(char(19), constraint_created, 100),
			constraint_type
		into #spconstrtab_1
		from #spconstrtab

		exec sp_autoformat @fulltabname = #spconstrtab_1,
			@selectlist = "name, definition, created",
			@orderby = "order by constraint_type"
		drop table #spconstrtab_1
	END
END
/* Show all details - pretty printing is not required for this perhaps ? */
ELSE
BEGIN
	SELECT @len1 = max(datalength(constraint_name)) FROM #spconstrtab
	SELECT @len2 = max(datalength(constraint_msg )) FROM #spconstrtab
	SELECT @len3 = max(datalength(constraint_desc)) FROM #spconstrtab

	IF (@len1 < 15 and @len3 < 60)
	BEGIN
		SELECT	name = convert(char(15), constraint_name),
			definition = convert(char(60), constraint_desc),
			created = convert(char(19), constraint_created, 100),
			msg  = constraint_msg
		FROM #spconstrtab
		ORDER BY constraint_type
	END
	ELSE
	BEGIN
		select 'name' = constraint_name,
			'type' = constraint_type,
			'definition' = constraint_desc,
			'created' = convert(char(19), constraint_created, 100),
			'msg'  = constraint_msg
		into #spconstrtab_2
		from #spconstrtab

		exec sp_autoformat @fulltabname = #spconstrtab_2,
			@orderby = "order by type"
		drop table #spconstrtab_2
	END
END

SELECT  @total_ref = @refing + @ref - @self_ref
IF (@total_ref > 0)
BEGIN
	PRINT	" "
        EXEC sp_getmessage 18243, @msg out
	PRINT @msg, @total_ref
	PRINT	" "
	EXEC sp_getmessage 18449, @msg out
	PRINT @msg
        EXEC sp_getmessage 18244, @msg out
        PRINT @msg, @refing
        EXEC sp_getmessage 18245, @msg out
        PRINT @msg, @ref
        EXEC sp_getmessage 18246, @msg out
        PRINT @msg, @self_ref
	PRINT	" "
        EXEC sp_getmessage 18247, @msg out
        PRINT @msg
	EXEC sp_getmessage 18450, @msg out
	PRINT @msg
	EXEC sp_getmessage 18451, @msg out
	PRINT @msg
	EXEC sp_getmessage 18452, @msg out
	PRINT @msg
	EXEC sp_getmessage 18453, @msg out
	PRINT @msg
END
RETURN (0)
go
exec sp_procxmode 'sp_helpconstraint', 'anymode'
go
grant execute on sp_helpconstraint to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpdb')
begin
	drop procedure sp_helpdb
end
go
print "Installing sp_helpdb"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helpdb"             17590
**
** 17111, "log only"
** 17590, "The specified database does not exist."
** 17591, "no options set"
** 17592, " -- unused by any segments --"
** 17714, "not applicable"
** 17600, "sp_helpdb: order value '%1!' is not valid. Valid values are 
**	'lstart' and 'device_name'. Using default value 'lstart'."
** 17609, "Device allocation is not displayed for local temporary 
**	   database '%1!'. To display this information, execute the 
**	   procedure on the owner instance '%2!'."
*/
create procedure sp_helpdb
@dbname varchar(255) = NULL,			/* database name to change */
@order	varchar(20) = 'lstart'			/* Use 'device_name' to order
						** by device name
						*/
as

declare @showdev	int
declare @showinstance	int
declare @allopts	int
declare @all2opts	int
declare @all3opts	int
declare @all4opts	int
declare @dbstatus4	int
declare @thisopt	int
declare @optmask	int
declare @template_mask	int
declare @imdb_mask	int
declare @has_template_mask	int
declare @local_tempdb_mask	int
declare @pagekb		int
declare @msg 		varchar(1024)
declare @sptlang	int
declare @na_phrase	varchar(30)	/* length of German */
declare @sqlbuf		varchar(1024)
declare @len1 int, @len2 int, @len3 int
declare @q		char(1)		/* quote sign */
declare @instancename	varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	    select @sptlang = 0
	else
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17110 and 17119
		and langid = @@langid)
	    select @sptlang = 0
end

set nocount on

/*
**  If no database name given, get 'em all.  Otherwise, count how many
**  databases match the specified name.
*/
if @dbname is null
	select @dbname = "%",
	       @showdev = count(*) from master.dbo.sysdatabases
else
	select @showdev = count(*)
			   from master.dbo.sysdatabases
			   where name like @dbname

/*
**  Sure the database exists
*/
if @showdev = 0
begin
	/* 17590, "The specified database does not exist." */
	raiserror 17590
	return (1)
end

/*
**  Set allopts to be the sum of all possible user-settable database status
**  bits.  (Note that there are 2 groups of such bits.)  If we can't get
**  the option mask from spt_values, guess at the correct value.
*/
select @allopts = number
from master.dbo.spt_values
where	type = "D"
  and	name = "ALL SETTABLE OPTIONS"
if (@allopts is NULL)
	select @allopts = 4 | 8 | 16 | 512 | 1024 | 2048 | 4096 | 8192

select @all2opts = number
from master.dbo.spt_values
where	type = "D2"
  and	name = "ALL SETTABLE OPTIONS"
if (@all2opts is NULL)
	select @all2opts = 1 | 2 | 4 | 8 | 64

select @all3opts = number
from master.dbo.spt_values
where	type = "D3"
  and	name = "ALL SETTABLE OPTIONS"
if (@all3opts is NULL)
	select @all3opts = 0

select @all4opts = number
from master.dbo.spt_values
where	type = "D4"
  and	name = "ALL SETTABLE OPTIONS"
if (@all4opts is NULL)
	select @all4opts = 0

/*
** @allopts (sysdatabases.status options) should also contain some
** NON-settable options that we want to check for:
**	 32 = "don't recover"
**	256 = "not recovered"
*/
select @allopts = @allopts | 32 | 256

/*
** @all2opts (sysdatabases.status2 options) should also contain a
** NON-settable option that we want to check for:
**	 16 = "offline"
**	128 = "has suspect objects"
**     1024 = "online for standby access"
**    32768 = "mixed log and data" 
*/
select @all2opts = @all2opts | 16 | 128 | 1024 | 32768

/*
** @all3opts (sysdatabases.statu3 options) should also contain 
** NON-settable options that we want to check for:
**
**	0128 = "quiesce database"
**	
**	if SMP
**		256 = "user created temp db"
**	if SDC
**	        256 = "local user temp db"
**		536870912 = "local system tempdb"
**		1073741824 = "global user tempdb"
**
**	1024 = "async log service"
**	2048 = "delayed commit"
**   4194304 = "archive database"
**   8388608 = "compressed data"
** 134217728 = "compressed log"
*/
select @all3opts = @all3opts | 128 | 256 | 1024 | 2048 | 4194304 | 8388608 | 134217728
if @@clustermode = "shared disk cluster"
begin
	select @all3opts = 
		@all3opts | 536870912 | 1073741824
	select @local_tempdb_mask = number
		from master.dbo.spt_values
		where   type = "D3" and name = "LOCAL TEMPDB STATUS MASK"
end
else
begin
	select @local_tempdb_mask = 0 
end

/*
** @all4opts (sysdatabases.status4 options) should also contain 
** NON-settable options that we want to check for:
**
**	4096 = "in-memory database"
**	512  = "has template"
**	1024 = "is template database"
**	
*/
select 	@all4opts = @all4opts | 256 | 1024 | 4096,
	@has_template_mask = 512,
	@template_mask = 1024,
	@imdb_mask = 4096

/*
**  Since we examine the status bits in sysdatabase and turn them
**  into english, we need a temporary table to build the descriptions.
*/
create table #spdbdesc
(
	dbid	smallint null,
	dbdesc	varchar(777) null
)

/*
**  Initialize #spdbdesc from sysdatabases
*/
insert into #spdbdesc (dbid)
		select dbid 
			from master.dbo.sysdatabases
				where name like @dbname
/*
**  Now for each dbid in #spdbdesc, build the database status
**  description.
*/
declare @curdbid smallint		/* the one we're currently working on */
declare @dbdesc varchar(777)		/* the total description for the db */
declare @bitdesc varchar(30)		/* the bit description for the db */

/* For regular databases, we don't need to show the owner instances. */
select @showinstance = 0

/*
**  Set @curdbid to the first dbid.
*/
select @curdbid = min(dbid)
	from #spdbdesc
while @curdbid is not NULL
begin
	/*
	**  Initialize @dbdesc.
	*/
	select @dbdesc = ""

	/*
	**  Check status options (spt_values.type = "D")
	*/
	select @thisopt = 1
	select @optmask = @allopts	/* status options */
	while (@optmask != 0)		/* until all set options noted ... */
	begin
		/*
		** If this option is user-settable, check for it
		*/
		if (@optmask & @thisopt = @thisopt)
		begin
			select @bitdesc = null

			select @bitdesc = m.description
			from master.dbo.spt_values v,
			     master.dbo.sysdatabases d,
			     master.dbo.sysmessages m
			where d.dbid = @curdbid
				and v.type = "D"
				and d.status & v.number = @thisopt
				and v.number = @thisopt
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
			if @bitdesc is not null
			begin
				if @dbdesc != ""
					select @dbdesc = @dbdesc + ", " +  @bitdesc
				else select @dbdesc = @bitdesc
			end

			/* Turn off this status bit in the options mask */
			select @optmask = @optmask & ~(@thisopt)
		end

		/*
		** Get the next option bit.  Check for integer overflow for
		** bit 31 (0x80000000).
		*/
		if (@thisopt < 1073741824)
			select @thisopt = @thisopt * 2
		else
			select @thisopt = -2147483648
	end

	/*
	**  Check status2 options (spt_values.type = "D2")
	*/
	select @thisopt = 1
	select @optmask = @all2opts	/* status2 options */
	while (@optmask != 0)		/* until all set options noted ... */
	begin
		/*
		** If this option is user-settable, check for it
		*/
		if (@optmask & @thisopt = @thisopt)
		begin
			select @bitdesc = null

			select @bitdesc = m.description
			from master.dbo.spt_values v,
			     master.dbo.sysdatabases d,
			     master.dbo.sysmessages m
			where d.dbid = @curdbid
				and v.type = "D2"
				and d.status2 & v.number = @thisopt
				and v.number = @thisopt
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
			if @bitdesc is not null
			begin
				if @dbdesc != ""
					select @dbdesc = @dbdesc + ", " +  @bitdesc
				else select @dbdesc = @bitdesc
			end

			/* Turn off this status bit in the options mask */
			select @optmask = @optmask & ~(@thisopt)
		end

		/*
		** Get the next option bit.  Check for integer overflow for
		** bit 31 (0x80000000).
		*/
		if (@thisopt < 1073741824)
			select @thisopt = @thisopt * 2
		else
			select @thisopt = -2147483648
	end

	/*
	**  Check status3 options (spt_values.type = "D3")
	*/
	select @thisopt = 1
	select @optmask = @all3opts	/* status3 options */
	while (@optmask != 0)		/* until all set options noted ... */
	begin
		/*
		** If this option is user-settable, check for it
		*/
		if (@optmask & @thisopt = @thisopt)
		begin
			select @bitdesc = null

			select @bitdesc = m.description
			from master.dbo.spt_values v,
			     master.dbo.sysdatabases d,
			     master.dbo.sysmessages m
			where d.dbid = @curdbid
				and v.type = "D3"
				and d.status3 & v.number = @thisopt
				and v.number = @thisopt
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
			if @bitdesc is not null
			begin
				if @dbdesc != ""
					select @dbdesc = @dbdesc + ", " +  @bitdesc
				else select @dbdesc = @bitdesc

				if (@thisopt & @local_tempdb_mask = @thisopt)
					select @showinstance = 1
			end

			/* Turn off this status bit in the options mask */
			select @optmask = @optmask & ~(@thisopt)
		end

		/*
		** Get the next option bit.  Check for integer overflow for
		** bit 31 (0x80000000).
		*/
		if (@thisopt < 1073741824)
			select @thisopt = @thisopt * 2
		else
			select @thisopt = -2147483648
	end

	/*
	**  Check status4 options (spt_values.type = "D4")
	*/
	select @thisopt = 1
	select @optmask = @all4opts	/* status4 options */
	while (@optmask != 0)		/* until all set options noted ... */
	begin
		/*
		** If this option is user-settable, check for it
		*/
		if (@optmask & @thisopt = @thisopt)
		begin
			select @bitdesc = null

			select @bitdesc = m.description
			from master.dbo.spt_values v,
			     master.dbo.sysdatabases d,
			     master.dbo.sysmessages m
			where d.dbid = @curdbid
				and v.type = "D4"
				and d.status4 & v.number = @thisopt
				and v.number = @thisopt
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
			if @bitdesc is not null
			begin
				if @dbdesc != ""
					select @dbdesc = @dbdesc + ", " +  @bitdesc
				else select @dbdesc = @bitdesc
			end

			/* Turn off this status bit in the options mask */
			select @optmask = @optmask & ~(@thisopt)
		end

		/*
		** Get the next option bit.  Check for integer overflow for
		** bit 31 (0x80000000).
		*/
		if (@thisopt < 1073741824)
			select @thisopt = @thisopt * 2
		else
			select @thisopt = -2147483648
	end

	/*
	**  If no flags are set, say so.
	*/
	if @dbdesc = ""
	begin
		/* 17591, "no options set" */
		exec sp_getmessage 17591, @dbdesc out
	end

	/*
	**  Save the description.
	*/
	update #spdbdesc
		set dbdesc = @dbdesc
			from #spdbdesc
				where dbid = @curdbid

	/*
	**  Now get the next, if any dbid.
	*/
	select @curdbid = min(dbid)
		from #spdbdesc
			where dbid > @curdbid
end 
	
/* 
** Get the rows of interest from sysusages into a temp table.  This is to
** avoid deadlocking with create table, which could happen if we directly
** join sysdatabases and sysusages.
*/

select u.dbid, u.segmap, u.lstart, u.size, u.vdevno, u.unreservedpgs, u.crdate
	into #spdbusages
	from #spdbdesc, master.dbo.sysusages u
	where #spdbdesc.dbid = u.dbid

/*	
** Compute number of Pages in a Megabyte.
*/
declare @numpgsmb 	float		/* Number of Pages per Megabyte */

select @numpgsmb = (1048576. / v.low)
	from master.dbo.spt_values v
		 where v.number = 1
		 and v.type = "E"	

/*
**  Now #spdbdesc is complete so we can print out the db info
*/

	select distinct name = d.name,
		db_size = str(sum(u.size) / @numpgsmb, 10, 1)
			+ " MB",
		owner = l.name,
		dbid = d.dbid,
		created = convert(char(18), d.crdate, 107),
		durability = db_attr(d.dbid, 'durability'),
		status = #spdbdesc.dbdesc

	into #sphelpdb1rs
			from master.dbo.sysdatabases d, master.dbo.syslogins l,
				 #spdbusages u, #spdbdesc
		where d.dbid = #spdbdesc.dbid
			and d.suid = l.suid
			and #spdbdesc.dbid = u.dbid
		group by #spdbdesc.dbid
		having d.dbid = #spdbdesc.dbid
			and d.suid = l.suid
			and #spdbdesc.dbid = u.dbid


/* Print the owner instance name only if the database name is specified
** and the database is a local tempdb (@showinstance = 1)
*/

	exec sp_autoformat @fulltabname = #sphelpdb1rs,
		@selectlist = "name, db_size, owner, dbid, created, durability, status",
		@orderby = "order by 1"


/*  
** Print sysattributes data if there is any.  The join with multiple
** instances of sysattributes is to get the string descriptions for
** the class (master..sysattributes cn) and the attribute
** (master..sysattributes an). These should never be longer than
** 30 characters, so it's okay to truncate them.
*/

select name = db.name, attribute_class = cn.char_value, 
	attribute = an.char_value, a.int_value, 
	a.char_value, a.comments, class = a.class, attribute_id = a.attribute
into #spdbattr
from master.dbo.sysdatabases db, #spdbdesc d,
	master.dbo.sysattributes a, master.dbo.sysattributes an,
	master.dbo.sysattributes cn
where db.dbid = d.dbid
and a.class = cn.object
and a.attribute = an.object_info1
and a.class = an.object
and a.object_type = "D"
and a.object = d.dbid
and cn.class = 0
and cn.attribute = 0
and an.class = 0
and an.attribute = 1
and a.object = db.dbid

/*
** It's possible a cache is deleted without doing an unbind first. After
** a server reboot the binding is marked 'invalid' (int_value = 0).
** If we have such an invalid binding, don't show it in the output.
*/
delete from #spdbattr
where class = 3
and attribute_id = 0
and int_value = 0

if exists (select * from #spdbattr)
begin
	exec sp_autoformat  @fulltabname = #spdbattr,
		@selectlist = "name, attribute_class, attribute, int_value,char_value,comments"
end



if @showdev = 1 
begin
	select @curdbid = dbid			/* database ID */
		from master.dbo.sysdatabases
		where name like @dbname
	select @pagekb = (low / 1024)		/* kbytes per page */
		from master.dbo.spt_values
		where number = 1
		  and type = 'E'

	/* 17714, "not applicable" */
	select @na_phrase = description
		from master.dbo.sysmessages 
		where error = 17714
		  and isnull(langid, 0) = @sptlang

	/* Check the length of the usage column */
	select distinct @len3 = max(datalength(m.description))
	    from master.dbo.sysdatabases d, #spdbusages u, master.dbo.sysdevices v, 
			master.dbo.spt_values b, master.dbo.sysmessages m
		where d.dbid = u.dbid
			and u.vdevno = v.vdevno
			and ((v.status & 2 = 2)  or (v.status2 & 8 = 8))
			and d.name like @dbname
			and b.type = "S"
			and u.segmap & 7 = b.number
			and b.msgnum = m.error
			and isnull(m.langid, 0) = @sptlang

	/*
	** Order the device fragments output by sysusages.lstart unless
	** the 2nd parameter of sp_helpdb is "device_name"
	*/
	if (@order = "device_name")
	begin
		select @order = "v.name"
	end
	else
	begin
		if (@order != "lstart")
		begin
			/*
			** 17600, "sp_helpdb: order value '%1!' is not valid. 
			** Valid values are 'lstart' and 'device_name'. 
			** Using default value 'lstart'."
			*/
			raiserror 17600, @order
		end

		/* Fragment order same as order in create/alter database */
		select @order = "u.lstart"

	end

	if (@len3 < 20)
		select @len3 = 20

	select  @q = substring('''',1,1)

	select @sqlbuf = 
	    'select device_fragments = v.name, size =
			str(size / ' + str(@numpgsmb,10,1) + ', 10, 1) + '
			+ @q + ' MB' + @q + ',
		usage = convert(char('
			+ convert(varchar, @len3) + '), m.description),
		created = convert(char(25), u.crdate, 100),
		case
			when u.segmap = 4 then ' + @q + @na_phrase + @q
			+ ' else 
			str((curunreservedpgs(d.dbid, u.lstart,
				u.unreservedpgs) * ' 
				+ convert(varchar, @pagekb) + '), 16)
		end "free kbytes"
	    from master.dbo.sysdatabases d,
		 #spdbusages u,
		 master.dbo.sysdevices v,
		 master.dbo.spt_values b,
		 master.dbo.sysmessages m
		where d.dbid = u.dbid
			and u.vdevno = v.vdevno
			and ((v.status & 2 = 2)  or (v.status2 & 8 = 8))
			and d.name = '  +@q + @dbname + @q + '
			and b.type = ' + @q + 'S' + @q + '
			and u.segmap & 7 = b.number
			and b.msgnum = m.error
			and isnull(m.langid, 0) = ' 
				+ convert(varchar,@sptlang) +
	    ' order by ' + @order 

	exec (@sqlbuf)

	/* If log segment free space wasn't selected above, select it now. */
	if exists (select *
	    from master.dbo.sysdatabases d, master.dbo.sysusages u
		where d.name like @dbname
			and d.dbid = u.dbid
			and u.segmap = 4)
	begin
		/* 17111, "log only".  Length 17 is for French, the longest */
		select substring((select description
		    from master.dbo.sysmessages 
			where error = 17111
			   and isnull(langid, 0) = @sptlang), 1, 17)
		+ " " + "free kbytes" + " = "
		+ convert (char, (lct_admin("logsegment_freepages", @curdbid)
				- lct_admin("reserved_for_rollbacks", @curdbid))
				* @pagekb)
	end

	/*
	**  If there is only one database and we are in it, show the
	**  segments.
	*/
	if exists (select *
			from #spdbdesc
				where db_id() = dbid)
	begin
		declare @curdevice	varchar(255),
			@curseg		smallint,
			@segbit		int

		delete #spdbdesc

		select @curdevice = min(d.name)
			from  #spdbusages u, master.dbo.sysdevices d
				where u.dbid = db_id()
					and u.vdevno = d.vdevno
					and ((d.status & 2 = 2)  or (d.status2 & 8 = 8))
		while (@curdevice is not null)
		begin
			/*
			** We need an inner loop here to go through
			**  all the possible segment.
			*/
			select @curseg = min(segment)
					from syssegments
			while (@curseg is not null)
			begin
				if (@curseg < 31)
					select @segbit = power(2, @curseg)
				else select @segbit = low
					from master.dbo.spt_values
						where type = "E"
							and number = 2
				insert into #spdbdesc
					select @curseg, @curdevice
						from #spdbusages u,
							master.dbo.sysdevices d,
							master.dbo.spt_values v
					where u.segmap & @segbit = @segbit
						and u.vdevno = d.vdevno
						and u.dbid = db_id()
						and ((d.status & 2 = 2)  or (d.status2 & 8 = 8))
						and v.number = 1
						and v.type = "E"
						and d.name = @curdevice
				select @curseg = min(segment)
						from syssegments
							where segment > @curseg
			end

			select @curdevice = min(d.name)
				from  #spdbusages u,
					master.dbo.sysdevices d
				where u.dbid = db_id()
					and u.vdevno = d.vdevno
					and ((d.status & 2 = 2)  or (d.status2 & 8 = 8))
					and d.name > @curdevice
		end

		/*
		**  One last check for any devices that have no segments.
		*/
		insert into #spdbdesc
			select null, d.name
				from #spdbusages u,
					master.dbo.sysdevices d
			where u.segmap = 0
				and u.vdevno = d.vdevno
				and u.dbid = db_id()
				and ((d.status & 2 = 2)  or (d.status2 & 8 = 8))

		/* 17592, " -- unused by any segments --" */
		exec sp_getmessage 17592, @msg out

			select distinct device = dbdesc,
				segment = isnull(name, @msg)
			into #sphelpdb2rs
			from #spdbdesc, syssegments
				where dbid *= segment
			exec sp_autoformat @fulltabname = #sphelpdb2rs,
				@orderby = "order by 1, 2"
			drop table #sphelpdb2rs
	end

	/*
	** If the given database is a template database then
	** print all the database created from it.
	*/
	select @dbstatus4 = d.status4
		from master.dbo.sysdatabases d
		where name like @dbname

	/*
	** OMNI: Display the default location for remote tables
	**       if one exists.
	**
	** IMDB: In case of in-memory database def_remote_loc is
	** used to store the template database associated with the
	** in-memory database.
	*/
	if exists (select *
			from master.dbo.sysdatabases
				where name like @dbname 
				and def_remote_loc is not null)
	begin --{
		if ((@dbstatus4 & @has_template_mask) != 0)
		begin --{
			select "template_database" 
					= substring(def_remote_loc, 1, 30)
				from master.dbo.sysdatabases
					where name like @dbname
		end --}
		else
		begin --{
			select "remote location" = 
					substring(def_remote_loc, 1, 77)
				from master.dbo.sysdatabases
					where name like @dbname
		end --}
	end --}

	if ((@dbstatus4 & @template_mask) = @template_mask)
	begin --{
		select template_for = name 
		into #templateddbs
		from master.dbo.sysdatabases
		where def_remote_loc like @dbname
		
		exec sp_autoformat @fulltabname = #templateddbs
	end --}
end

drop table #spdbdesc
drop table #spdbattr
return (0)
go
exec sp_procxmode 'sp_helpdb', 'anymode'
go
grant execute on sp_helpdb to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpdevice')
begin
	drop procedure sp_helpdevice
end
go
print "Installing sp_helpdevice"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Generated by spgenmsgs.pl on Wed Nov 28 03:13:03 2007 
*/
/*
** raiserror Messages for generic/sproc/helpdevice [Total 1]
**
** 17610, "No such i/o device exists."
*/
/*
** sp_getmessage Messages for generic/sproc/helpdevice [Total 20]
**
** 17611, "special"
** 17612, "disk"
** 17613, "tape"
** 17614, "UNKNOWN DEVICE"
** 17615, "MIRROR ENABLED"
** 17616, "MIRROR DISABLED"
** 17617, "mirror ="
** 17618, "only device '%1!' of mirror is enabled -- device '%2!' is disabled"
** 17619, "channel"
** 17620, "nonserial writes"
** 17621, "dsync on"
** 17622, "dsync off"
** 17623, "directio on"
** 17624, "directio off"
** 17625, "raw device"
** 17626, "block device"
** 17627, "file system device"
** 17628, "unknown device type"
** 17629, "private"
** 17630, "REFIT PENDING"
** 17631, "virtual cache device"
*/
/*
** End spgenmsgs.pl output.
*/
go
create procedure sp_helpdevice
@devname varchar(255) = "%"		/* device to check out */
as

declare @tapeblocksize int

declare @msg varchar(1024)
declare @sptlang	int
declare @length		int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17120 and 17129
		and langid = @@langid)
	    select @sptlang = 0
end

/*
**  See if the device exists.
*/
if not exists (select *
			from master.dbo.sysdevices
				where name like @devname)
begin
	/* 17610, "No such i/o device exists." */
	raiserror 17610
	return (1)
end

/*
**  Create a temporary table where we can build up a translation of
**  the device status bits.
*/
create table #spdevtab
(
	dbdev_flag smallint,
	imdbdev_flag int,
	vpn_low int,
	vpn_high int,
	name varchar(255),
	vdevno int,
	statusdesc varchar(1024) null
)

set nocount on

/*
**  Initialize the temporary table with -
**  - names of the devices.
**  - null (no description yet)
**  - the device's low page number
**  - the device's high page number
**  - a flag stating whether this is a database device
*/
insert into #spdevtab (dbdev_flag, imdbdev_flag, vpn_low, 
				vpn_high, name, vdevno)
	select status & 2, status2 & 8, low, high, name, vdevno
	from master.dbo.sysdevices
	where name like @devname

/*
** Now figure out what kind of device it is
**    1 -  raw device
**    2 -  block device
**    3 -  file system device
*/

/* 17628, "unknown device type" */
exec sp_getmessage 17628,@msg out
update #spdevtab set statusdesc = @msg 

/* 17631, "virtual cache device" */
exec sp_getmessage 17631, @msg out
	update #spdevtab
	set statusdesc = @msg
		from master.dbo.sysdevices d, #spdevtab
		where d.status2 & 8 = 8
		and #spdevtab.name = d.name

/* 17625, "raw device" */
exec sp_getmessage 17625, @msg out
update #spdevtab
         set statusdesc = @msg
                 from master.dbo.sysdevices d, #spdevtab
                         where 1 in ( select getdevicetype(d.phyname) )
                                 and #spdevtab.name = d.name

/* 17626, "block device" */
exec sp_getmessage 17626, @msg out
update #spdevtab
        set statusdesc = @msg
                from master.dbo.sysdevices d, #spdevtab
                        where 2 in ( select getdevicetype(d.phyname) )
                                and #spdevtab.name = d.name

/* 17627, " file system device" */
exec sp_getmessage 17627, @msg out
update #spdevtab
        set statusdesc = @msg
                from master.dbo.sysdevices d, #spdevtab
                        where 3 in ( select getdevicetype(d.phyname) )
                                and #spdevtab.name = d.name 

/*
**  Now figure out what kind of controller type it is.  The type are
**  COMPLETELY machine dependent and are for UNIX.
**  cntrltype = 0	special
**	        2	disk
**	      3-8	tape
**	      9-14	channel
*/

/* 17611, "special" */
exec sp_getmessage 17611, @msg out
update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype = 0
				and #spdevtab.name = d.name

/* 17612, "disk" */
exec sp_getmessage 17612, @msg out
update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype = 2
				and #spdevtab.name = d.name

/* 17613, "tape" */
exec sp_getmessage 17613, @msg out
update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype >= 3 and d.cntrltype <= 8
				and #spdevtab.name = d.name
/* 17619, "channel" */
exec sp_getmessage 17619, @msg out
update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype >= 9 and d.cntrltype <= 14
				and #spdevtab.name = d.name

/*
**  If a tape device, also figure out the tape capacity which is listed
**  in sysdevices.high in number of 32k blocks.
*/
if exists (select *
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype >= 3 and d.cntrltype <= 8
				and d.high > 0
				and #spdevtab.name = d.name)
begin
        /*
        ** Find size of tape block.  Default to 32k.
        */

        select @tapeblocksize = low
                from master.dbo.spt_values
                        where type = "E"
                                and number = 4
        if @tapeblocksize is NULL
        begin
                select @tapeblocksize = 32768
        end

	update #spdevtab
		set statusdesc = statusdesc + ", " + str(round((d.high *
                                convert(float, @tapeblocksize)) / 1048576., 0))
			+ " MB"
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype >= 3 and d.cntrltype <= 8
				and d.high > 0
				and #spdevtab.name = d.name
end

/* 17614, "UNKNOWN DEVICE" */
exec sp_getmessage 17614, @msg out
update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.cntrltype > 14
				and #spdevtab.name = d.name



/*
**  Now check out the status bits and turn them into english.
**  The mirror status bits after masking with 16383 are >= 32.
**  The 0x3fff mask is necessary since ASE12.0 introduced a
**  new status bit 0x4000 to indicate the dsync option.
*/


if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and (d.status & 16383) >= 32
			and d.status & 256 != 256
			and #spdevtab.name = d.name)
begin
	/*
	**  Check to see if the mirror is enabled. 0x200 (512) bit in status.
	*/
	if exists (select *
		from master.dbo.sysdevices d, #spdevtab
			where d.status & 512 = 512
				and #spdevtab.name = d.name)
	begin
		/* 17615, "MIRROR ENABLED" */
		exec sp_getmessage 17615, @msg out
		update #spdevtab
			set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.status & 512 = 512
				and #spdevtab.name = d.name
	end

	if exists (select *
		from master.dbo.sysdevices d, #spdevtab
			where d.status & 512 != 512
				and (d.status & 16383) >= 32
				and #spdevtab.name = d.name)
	begin
		/* 17616, "MIRROR DISABLED" */
		exec sp_getmessage 17616, @msg out
		update #spdevtab
			set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where d.status & 512 != 512
				and (d.status & 16383) >= 32
				and #spdevtab.name = d.name
	end

	/* add mirror name.*/
	
	/* 
	** NOTE: Do not include this for private devices as there's no mirroring
	** done for private device due to which we'll always see text as follows
	**  	... MIRROR DISABLED, mirror = ''...
	*/
	
	/* 17617, "mirror = " */
	exec sp_getmessage 17617, @msg out
	update #spdevtab
		set statusdesc = statusdesc + ", " + @msg + " '" + d.mirrorname
			+ "'"
		from master.dbo.sysdevices d, #spdevtab
			where #spdevtab.name = d.name
				and (d.status & 16383) >= 32
				and (d.status2 & 2)  != 2
end

/*
**  Check to see if there is a mirrorname entry but mirroring not enabled.
**  If so, then one side of the mirror is off-line.
*/
else if exists (select *
	from master.dbo.sysdevices d, #spdevtab
		where #spdevtab.name = d.name
		and d.status & 256 = 256
		and d.mirrorname is not null)
begin
	/* Set up the message */
	declare @part1	varchar(60)
	declare @part2	varchar(60)
	declare @part3	varchar(60)
	/* 17618, "only device '%1!' of mirror is enabled -- device '%2!'
	**	is disabled"
	*/
	exec sp_getmessage 17618, @msg out
	select @part1 = substring(@msg, 1, charindex("%1!", @msg) - 1)
	select @part2 = substring(@msg, charindex("%1!", @msg) + 3, 
		((charindex("%2!", @msg) - 1) - (charindex("%1!", @msg) +2)))
	select @part3 = substring(@msg, charindex("%2!", @msg) + 3, 60)

	/*
	**  Figure out which side of the mirror is disabled.
	**  If 0x100 is on then phyname is disabled and mirrorname is enabled.
	*/
	if exists (select *
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
			where v.type = "V" and v.number > -1
				and d.status & v.number = 256
				and #spdevtab.name = d.name)
	begin
		update #spdevtab
			set statusdesc = @part1 + d.mirrorname 
				+ @part2 + d.phyname + @part3
			from master.dbo.sysdevices d, master.dbo.spt_values v,
				#spdevtab
			where v.type = "V" and v.number > -1
				and d.status & v.number = 256
				and #spdevtab.name = d.name
	end
	else if exists (select *
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
			where v.type = "V" and v.number > -1
				and d.status & v.number = 64
				and #spdevtab.name = d.name)
	begin
		update #spdevtab
			set statusdesc = @part1 + d.phyname 
				+ @part2 + d.mirrorname + @part3
			from master.dbo.sysdevices d, master.dbo.sysdevices e,
				master.dbo.spt_values v, #spdevtab
			where v.type = "V" and v.number > -1
				and d.status & v.number = 64
				and #spdevtab.name = d.name
				and e.status & 256 != 256
				and #spdevtab.name = e.name
	end
end


/*
**  Status of 0x20 is "serial writes" for mirrored disks.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and d.status & v.number = 32
			and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab,
				master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 32
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
end

/* 17620, "nonserial writes" */
exec sp_getmessage 17620, @msg out

/*
** "nonserial writes" only relevant for mirrorred devices.
** The 0x3fff mask is necessary since ASE12.0 introduced a
** new status bit 0x4000 to indicate the dsync option.
*/

update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
			where (d.status & 16383) > 32
				and d.status &32 != 32
				and #spdevtab.name = d.name

/*  
** Check for the dsync option :
** The status bit 16384 (0x4000) sets the dsync option for the disk_device only
*/

begin
	/*
        ** For all devices, check to see if the 'dsync' bit is on.
        ** 'master' and 'master_companion' (in HA failover mode),
        ** always have the 'dsync' bit on. The use of @@cmpstate here is
        ** to distinguish a master_companion device from a HA failover
        ** and a non-HA user created one. It is possible for user to
        ** create a device named "master_companion" in a non-HA ASE.
	*/		
	/* 17621, "dsync on" */
       	exec sp_getmessage 17621,@msg out	
		update #spdevtab
			set statusdesc = statusdesc + ", " + @msg
			from master.dbo.sysdevices d, #spdevtab
			where (d.status & 16384 = 16384 
				or (d.name = "master"
					or (d.name = "master_companion"
				 		and @@cmpstate in (4,12))))
			and d.status & 2 = 2
			and #spdevtab.name = d.name 

	/* 17622, "dsync off" */
	exec sp_getmessage 17622, @msg out	
		update #spdevtab
			set statusdesc = statusdesc + ", " + @msg
			from master.dbo.sysdevices d, #spdevtab 
			where (d.status & 16384 != 16384)
			and d.status & 2 = 2
			and #spdevtab.name = d.name
			and not (d.name = "master"
				or (d.name = "master_companion"
					and @@cmpstate in (4,12)))
	
end

/* 17623, "directio on" */
exec sp_getmessage 17623,@msg out
update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
	from master.dbo.sysdevices d, #spdevtab
		where d.status2 & 1 = 1
		and d.status & 2 = 2
		and #spdevtab.name = d.name

/* 17624, "directio off" */
exec sp_getmessage 17624, @msg out
	update #spdevtab
	set statusdesc = statusdesc + ", " + @msg
		from master.dbo.sysdevices d, #spdevtab
		where d.status2 & 1 != 1
		and d.status & 2 = 2
		and #spdevtab.name = d.name

/*
**  Status of 0x80 is "reads mirrored" for mirrored disks.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and d.status & v.number = 128
			and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab,
				master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 128
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
end

/*
**  Now check out the status bits and turn them into english.
**  Status of 0x10 is a dump device.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and d.status & v.number = 16
			and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab,
				master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 16
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
end

/*
**  Now check out the status bits and turn them into english.
**  Status of 0x01 is a default disk.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and d.status & v.number = 1
			and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab,
				master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 1
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
end

/*
**  Now check out the status bits and turn them into english.
**  Status of 0x02 is a physical disk Status2 0x08 is virtual
**  cache device used for in-memory databases.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where (	  (v.type = "V" and v.number > -1
			   and (d.status & v.number = 2))
			or (v.type = "V2" and v.number > -1
			    and (d.status2 & v.number = 8)))
		and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab,
				master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 2
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang

	/*
	** Compute number of Pages in a Megabyte.
	*/
	declare @numpgsmb float		/* Number of 'virtual' Pages per Megabytes */

	select @numpgsmb = (1048576. / @@pagesize)

	/*
	**  Add in its size in MB.
	*/
	update #spdevtab
		set statusdesc = statusdesc + ", " +
			ltrim(str((1. + (d.high - d.low)) / @numpgsmb, 10, 2)) + " MB"
		from master.dbo.sysdevices d, #spdevtab
			where ((d.status & 2 = 2) or (d.status2 & 8 = 8))
				and #spdevtab.name = d.name

	/*                                                  
	** Calculate unused size in MB.                     
	*/                                                  
	select d.vdevno, usedsizeMB = isnull((sum(u.size)/512.0)*(@@maxpagesize/@@pagesize),0)
		into #spdevusedtab                                   
		from master.dbo.sysdevices d, master.dbo.sysusages u 
			where u.vdevno =* d.vdevno                            
				and ((d.status & 2 = 2) or (d.status2 & 8 = 8))
			group by d.vdevno                                    

	update #spdevtab                                                           
		set statusdesc = statusdesc + ", Free: " +                                
			ltrim(str(((1. + (d.high - d.low)) / @numpgsmb) - usedsizeMB, 10, 2)) + " MB"
		from master.dbo.sysdevices d, #spdevusedtab u, #spdevtab                  
			where ((d.status & 2 = 2) or (d.status2 & 8 = 8))
				and d.vdevno = u.vdevno
				and #spdevtab.name = d.name

end

/*
**  Now check out the status bits and turn them into english.
**  Status of 0x04 is a archive database disk.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and d.status & v.number = 4
			and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, 
				#spdevtab, master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 4
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
end

/*
**  Now check out the status bits and turn them into english.
**  Status of 0x08 is a read-only disk device.
*/
if exists (select *
	from master.dbo.sysdevices d, master.dbo.spt_values v, #spdevtab
		where v.type = "V" and v.number > -1
			and d.status & v.number = 8
			and #spdevtab.name = d.name)
begin
	update #spdevtab
		set statusdesc = statusdesc + ", " + m.description
		from master.dbo.sysdevices d, master.dbo.spt_values v, 
				#spdevtab, master.dbo.sysmessages m
			where v.type = "V" and v.number > -1
				and d.status & v.number = 8
				and #spdevtab.name = d.name
				and v.msgnum = m.error
				and isnull(m.langid, 0) = @sptlang
end

set nocount off

/*
**  Display the device info
*/

    select device_name = d.name,
	physical_name = d.phyname,
	description = #spdevtab.statusdesc,
	d.status, d.cntrltype,
	d.vdevno, vpn_low, vpn_high
    into #sphelpdevice1rs
    from master.dbo.sysdevices d, #spdevtab
    where d.name = #spdevtab.name

    exec sp_autoformat @fulltabname = #sphelpdevice1rs,
         @orderby = "order by device_name" 
    drop table #sphelpdevice1rs

/* 
** Display space allocation per database if called for a single device 
*/
set nocount on

if (select count(*) from #spdevtab
    where ((dbdev_flag = 2) or (imdbdev_flag = 8))) = 1
begin
   select dbname=db_name(dbid), 
	size=str(((size / 512.0)*(@@maxpagesize/@@pagesize)), 10, 2) + " MB",
	allocated=crdate,
	vstart, lstart
  into #spdevfragtab
  from master.dbo.sysusages
  where vdevno = (select vdevno from #spdevtab 
  			where ((dbdev_flag = 2) or (imdbdev_flag = 8)))
  
  exec sp_autoformat @fulltabname = #spdevfragtab, 
	@orderby = "order by allocated, vstart"
end

set nocount off

/*
** If the server is booted with the trace flag 1624 on, then 'dsync' 
** will be turned off for the master device.
**
** If the server is booted with the trace flag 1623 on, then 'dsync'
** will be turned off for all the devices.
**
** Report a warning message to the user if the server is booted 
** with the trace flag 1623 or 1624 turned .
**
** Note: The warning messages generated will be in English only, as
** these trace flags are for internal testing only.
*/		
declare @tracemsg varchar(255)
select @tracemsg = "WARNING: 'dsync is OFF' FOR %1! DUE TO THE TRACE FLAG %2!; OVERRIDING THE REAL STATUS IN SYSDEVICES"
dbcc istraceon(1624)
if @@error != -1
begin
	dbcc istraceon(1623)
	if @@error = -1
	begin	
		print ""
		print @tracemsg, "THE 'master'/'master_companion' DEVICE", 1624
	end
end

dbcc istraceon(1623)
if @@error ! = -1
begin
	print ""
	print @tracemsg, "ALL DEVICES", 1623
end

return (0)
go
exec sp_procxmode 'sp_helpdevice', 'anymode'
go
grant execute on sp_helpdevice to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helplog')
begin
	drop procedure sp_helplog
end
go
print "Installing sp_helplog"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
** Messages for "sp_helplog"            17672
**
** 17672, "In database '%1!', the log starts on device '%2!'."
** 18433, "No valid log device can be found to contain the starting logpage 
**	   of '%1!', on database '%2!'. Perhaps the segment mapping of 
**	   database has changed recently.  Please inspect the sysusages 
**	   catalog and contact your system administrator."
**
*/
create procedure sp_helplog
as
declare @firstpage int,
	@devname varchar(255),
	@msg varchar(1024),
	@dbname varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Get the first page of the log from sysindexes */
select @firstpage = firstpage
from syspartitions
where id = 8
  and partitionid = 8
  and indid = 0

/*
**  Get the name of the device which contains the first page of the log.
**  Make sure that the device has logsegment mapped to it.
*/
select @devname = d.name 
from master.dbo.sysdevices d, master.dbo.sysusages u
where	(d.status & 6) != 0
	and @firstpage >= u.lstart
	and @firstpage < u.lstart + u.size
	and u.dbid = db_id()
	and u.segmap & 4 = 4
	and u.vdevno = d.vdevno

select @dbname = db_name()
 
if (@devname is NULL)
begin

	/* 
	** 18433, "No valid log device can be found to contain the starting 
	**	  logpage of '%1!', on database '%2!'. Perhaps the segment 
	**	  mapping of database has changed recently.  Please inspect 
	**	  the sysusages catalog and contact your system administrator."
	*/
	exec sp_getmessage 18433, @msg out
	print @msg, @firstpage, @dbname
end
else
begin
	/* Print the name of the device which contains the log start page */
	/* 17672, "In database '%1!', the log starts on device '%2!'." */
	exec sp_getmessage 17672, @msg out
	print @msg, @dbname, @devname
end

return (0)
go
exec sp_procxmode 'sp_helplog', 'anymode'
go
grant execute on sp_helplog to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpindex')
begin
	drop procedure sp_helpindex
end
go
print "Installing sp_helpindex"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helpindex"          17640
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
** 17640, "Object does not have any indexes."
** 17641, "Object has the following indexes"
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_helpindex
@objname varchar(767)			/* the table to check for indexes */
as

declare @indid int			/* the index id of an index */
declare @keys varchar(1024)		/* string to build up index key in */
declare @inddesc varchar(68)		/* string to build up index desc in */
declare @msg varchar(1024)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see that the object names are local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
end

/*
**  Check to see the the table exists 
*/
if not exists (select id
		from sysobjects
			where id = object_id(@objname))
/*
**  Table doesn't exist so return.
*/
begin
	/* 17461, "Object does not exist in this database." */
	raiserror 17461
	return (1)
end

/*
**  See if the object has any indexes.
**  Since there may be more than one entry in sysindexes for the object,
**  this select will set @indid to the index id of the first index.
*/
select @indid = min(indid)
	from sysindexes
		where id = object_id(@objname)
			and indid > 0
			and indid < 255

/*
**  If no indexes, return.
*/
if @indid is NULL
begin
	/* 17640, "Object does not have any indexes." */
        exec sp_getmessage 17640, @msg output
        print @msg
	return (1)
end

/*
**  Now check out each index, figure out it's type and keys and
**  save the info in a temporary table that we'll print out at the end.
*/
create table #spindtab
(
	index_name	varchar(255),
	index_keys	varchar(1024),
	index_description	varchar(68),
	index_max_rows_per_page	smallint,
	index_fillfactor	smallint,
	index_reservepagegap	smallint,
	index_created		datetime NULL,
	index_local		varchar(255)
)

/*  Create temporary table for sysattributes data */
create table #spindattr
(
	name		varchar(255), 
	class		smallint,
	attribute	smallint,
	int_value	int NULL,
	char_value	varchar(255) NULL,
	comments	varchar(255) NULL
)

/* This is for the index partition information. */
create table #spindptn
(
	index_ptn_name	varchar(255),
	index_ptn_seg	varchar(255),
)

while @indid is not NULL
begin
	
	/*
	**  First we'll figure out what the keys are.
	*/
	declare @i int
	declare @thiskey varchar(255)
	declare @sorder char(4)	
	declare @lastindid int

	select @keys = "", @i = 1

	set nocount on

	while @i <= 31
	begin
		select @thiskey = index_col(@objname, @indid, @i)

		if (@thiskey is NULL) 
		begin
			goto keysdone
		end

		if @i > 1
		begin
			select @keys = @keys + ", " 
		end

		/*select @keys = @keys + index_col(@objname, @indid, @i)*/
		select @keys = @keys + @thiskey

		/*
		** Get the sort order of the column using index_colorder()
		** This support is added for handling descending keys.
		*/
		select @sorder = index_colorder(@objname, @indid, @i)
		if (@sorder = "DESC")
			select @keys = @keys + " " + @sorder

		/*
		**  Increment @i so it will check for the next key.
		*/
		select @i = @i + 1

	end


	/*
	**  When we get here we now have all the keys.
	*/
	keysdone:
		set nocount off


	/*
	**  Initialize the index description by figuring out if it's a
	**  clustered or nonclustered index.
	*/
	if @indid = 1
	begin
		select @inddesc = "clustered"
	end
	if @indid > 1
	begin
			if exists (select * from sysindexes i
					where status2 & 512 = 512
					and i.indid = @indid
					and i.id = object_id(@objname))
			begin
				select @inddesc = "clustered"
			end 
			else
			begin
				select @inddesc = "nonclustered"
			end
	end

	/*
	**  Now we'll check out the status bits for this index and
	**  build an english description from them.
	*/

	/*
	**  See if the index is unique (0x02).
	*/
	if exists (select *
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 2
				and i.id = object_id(@objname)
				and i.indid = @indid)
	begin
	select @inddesc = @inddesc + ", " + v.name
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 2
				and i.id = object_id(@objname)
				and i.indid = @indid
	end
	else
	/* 
	** if this is a nonunique clustered index on dol tables, dup rows
	** are allowed
	*/
	if exists (select * from sysindexes i
			where status2 & 512 = 512
			and i.indid = @indid
			and i.id = object_id(@objname))
	begin
		select @inddesc = @inddesc + ", " + v.name
			from master.dbo.spt_values v, sysindexes i
			where v.type = "I"
			and v.number = 64
			and i.id = object_id(@objname)
			and i.indid = @indid
	end

	/*
	**  See if the index is ignore_dupkey (0x01).
	*/
	if exists (select *
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 1
				and i.id = object_id(@objname)
				and i.indid = @indid)
	begin
	select @inddesc = @inddesc + ", " + v.name
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 1
				and i.id = object_id(@objname)
				and i.indid = @indid
	end

	/*
	**  See if the index is ignore_dup_row (0x04).
	*/
	if exists (select *
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 4
				and i.id = object_id(@objname)
				and i.indid = @indid)
	begin
	select @inddesc = @inddesc + ", " + v.name
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 4
				and i.id = object_id(@objname)
				and i.indid = @indid
	end

	/*
	**  See if the index is allow_dup_row (0x40).
	*/
	if exists (select *
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 64
				and i.id = object_id(@objname)
				and i.indid = @indid)
	begin
	select @inddesc = @inddesc + ", " + v.name   
		from master.dbo.spt_values v, sysindexes i
			where i.status & v.number = v.number
				and v.type = "I"
				and v.number = 64
				and i.id = object_id(@objname)
				and i.indid = @indid
	end

	/*
	**  Now we have the whole description for the index so we'll add
	**  the goods to the temporary table.
	*/
	insert into #spindtab
		select name, @keys, @inddesc, maxrowsperpage, fill_factor,
			isnull(res_page_gap,0), crdate, 
			case when (status3 & 8 = 8) then "Local Index"
			     else "Global Index"
			end
			from sysindexes
				where id = object_id(@objname)
					and indid = @indid
	/* 
	**  Get sysattributes data if there is any
	*/
	insert #spindattr (name, class, attribute, int_value, char_value, 
								comments)
		select i.name, a.class, a.attribute, a.int_value, a.char_value,
								a.comments
		from sysindexes i, sysattributes a
		where a.object_type = "I"
		and a.object = object_id(@objname)
		and a.object_info1 = @indid
		and i.id = object_id(@objname)
		and i.indid = @indid


	insert #spindptn(index_ptn_name, index_ptn_seg)
	select idxptn_nam = p.name, segment = s.name
		from syssegments s, syspartitions p
		where s.segment = p.segment and p.id = object_id(@objname)
		and p.indid = @indid

	/*
	** It's possible a cache is deleted without doing an unbind first. After
	** a server reboot the binding is marked 'invalid' (int_value = 0).
	** If we have such an invalid binding, don't show it in the output.
	*/
	delete from #spindattr
	where class = 3
	and attribute = 0
	and int_value = 0

	/*
	**  Now move @indid to the next index.
	*/
	select @lastindid = @indid
	select @indid = NULL
	select @indid = min(indid)
		from sysindexes
			where id = object_id(@objname)
				and indid > @lastindid
				and indid < 255
end

/*
**  Now print out the contents of the temporary index table.
*/
exec sp_getmessage 17641, @msg output
print @msg
print ""

exec sp_autoformat #spindtab

drop table #spindtab

exec sp_autoformat #spindptn

drop table #spindptn


/*
** If the table has functional indexes, display all the functional index 
** keys.
*/
if exists (select 1 from sysindexes i where i.id = object_id(@objname) and
		(status2 & 32768) = 32768)
begin
	print ""
	execute dbo.sp_helpcomputedcolumn @objname, 1
end

/*  
** Print sysattributes data if there is any.  The join with
** master..sysattributes is to get the string descriptions for the
** class (master.dbo.sysattributes cn) and attribute
** (master.dbo.sysattributes an). These should never be more than
** 30 characters, so it's okay to truncate them to 30.
*/

if exists (select * from #spindattr)
begin 
	select name = a.name, attribute_class = cn.char_value,
		attribute = an.char_value, a.int_value, 
		a.char_value, a.comments
	into #sphelpindex1rs
	from #spindattr a, master.dbo.sysattributes cn,
		master.dbo.sysattributes an
	where a.class = cn.object
	and a.attribute = an.object_info1
	and a.class = an.object
	and cn.class = 0
	and cn.attribute = 0
	and an.class = 0
	and an.attribute = 1
	exec sp_autoformat @fulltabname = #sphelpindex1rs
	drop table #sphelpindex1rs
end
drop table #spindattr
return (0)
go
exec sp_procxmode 'sp_helpindex', 'anymode'
go
grant execute on sp_helpindex to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpjoins')
begin
	drop procedure sp_helpjoins
end
go
print "Installing sp_helpjoins"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helpjoins"          17650
**
** 17460, "Object must be in the current database."
** 17650, "First table doesn't exist."
** 17651, "Second table doesn't exist."
** 17652, "Object must be in your current database."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_helpjoins
@lefttab varchar(767),			/* name of first table to join */
@righttab varchar(767)			/* name of first table to join */
as

declare @foundit bit			/* flag to indicate joins found */


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  This procedure returns any foreign or common joins.
**  If none exists, then it returns any joins that have the same usertype.
**  If none exists, it returns any joins that have the same physical type.
*/

/*
**  Make sure the @objname is local to the current database.
*/
if @lefttab like "%.%.%" and
	substring(@lefttab, 1, charindex(".", @lefttab) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
end
if @righttab like "%.%.%" and
	substring(@righttab, 1, charindex(".", @righttab) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
end

/*
**  See if we can find the objects.  They must be a system table, user table,
**  or view.  The low 3 bits of sysobjects.sysstat indicate what the 
**  object type is -- it's more reliable than using sysobjects.type which
**  could change.
*/
/*
**  If either of the tables don't exist, quit.
*/
if not exists (select id
	from sysobjects
		where id = object_id(@lefttab)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3))	/* user table */
begin
	/* 17650, "First table doesn't exist." */
	raiserror 17650
	return (1)
end 

if not exists (select id
	from sysobjects
		where id = object_id(@righttab)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3))	/* user table */

begin
	/* 17651, "Second table doesn't exist." */
	raiserror 17651
	return (1)
end 

create table #hjtab
(
	a1	varchar(100),
	a2	varchar(100),
	b1	varchar(100) null,
	b2	varchar(100) null,
	c1	varchar(100) null,
	c2	varchar(100) null,
	d1	varchar(100) null,
	d2	varchar(100) null,
	e1	varchar(100) null,
	e2	varchar(100) null,
	f1	varchar(100) null,
	f2	varchar(100) null,
	g1	varchar(100) null,
	g2	varchar(100) null,
	h1	varchar(100) null,
	h2	varchar(100) null
)

/*
**  Look for foreign key joins.
*/
select @foundit = 0
if exists (select *
		from syskeys
			where type = 2
				and id = object_id(@lefttab)
				and depid = object_id(@righttab))
begin
	insert into #hjtab
	select distinct first_pair = convert(varchar(100), col_name(id, key1)), convert(varchar(100), col_name(depid, depkey1)),
		second_pair = convert(varchar(100), col_name(id, key2)), convert(varchar(100), col_name(depid, depkey2)),
		third_pair = convert(varchar(100), col_name(id, key3)), convert(varchar(100), col_name(depid, depkey3)),
		fourth_pair = convert(varchar(100), col_name(id, key4)), convert(varchar(100), col_name(depid, depkey4)),
		fifth_pair = convert(varchar(100), col_name(id, key5)), convert(varchar(100), col_name(depid, depkey5)),
		sixth_pair = convert(varchar(100), col_name(id, key6)), convert(varchar(100), col_name(depid, depkey6)),
		seventh_pair = convert(varchar(100), col_name(id, key7)), convert(varchar(100), col_name(depid, depkey7)),
		eighth_pair = convert(varchar(100), col_name(id, key8)), convert(varchar(100), col_name(depid, depkey8))
	from syskeys
		where type = 2
			and id = object_id(@lefttab)
			and depid = object_id(@righttab)

	select @foundit = 1
end

if exists (select *
		from syskeys
			where type = 2
				and id = object_id(@righttab)
				and depid = object_id(@lefttab))
begin
	insert into #hjtab
	select distinct first_pair = convert(varchar(100), col_name(depid, depkey1)), convert(varchar(100), col_name(id, key1)),
		second_pair = convert(varchar(100), col_name(depid, depkey2)), convert(varchar(100), col_name(id, key2)),
		third_pair = convert(varchar(100), col_name(depid, depkey3)), convert(varchar(100), col_name(id, key3)),
		fourth_pair = convert(varchar(100), col_name(depid, depkey4)), convert(varchar(100), col_name(id, key4)),
		fifth_pair = convert(varchar(100), col_name(depid, depkey5)), convert(varchar(100), col_name(id, key5)),
		sixth_pair = convert(varchar(100), col_name(depid, depkey6)), convert(varchar(100), col_name(id, key6)),
		seventh_pair = convert(varchar(100), col_name(depid, depkey7)), convert(varchar(100), col_name(id, key7)),
		eighth_pair = convert(varchar(100), col_name(depid, depkey8)), convert(varchar(100), col_name(id, key8))
	from syskeys
		where type = 2
			and id = object_id(@righttab)
			and depid = object_id(@lefttab)

	select @foundit = 1
end

/*
**  Look for common key joins.
*/
if exists (select *
		from syskeys
			where type = 3
				and id = object_id(@lefttab)
				and depid = object_id(@righttab))
begin
	insert into #hjtab
	select distinct first_pair = convert(varchar(100), col_name(id, key1)), convert(varchar(100), col_name(depid, depkey1)),
		second_pair = convert(varchar(100), col_name(id, key2)), convert(varchar(100), col_name(depid, depkey2)),
		third_pair = convert(varchar(100), col_name(id, key3)), convert(varchar(100), col_name(depid, depkey3)),
		fourth_pair = convert(varchar(100), col_name(id, key4)), convert(varchar(100), col_name(depid, depkey4)),
		fifth_pair = convert(varchar(100), col_name(id, key5)), convert(varchar(100), col_name(depid, depkey5)),
		sixth_pair = convert(varchar(100), col_name(id, key6)), convert(varchar(100), col_name(depid, depkey6)),
		seventh_pair = convert(varchar(100), col_name(id, key7)), convert(varchar(100), col_name(depid, depkey7)),
		eighth_pair = convert(varchar(100), col_name(id, key8)), convert(varchar(100), col_name(depid, depkey8))
	from syskeys
		where type = 3
			and id = object_id(@lefttab)
			and depid = object_id(@righttab)

	select @foundit = 1
end

if exists (select *
		from syskeys
			where type = 3
				and id = object_id(@righttab)
				and depid = object_id(@lefttab))
begin
	insert into #hjtab
	select distinct first_pair = convert(varchar(100), col_name(depid, depkey1)), convert(varchar(100), col_name(id, key1)),
		second_pair = convert(varchar(100), col_name(depid, depkey2)), convert(varchar(100), col_name(id, key2)),
		third_pair = convert(varchar(100), col_name(depid, depkey3)), convert(varchar(100), col_name(id, key3)),
		fourth_pair = convert(varchar(100), col_name(depid, depkey4)), convert(varchar(100), col_name(id, key4)),
		fifth_pair = convert(varchar(100), col_name(depid, depkey5)), convert(varchar(100), col_name(id, key5)),
		sixth_pair = convert(varchar(100), col_name(depid, depkey6)), convert(varchar(100), col_name(id, key6)),
		seventh_pair = convert(varchar(100), col_name(depid, depkey7)), convert(varchar(100), col_name(id, key7)),
		eighth_pair = convert(varchar(100), col_name(depid, depkey8)), convert(varchar(100), col_name(id, key8))
	from syskeys
		where type = 3
			and id = object_id(@righttab)
			and depid = object_id(@lefttab)

	select @foundit = 1
end

/*
**  We got a foreignkey and we didn't get a common key.
*/
if @foundit = 1
begin
	select distinct *
	into #hjtab_dis
	from #hjtab

	exec sp_autoformat @fulltabname = #hjtab_dis

	drop table #hjtab
	drop table #hjtab_dis

	return (0)
end

/*
**  We didn't find any defined joins so we'll look for common user types.
*/
if exists (select *
		from syscolumns a, syscolumns b
			where a.id = object_id(@lefttab)
				and b.id = object_id(@righttab)
				and a.usertype = b.usertype
				and a.usertype > 99)
begin
	select distinct first_pair = col_name(a.id, a.colid),
		first_pair_second = col_name(b.id, b.colid)
	into #hjtab1
	from syscolumns a, syscolumns b
		where a.id = object_id(@lefttab)
			and b.id = object_id(@righttab)
			and a.usertype = b.usertype
			and a.usertype > 99

	exec sp_autoformat @fulltabname = #hjtab1,
			@orderby ="order by first_pair"
			
	drop table #hjtab1

	/*
	**  If we found something, we can stop.
	*/
	if @@rowcount > 0
		return (0)
end

/*
**  We couldn't find anything so far so we'll see if we have anything
**  that just shares the same physical type.
*/
if exists (select *
		from syscolumns a, syscolumns b, master.dbo.spt_values y,
			master.dbo.spt_values z
		where a.id = object_id(@lefttab)
			and b.id = object_id(@righttab)
			and a.id != b.id
			and a.name = b.name
			and y.type = "J"
			and a.type = y.low
			and z.type = "J"
			and b.type = z.low
			and y.number = z.number)
begin
	select distinct first_pair = col_name(a.id, a.colid),
		first_pair_second = col_name(b.id, b.colid)
	into #hjtab2
	from syscolumns a, syscolumns b, master.dbo.spt_values y,
		master.dbo.spt_values z
	where a.id = object_id(@lefttab)
		and b.id = object_id(@righttab)
		and a.id != b.id
		and a.name = b.name
		and y.type = "J"
		and a.type = y.low
		and z.type = "J"
		and b.type = z.low
		and y.number = z.number
	exec sp_autoformat @fulltabname = #hjtab2,
		@orderby = "order by first_pair"

	drop table #hjtab2
end

return (0)
go
exec sp_procxmode 'sp_helpjoins', 'anymode'
go
grant execute on sp_helpjoins to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpkey')
begin
	drop procedure sp_helpkey
end
go
print "Installing sp_helpkey"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helpkey"            17660
**
** 17390, "Table or view name must be in 'current' database."
** 17492, "The table or view named doesn't exist in the current database."
** 17660, "No defined keys for this object."
** 17661, " -- none --"
** 17662, "NOTE : For information on declarative integrity features : PRIMARY KEY, UNIQUE, FOREIGN KEY, CHECK CONSTRAINT, REFERENTIAL CONSTRAINT, NULL/NOT NULL, and DEFAULT, use sp_helpconstr, a new system stored procedure."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_helpkey
@tabname varchar(767) = null	/* table or view we want to check */
as

declare @note	varchar(1024)
declare @msg	varchar(1024)
declare @none	varchar(30)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see that the object names are local to the current database.
*/
if @tabname like "%.%.%" and
	substring(@tabname, 1, charindex(".", @tabname) - 1) != db_name()
begin
	/* 17390, "Table or view name must be in 'current' database." */
	raiserror 17390
	return (1)
end

/*
** This procedure should eventually become obsolete since with System 10
** we support declarative constraints.  This constraint information is
** available through sp_helpconstr.  The server will not record any information
** in syskeys.  Do this only if this procedure is executed directly.
*/
if @@nestlevel = 1
begin
	exec sp_getmessage 17662, @note out
	print @note
	print ""
end

exec sp_getmessage 17661, @none out

/*
**  If @tabname is null, show all the keys.
*/
if @tabname is null
begin

	select keytype = v.name, object = object_name(k.id),
		related_object = isnull(object_name(k.depid), @none),
		object_keys = convert(varchar(80), col_name(k.id, key1)) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key2), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key3), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key4), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key5), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key6), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key7), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key8), "*")),
		related_keys = 
		convert(varchar(80), isnull(col_name(k.depid, depkey1), "*")) + ", "
	+ convert(varchar(80), isnull(col_name(k.depid, depkey2), "*")) + ", "
	
		+ convert(varchar(80), isnull(col_name(k.depid, depkey3), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey4), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey5), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey6), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey7), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey8), "*"))
	into #sphelpkeys1rs
	from syskeys k, master.dbo.spt_values v
		where k.type = v.number and v.type = 'K'
	exec sp_autoformat @fulltabname = #sphelpkeys1rs,
		@orderby = "order by object, keytype, related_object"
	drop table #sphelpkeys1rs
	return (0)
end

/*
**  We're looking for a particular table or view.
*/
else
begin
	/*
	**  Make sure the table or view exists.
	*/
	if not exists (select id
			from sysobjects
				where id = object_id(@tabname))
	begin
		/* 17492, "The table or view named doesn't exist in the current database." */
		raiserror 17492
		return (1)
	end

	/*
	**  See if any keys exist.
	*/
	if not exists (select *
			from syskeys
			where id = object_id(@tabname) or 
				depid = object_id(@tabname))
	begin
		/* 17660, "No defined keys for this object." */
		exec sp_getmessage 17660, @msg output
		print @msg
		return (1)
	end


	    select keytype = v.name,
		object = object_name(k.id),
		related_object = isnull(object_name(k.depid), @none),
		object_keys = convert(varchar(80), col_name(k.id, key1)) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key2), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key3), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key4), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key5), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key6), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key7), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.id, key8), "*")),
		related_keys =
		convert(varchar(80), isnull(col_name(k.depid, depkey1), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey2), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey3), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey4), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey5), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey6), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey7), "*")) + ", "
		+ convert(varchar(80), isnull(col_name(k.depid, depkey8), "*"))
	    into #sphelpkeys2rs
	    from syskeys k, master.dbo.spt_values v
		where k.type = v.number and v.type = 'K'
			and (k.id = object_id(@tabname) or 
			     k.depid = object_id(@tabname))
	    exec sp_autoformat @fulltabname =  #sphelpkeys2rs,
		@orderby = "order by object, keytype, related_object"
	    drop table #sphelpkeys2rs
	return (0)
end
go
exec sp_procxmode 'sp_helpkey', 'anymode'
go
grant execute on sp_helpkey to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_objectsegment')
begin
	drop procedure sp_objectsegment
end
go
print "Installing sp_objectsegment"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */

/*
** Messages for "sp_objectsegment"      17714
**
** LOCALIZE the following:
**
**      select Data_located_on_segment = s.name, When_created = crdate
**
** Data_located_on_segment
** When_created
**
** 17714, "not applicable" 
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_objectsegment
@objname	varchar(767)	/* table name */
as
declare @msg varchar(30)	-- Keep length short so that message comes
				-- out nicely formatted. No need for 1024 here.


	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* 
	** Print out the create date for each partition of the object 
	** and it's data segment, if applicable.
	*/

	/*
	**  Objects have the following value for sysstat & 15:
	**			15 is the max value for object type.
	**	0 - any/illegal object
	**	1 - system table
	**	2 - view
	**	3 - user table
	**	4 - sproc
	**	5 - NOT UNUSED
	**	6 - default
	**	7 - rule
	**	8 - trigger
	**	9 - referential constraint
	**	10 - check constraint
	**	11 - Extended type
	**	12 - stored function
	**	13 - computed column
	**	14 - Partition condition
	*/
	if exists (select *
			from sysobjects
				where id = object_id(@objname)
					and sysstat & 15 in (1, 3))
	begin
		select Partition_name = p.name, 
		       Data_located_on_segment = s.name, 
		       When_created = p.crdate
		into #segresult
		from syssegments s, syspartitions p
		where p.id = object_id(@objname)
		  and p.indid < 2
		  and p.segment = s.segment

		exec sp_autoformat @fulltabname='#segresult', 
				   @orderby='order by 1'
	end

	/*
	**  It's not a table so segment is not applicable.
	*/
	else
	begin
		/*
		** 17714, "not applicable" 
		*/
		exec sp_getmessage 17714, @msg output
		select Data_located_on_segment = @msg,
			When_created = o.crdate
		from sysobjects o
			where o.id = object_id(@objname)
	end

return (0)

go
exec sp_procxmode 'sp_objectsegment', 'anymode'
go
grant execute on sp_objectsegment to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_indsuspect')
begin
	drop procedure sp_indsuspect
end
go
print "Installing sp_indsuspect"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages from sysmessages
**
** 17860, "Suspect indexes in database %1!:"
** 17861, "There are no suspect indexes in database %1!."
** 17862, "Table must be in the 'current' database."
** 17863, "There is no table named %1! in the 'current' database."
** 17864, "Suspect indexes on table %1!:"
** 17865, "There are no suspect indexes on table %1!."
*/

create procedure sp_indsuspect
@tab_name varchar(767) = NULL		/* if NULL, check all tables in db */
AS

declare @msg		varchar(1024)	/* used for message to user */
declare @msg2		varchar(30)	/* used for table/db name */
declare @ind_suspect	smallint	/* value of IND_SUSPECT bit */


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

/* 
** Specify the bit mask as -32768, not in hex notation, for portability
** to byte-swapped platforms.  This could break on a 1's complement 
** platform, but there isn't really a better solution.  SQL handles 
** hex numbers as binary data, not as numeric values as in C.
*/

select @ind_suspect = -32768

if (@tab_name is null)
begin
	/*
	** No table name specified, sp search for any
	** suspected indexes in the entire database.
	*/
	if exists (select * from sysindexes i
			where (i.status & @ind_suspect) != 0)
	begin
		/* 17860, "Suspect indexes in database %1!:" */
		exec sp_getmessage 17860, @msg output
		select @msg2 = db_name()
		print @msg, @msg2

		select
                        "Own.Tab.Ind (Obj_ID, Ind_ID)" =
				u.name + "." + o.name + '.' + i.name +
				' (' + convert(varchar, o.id) + ', ' +
				convert(varchar, i.indid) + ')'
		from
			sysobjects o,
			sysindexes i,
			sysusers u
		where
			o.id = i.id
		    and o.uid = u.uid
		    and (i.status & @ind_suspect) != 0

		exec sp_autoformat @fulltabname = #temp1,
			@selectlist = "'Own.Tab.Ind (Obj_ID, Ind_ID)' = name"
	end
	else
	begin
		/* 17861, "There are no suspect indexes in database %1!." */
		exec sp_getmessage 17861, @msg output
		select @msg2 = db_name()
		print @msg, @msg2
	end
end
else
begin
	/*
	** User has specified a table.
	** Check to see that the table name is local to the current database.
	*/
	if (@tab_name like '%.%.%')
	begin
		/* 17862, "Table must be in the 'current' database." */
		raiserror 17862
		return (1)
	end

	/*
	** Now, see if the table actually exists.
	*/
	if (object_id(@tab_name) is null)
	begin
		/* 17863, "There is no table named %1! in the 'current' database." */
		raiserror 17863, @tab_name
		return (2)
	end

	/*
	** Now, check for any suspect indexes on this table.
	*/
	if exists (select * from sysindexes i
			where i.id = object_id(@tab_name)
			  and (i.status & @ind_suspect) != 0)
	begin
		/* 17864, "Suspect indexes on table %1!:" */
		exec sp_getmessage 17864, @msg output
		print @msg, @tab_name

		select
                        "Own.Tab.Ind (Obj_ID, Ind_ID)" =
				u.name + "." + o.name + '.' + i.name +
				' (' + convert(varchar, o.id) + ', ' +
				convert(varchar, i.indid) + ')'
		from
			sysobjects o,
			sysindexes i,
			sysusers u
		where
			o.id = i.id
		    and o.uid = u.uid
		    and o.id = object_id(@tab_name)
		    and (i.status & @ind_suspect) != 0
	end
	else
	begin
		/* 17865, "There are no suspect indexes on table %1!." */
		exec sp_getmessage 17865, @msg output
		print @msg, @tab_name
	end
end
return (0)
go
exec sp_procxmode 'sp_indsuspect', 'anymode'
go
grant execute on sp_indsuspect to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpartition')
begin
	drop procedure sp_helpartition
end
go
print "Installing sp_helpartition"
go

/*
** Messages for "sp_helpartition"          
**
** 17460, "Object must be in the current database."
** 17733, "There is no table named '%1!'."
** 17734, "There is no index named '%1!' for table '%2!'."
** 19305, "There is no partition named '%1!' for table '%2!', index '%3!'."
** 19337, "Text is encrypted"
** 19340, "Warning: Configuration Parameter 'allow select on syscomments.text' 
**	   is set to 0. Only the object owner or user with sa_role can access 
**	   the text. The text for the partition condition cannot be displayed."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
**
** Parameters:
**	@tabname	- if null, the number of partitions for all
**			  user tables are reported
**	@indexname	- if null, the partition info of the base table
**			  is reported
**			- if 'all', the partition info of all indexes,
**			  including the base table(if there is no clustered
**			  index on the table), will be reported, but no
**			  partition level detailed information.
**			- else, the partition info of that particular index
**			  including all partition level details will be
**			  reported.
**	@partitionname	- if null, the partition info of that particular index
**			  including all partition level details will be
**			  reported.
**			- if specified, the partition info of that particular 
**			  index and the partition level detail of that 
**			  particular partition is reported.
*/
create procedure sp_helpartition
@tabname varchar(767) = NULL,		/* the table to check for partitions */
@indexname varchar(255) = NULL,
@partitionname varchar(255) = NULL
as

declare	@tableid	int,
	@indexid	int,
	@dbid		int,
	@use_savedname	int,
	@columnname	varchar(255),
	@columnlist	varchar(1024),
	@indid		smallint,
	@current_indid	smallint,
	@indextype	varchar(16),
	@datapage_indid	smallint,
	@ptntype	smallint,
	@typename	varchar(12),
	@condid		int,
	@range		smallint,
	@hash		smallint,
	@roundrobin	smallint,
	@list		smallint,
	@config_parm	int,
	@hiddenmsg	varchar(255),
	@disallowmsg	varchar(255),
	@ptnid		int,
	@avg_pages	int,
	@max_pages	int,
	@min_pages	int,
	@datapage_ptnid int

if @@trancount = 0
begin
	set transaction isolation level 1
	set chained off
end

/* 
** Since different partition types have different information content,
** we need to find the partition types first.
*/

select @range = v.number from master.dbo.spt_values v 
		where v.type = 'PN' and v.name = 'range' 
select @hash = v.number from master.dbo.spt_values v 
		where v.type = 'PN' and v.name = 'hash'
select @roundrobin = v.number from master.dbo.spt_values v  
		where v.type = 'PN' and v.name = 'roundrobin'
select @list = v.number from master.dbo.spt_values v   
		where v.type = 'PN' and v.name = 'list'

set nocount on

/*
**  If no object name is specified, print all user tables in the database 
*/
if @tabname is null
begin
 
select "owner" = user_name(uid), o.name
	, "partitions" = (select count(*)
			  from syspartitions p
			  where p.id = o.id
			    and p.indid < 2 )
	, "partition_type" = (select v.name
			      from master.dbo.spt_values v
			      where v.type = 'PN'
				and v.number = isnull(i.partitiontype, @roundrobin))
into #all_tables
from sysobjects o, sysindexes i
where o.type = "U" and o.id = i.id and i.indid < 2

exec sp_autoformat @fulltabname = "#all_tables", @orderby = "order by 1, 2"
-- order by 1,2

return 0

end

/*
**  Check to see that the object names are local to the current database.
*/
if @tabname like '%.%.%' and 
	substring(@tabname, 1, charindex('.', @tabname) - 1) != db_name()
begin
       	/* 17460, "Object must be in the current database." */
       	raiserror 17460
       	return (1)
end

/*
**  Check to see that the table exists
*/
if not exists (select 1 from sysobjects 
	       where id = object_id(@tabname)
	         and (type = 'S' or type = 'U'))
begin
	/** 17733, "There is no table named '%1!'."*/
	raiserror 17733, @tabname
	return (1)
end

select @tableid = object_id(@tabname)
	, @dbid = db_id()

/* 
** Check validity of tablename with index name if provided
*/
if @indexname is not null and @indexname != 'all' and  
	not exists (select 1
		    from sysindexes
                    where id = @tableid 
                    	and name = @indexname)
begin
        /* 17734, "There is no index named '%1!' for table '%2!'."*/
        raiserror 17734, @indexname, @tabname
        return (1)
end

/*
** If partion name is provided make sure the name is a valid
** partition on the given index, or on the table if the
** index is null
*/
if @indexname != 'all'  
begin
	select @indexid = indid
		from sysindexes 
		where id = @tableid
		      and ((@indexname is null and indid < 2) 
			   or name = @indexname) 
	
	/*
	** If user didn't specify index name, it implicitly
	** means the base table, but for table with clustered
	** index, the partition name for base table is moved
	** to savedname in syspartitions. In this case, we need
	** to check the savedname to see if the partition name
	** given is valid.
	*/
	if @indexname is null and @indexid = 1
		select @use_savedname = 1
	else
		select @use_savedname = 0

	if @partitionname is not null and 
		not exists (select 1
                	from syspartitions 
                        where id = @tableid 
			      and indid = @indexid 
			      and ((@use_savedname = 0 
					and name = @partitionname)
				   or (@use_savedname = 1
				       and cdataptnname = @partitionname)))
	/*
	**  Partition doesn't exist on this index so return.
	*/
	begin
		/*
		** 19305, "There is no partition named '%1!' for table '%2!', 
		** index '%3!'."
		*/
		if @indexname is null
			raiserror 19305, @partitionname, @tabname, @tabname
		else
			raiserror 19305, @partitionname, @tabname, @indexname
		return (1)
	end
end
/*
** If table name is given then we want to create a list of
** column names that represent the partionkeys. Here
** we create a temp table that holds the id, indid, and
** the colname list of the partition keys in the form
** (col1, col2, col3, ...). We can then join this to the
** output below.
*/

declare keycursor cursor for
select distinct c.name, k.indid 
from syspartitionkeys k, syscolumns c
where k.id = @tableid
      and k.id = c.id
      and c.colid = k.colid
order by k.indid, k.position
for read only

/*
** Create a temp table to hold the partition key list for each table/index.
** There could be maximum of 31 keys, MAXNAME is 30, plus commas between 
** columns, varchar(1024) would be enough to hold the key list.
** Here we specify all columns to be not null and lock allpages to avoid
** renormalization/recompile of this stored procedure when the default
** dboptions change.
*/ 
create table #col_names (
	indid smallint not null, 
	col_name_list varchar(1024) null)
lock allpages

/* We are expecting to have exactly one row for every index in this table. */
create unique clustered index col_names_uniqind on #col_names(indid)

open keycursor


select @columnlist = "", @current_indid = -1

fetch keycursor into @columnname, @indid

while(@@sqlstatus = 0)
begin
	/* If first row, set current_indid and columnlist */
	if (@@rowcount = 1)
	begin
       		select @columnlist = @columnname 
       		select @current_indid = @indid
	end
	/* If next row of same index, concate the columnlist */
        else if (@current_indid = @indid)
        begin
                select @columnlist = @columnlist + ', ' + @columnname
        end

	/*
	** If next index, insert the columnlist for previous index,
	** and reset the current_indid and columnlist.
	*/
        else 
        begin
                insert #col_names values
                                (@current_indid, @columnlist)
                select @columnlist = @columnname
                select @current_indid = @indid
        end

	fetch keycursor into @columnname, @indid
	
	/*
	** If end of cursor, just insert the columnlist for previous
	** index, if there had been one.
	*/
	if (@@sqlstatus = 2)
	begin
		insert #col_names values
     			(@current_indid, @columnlist)
	end
end

close keycursor

deallocate cursor keycursor

/*
** Roundrobin partitioned table may have a fake partition
** key if there is a global clustered index on it, need to
** exclude these keys by detecting the partition type is rrobin.
*/
update #col_names set col_name_list = NULL 
	where exists (select 1 from sysindexes i, master.dbo.spt_values v 
		      where     i.id = @tableid 
			    and i.indid = #col_names.indid 
			    and isnull(i.partitiontype, @roundrobin) = v.number 
			    and v.type = 'PN'
			    and v.name = 'roundrobin'
		     )


/*
** Insert into the #temp table indexes where there is no partition
** columns and the partition columns will be inserted as NULL.
*/
insert #col_names select i.indid, NULL 
		  from sysindexes i 
		  where id = @tableid and not exists
			(select 1 
			from syspartitionkeys k
		  	where k.id = @tableid and i.indid = k.indid)

/*
** Print partition information when 'all' is specified for index 
** When "all" is specified, for each indexes in the table, we
** print the index's name, index type, partition type, partition key
** and number of partitions
*/
if (@indexname = 'all')
begin
	select 'name' = i.name, 
		'type' = case when i.indid = 0 then 'base table'
			      when i.indid = 255 then 'text/image'
			      when i.status3 & 8 = 8 then 'local index'
			      else 'global index'
			 end,
		'partition_type' = v.name,
		'partitions' = (select count(*)
				from syspartitions p
				where p.id = @tableid
				  and p.indid = i.indid

			       ),
		'partition_keys' = n.col_name_list
	into #result_all lock allpages
	from sysindexes i, #col_names n, master.dbo.spt_values v
	where i.id = @tableid
	  and i.indid = n.indid
	  and v.number = isnull(i.partitiontype, @roundrobin)
	  and v.type = 'PN'

	exec sp_autoformat #result_all

	return (0)
end

/*
** When we get here, the indexname is null or specificaly specified,
** print partition information for base table or the specified
** index. According to the partition type of base table or this
** index, we print related information. No matter partition name
** is specified or not, we always print a header information at
** index level, maily the partition type, number of partitions
** and partition keys if applicable. Then, if partition name is
** specified, we print the information of that partition, other
** wise, we will print the information of each partition and a
** summary info of these partitions.
*/

/* Get index type, ptntype, partition key */
select @ptntype = isnull(i.partitiontype, @roundrobin), 
       @condid = i.conditionid,
       @columnlist = n.col_name_list,
       @indextype = 
		case
			when i.indid = 0 or @indexname is null 
				then 'base table'
			when i.indid = 255 then 'text/image'
			when i.status3 & 8 = 8 then 'local index'
			else 'global index'
		end
from sysindexes i, #col_names n
where i.id = @tableid
	and i.indid = @indexid
	and i.indid = n.indid

/*
** Get the datapage_indid, which is the index id used in the builtin
** data_pages. For current implementation of this builtin, if user
** want the base table information, we have to passin 0 if the true
** index id is 1 in sysindexes, otherwise, we would get the pages
** only for the index part.
*/
if (@indexname is null)
	select @datapage_indid = 0
else
	select @datapage_indid = @indexid

select @typename = v.name 
from master.dbo.spt_values v
where v.type = 'PN' and v.number = @ptntype

/*
** For range and list partition, we will need to display the 
** partition condition text information, check the availability.
*/
select @hiddenmsg = NULL
select @disallowmsg = NULL

if @ptntype in (@range, @list)
begin
	/*
	** If the configuration parameter 'allow select on syscomments.text'
	** is set to 0, then the user can access the text ONLY in the
	** following cases
	**
	**      1. if the user has sa_role
	**      2. if the object is owned by the user
	**
	*/
	select @config_parm = value
		from master.dbo.syscurconfigs
		where config = 258


	if @config_parm = 0 and user_id() != 1
		and not exists (select name from sysobjects
					where uid = user_id()
					and id = @tableid)
	begin
		exec sp_getmessage 19340, @disallowmsg output
	end

	/* See if the partition condition text is hidden */
	else if exists (select 1 from syscomments c
			where c.id = @condid and (c.status & 1 = 1))
	begin
		exec sp_getmessage 19337, @hiddenmsg output
	end
end

/* Print the header information */
select 'name' = case 
			when @indexname is not null then @indexname
			else @tabname
		end, 
	'type' = @indextype,
	'partition_type' = @typename, 
	'partitions' = (select count(*) from syspartitions p
			where p.id = @tableid
			  and p.indid = @indexid),
	'partition_keys' = @columnlist
into #result_head lock allpages

exec sp_autoformat #result_head
print " "

/* Get each partition information */
create table #result_body(partition_name varchar(255) not null,
			  partition_id	int not null,
			  pages int not null,
			  row_count numeric(18,0) not null,
			  segment varchar(255) not null,
			  create_date datetime not null,
			  seqnum int not null)
			  lock allpages

create table #result_cond(Partition_Conditions varchar(255) null,
			  seqnum int not null, 
			  colid int not null, 
			  colid2 int not null)
			  lock allpages

if (@partitionname is not null)
begin

	select @ptnid = partitionid
	from syspartitions 
	where id = @tableid
      	      and indid = @indexid
       	      and ((@use_savedname = 1 and cdataptnname = @partitionname)
	   	    or name = @partitionname)
	insert #result_body
		select  'partition_name' = 
			case
				when @use_savedname = 1 then p.cdataptnname
				else p.name
			end,
			@ptnid,
			data_pages(@dbid, @tableid, @datapage_indid, @ptnid),
			case
				when (@datapage_indid > 1) then 0
				else row_count(@dbid, @tableid, @ptnid)
			end,
			s.name,
			p.crdate,
			0
		from syspartitions p, syssegments s
		where p.id = @tableid
			and p.indid = @indexid
			and p.segment = s.segment
			and p.partitionid = @ptnid

	/* Get partition condition */
	if @ptntype in (@roundrobin, @hash)
		insert #result_cond values (NULL,0,0,0)
	else if (@disallowmsg is null) and (@hiddenmsg is null)
		insert #result_cond
			select c.text, c.number, c.colid, c.colid2
			from syscomments c
			where c.id = @condid
		      		and c.partitionid = @ptnid 

end
		
/*
** If we come here, the partition name is not specified,
** we print the information for all partitions under this
** index.
** If range/list/hash partition, print the partitions in
** order their ptncond is stored in syscomments, this order
** is stored in the cnumber field of the syscomments row.
*/
else
begin
	if (@ptntype = @roundrobin)
	begin
	    insert #result_body
		select  'partition_name' = 
			case
				when @use_savedname = 1
					then p.cdataptnname
				else p.name
			end,
			p.partitionid,
			data_pages(@dbid, @tableid, @datapage_indid, 
					p.partitionid),
			case
				when (@datapage_indid > 1) then 0
				else row_count(@dbid, @tableid, p.partitionid)
			end,
			(select s.name from syssegments s
			 where s.segment = p.segment),

		        p.crdate,
			
			0
		from syspartitions p
		where p.id = @tableid
	              and p.indid = @indexid
	end
	else
	begin
	    insert #result_body
		select 'partition_name' = 
			case
				when @use_savedname = 1
					then p.cdataptnname
				else p.name
			end,
			p.partitionid,
			data_pages(@dbid, @tableid, @datapage_indid, 
					p.partitionid),
			case
				when (@datapage_indid > 1) then 0
				else row_count(@dbid, @tableid, p.partitionid)
			end,
			s.name,

			p.crdate,

			(select distinct c.number
			 from syscomments c
			 where c.id = @condid
			   and c.partitionid = p.partitionid)

		from syspartitions p, syssegments s
		where p.id = @tableid
	      	      and p.indid = @indexid
		      and p.segment = s.segment
	end

	/* Get partition condition */
	if (@ptntype = @roundrobin or @ptntype = @hash)
		insert #result_cond values (NULL,0,0,0)
	else if (@disallowmsg is null) and (@hiddenmsg is null)
		insert #result_cond
		select c.text, c.number, c.colid, c.colid2
		from syscomments c
		where c.id = @condid
end

if (@indexid > 1)
begin --{
	if (@indextype = 'text/image')
	begin --{
			/* 
			** This should be changed when we provide
			** per partition text partition to display
			** the number of rows in the corresponding
			** data partition.
			*/
                        update #result_body
                        set row_count = row_count(@dbid, @tableid)
	end --}
	else if (@indextype = 'global index')
        begin --{
                update #result_body
                set row_count
                        = row_count(@dbid, @tableid)
        end --}
        else
        begin --{
                if (@partitionname is not null)
                begin
                        select @datapage_ptnid = data_partitionid
                        from syspartitions
                        where id = @tableid and
                                partitionid = @ptnid
                        update #result_body
                        set row_count = row_count(@dbid, @tableid, 
							@datapage_ptnid)
                end
                else
                begin
                        update #result_body
                        set row_count = row_count(@dbid, @tableid, 
							s.data_partitionid)
                        from syspartitions as s, #result_body as r
                        where s.id = @tableid and
                                s.partitionid = r.partition_id
                end
        end --}
end --}

/* 
** Pretty printing using sp_autoformat.
** since the partition condition text could be big,
** we print it in a separate section from other partition
** information. But we print the partition condition for
** each partition in certain order, so that the first
** partition condition printed is the first partition
** shown in previous section (#result_body).
*/
exec sp_autoformat #result_body, 'partition_name, partition_id, pages,row_count,segment,create_date', NULL, 'order by seqnum, partition_id'

print " "

/*
** The following part prints the partition condition when applicable.
** If we are not allowed to select from syscomments.text (@disallowmsg
** is not null), then just print the disallow message. If the partition
** condition text is hidden, we insert the hidden message in the result
** table, so it will show in the place where partition condition text
** will show.
*/
if @disallowmsg is not null
	print @disallowmsg	
else
begin
	if @hiddenmsg is not null
		insert #result_cond values (@hiddenmsg,0,0,0)
	 
	exec sp_autoformat #result_cond, 'Partition_Conditions', 
		NULL, 'order by seqnum,colid2,colid'
end

/*
** Print the summary statistic information when more than one partitions
** are displayed.
*/
if @partitionname is not null
	return (0)

print " "

select @avg_pages = avg(data_pages(@dbid, @tableid, @datapage_indid, 
					partitionid)),
       @max_pages = max(data_pages(@dbid, @tableid, @datapage_indid, 
					partitionid)),
       @min_pages = min(data_pages(@dbid, @tableid, @datapage_indid, 
					partitionid))
from syspartitions
where id = @tableid
	and indid = @indexid

select 'Avg_pages' = @avg_pages, 
       'Max_pages' = @max_pages, 
       'Min_pages' = @min_pages,
       'Ratio(Max/Avg)' = 
		case 
			when @avg_pages = 0 then 0
			else convert(float, @max_pages)/@avg_pages
		end,
	'Ratio(Min/Avg)' =
		case
			when @avg_pages = 0 then 0
			else convert(float, @min_pages)/@avg_pages
		end

set nocount off
return (0)
go
exec sp_procxmode 'sp_helpartition', 'anymode'
go
grant execute on sp_helpartition to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_tab_suspectptn')
begin
	drop procedure sp_tab_suspectptn
end
go
print "Installing sp_tab_suspectptn"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages from sysmessages
**
** 17862, "Table must be in the 'current' database."
** 17863, "There is no table named %1! in the 'current' database."
** 19649, "Suspect partitioning in database %1!:"
** 19650, "There are no suspect partitioning in database %1!."
** 19651, "Suspect partitioning on table %1!:"
** 19652, "There are no suspect partitioning on table %1!."
*/

/*
**      Procedure sp_tab_suspectptn
**
**	Range-partition table on char-based partition keys can become
**	suspect after sort order change. Hash-partitioned table can
**	become suspect after cross-platform dump load. This procedure 
**	provides the administration interface for listing the table(s)
**	with suspect partitioning. The IND3_PTN_SUSPECT is set at table
**	level. Either all partitions in a table are suspect, or no 
**	partition is suspect.
**      
*/

create procedure sp_tab_suspectptn
@tab_name varchar(767) = NULL		/* if NULL, check all tables in db */
AS

declare @msg		varchar(1024)	/* used for message to user */
declare @msg2		varchar(256)	/* used for table/db name */
declare @ptn_suspect	smallint	/* value of IND3_PTN_SUSPECT bit */


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

/* 
** Specify the bit mask as 16, not in hex notation, for portability
** to byte-swapped platforms.  This could break on a 1's complement 
** platform, but there isn't really a better solution.  SQL handles 
** hex numbers as binary data, not as numeric values as in C.
*/

select @ptn_suspect = 16

if (@tab_name is null)
begin
	/*
	** No table name specified, sp search for any
	** suspected partitions in the entire database.
	*/
	if exists (select * from sysindexes i
			where (i.status3 & @ptn_suspect) != 0)
	begin
		/* 19649, "Suspect partitioning in database %1!:" */
		exec sp_getmessage 19649, @msg output
		select @msg2 = db_name()
		print @msg, @msg2

		select
                        "Partition type, Own.Tab.Ind (Obj_ID, Ind_ID)" =
				v.name+","+u.name + "." + o.name + '.' + i.name +
				'.' +' (' + convert(varchar, o.id) + 
				', ' + convert(varchar, i.indid) + ')'
		from
			sysobjects o,
			sysindexes i,
			sysusers u,
			master.dbo.spt_values v
		where
			o.id = i.id
		    and o.uid = u.uid
		    and i.partitiontype = v.number
		    and v.type = 'PN'
		    and (i.status3 & @ptn_suspect) != 0
	end
	else
	begin
		/* 19650, "There are no suspect partitioning in database %1!." */
		exec sp_getmessage 19650, @msg output
		select @msg2 = db_name()
		print @msg, @msg2
	end
end
else
begin
	/*
	** User has specified a table.
	** Check to see that the table name is local to the current database.
	*/
	if (@tab_name like '%.%.%')
	begin
		/* 17862, "Table must be in the 'current' database." */
		raiserror 17862
		return (1)
	end

	/*
	** Now, see if the table actually exists.
	*/
	if (object_id(@tab_name) is null)
	begin
		/* 17863, "There is no table named %1! in the 'current' database." */
		raiserror 17863, @tab_name
		return (2)
	end

	/*
	** Now, check for any suspect partitioning on this table.
	*/
	if exists (select * from sysindexes i
			where i.id = object_id(@tab_name)
			  and (i.status3 & @ptn_suspect) != 0)
	begin
		/* 19651, "Suspect partitioning on table %1!:" */
		exec sp_getmessage 19651, @msg output
		print @msg, @tab_name

		select
                        "Partition Type, Own.Tab.Ind.Ptn (Obj_ID, Ind_ID, Ptn_ID)" =
				v.name+", "+u.name + "." + o.name + '.' + i.name +
				'.' + p.name +' (' + convert(varchar, o.id) + 
				', ' + convert(varchar, i.indid) + 
				', ' + convert(varchar, p.partitionid) + ')'
		from
			sysobjects o,
			sysindexes i,
			sysusers u,
			syspartitions p,
	                master.dbo.spt_values v
		where
			o.id = i.id
		    and o.uid = u.uid
		    and i.id = p.id
		    and i.indid = p.indid
		    and i.partitiontype = v.number
	            and v.type = 'PN'
		    and o.id = object_id(@tab_name)
		    and (i.status3 & @ptn_suspect) != 0
	end
	else
	begin
		/* 19652, "There are no suspect partitioning on table %1!." */
		exec sp_getmessage 19652, @msg output
		print @msg, @tab_name
	end
end
return (0)
go
exec sp_procxmode 'sp_tab_suspectptn', 'anymode'
go
grant execute on sp_tab_suspectptn to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_params')
begin
	drop procedure sp_help_params
end
go
print "Installing sp_help_params"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:38 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/help_params [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/help_params [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

/*
** sp_help_params
**
**	Servant sproc to sp_help to pull out column related information
**	for a procedure, trigger, or SQL-J functions. It is assumed that the
** 	caller has validated tha the object exists, and is one of these kinds.
**	If not, you will just get no rows back, which will still be ok.
** 	(Currently, this is just an internal proc. If it gets to be used as
**	user-visible proc, we need updates to check for @objname etc.)
**
** Parameters:
**	@objname	- Name of object, possibly multi-part
**
** Returns:	Nothing.
{
*/
create procedure sp_help_params( @objname	varchar(767)
) as
begin
	declare @sptlang	int
	      , @grp_count	int
	      , @selectlist_str	varchar(80)
	      , @orderby_str	varchar(40)

	-- Does the sproc have any parameters? It not, nothing to do here.
	if not exists (select 1
			from syscolumns c, systypes t
			where c.id = object_id(@objname)
			  and c.usertype *= t.usertype)
		return 0

	select @sptlang = @@langid

	if (@sptlang != 0)	-- User has defined a non-default language
	begin
		if not exists (select * from master.dbo.sysmessages
				where error between 17100 and 17109
				  and langid = @@langid)
		    select @sptlang = 0
	end

	set nocount on

end
	-- Parameter_name _can_ be NULL for SQL-J functions, as per
	-- the SQL-J spec, but currently we don't allow that. Even 
	-- if we do so in the future, the name will come out as
	-- NULL, which is ok. Now, we do convert() to varchar() NULL
	-- as this is used to create a new table, and inserting NULL
	-- name will cause a problem at run-time.
	--
	select Parameter_name = convert(varchar(255) NULL, c.name),
	       Type = isnull(convert(char(30), x.xtname), 
			isnull(convert(char(30), 
				get_xtypename(c.xtype, c.xdbid)), 
			t.name)),
	       Length = c.length,
	       Prec = c.prec,
	       Scale = c.scale,
	       Param_order = c.colid,
	       Grp_number = c.number,
	       rtype = t.type, 
	       utype = t.usertype,

			/*
			** Handle the case where upgraded databases
			** have syscolumns.status2 as NULL. Report
			** those as 'unknown' parameter types.
			*/
	       Mode = case c.status2 
			when NULL then "unknown"
			else (select convert(nvarchar(20), mi.description)
			      from   master.dbo.spt_values vi
				   , master.dbo.sysmessages mi
			      where vi.number = c.status2
				and vi.msgnum = mi.error
				and isnull(mi.langid, 0) = @sptlang
				and mi.error between 17583 and 17586)
		      end
	into #helpproc
	from syscolumns c, systypes t, sysxtypes x
		where c.id = object_id(@objname)
			and c.usertype *= t.usertype
			and c.xtype *= x.xtid
	
	 /*  If it is a procedure group, grp_count>1 */
	 select @grp_count = count(distinct Grp_number)
	 from #helpproc
	
	/* Handle National Characters */
	update #helpproc
		set Length = Length / @@ncharsize
		where (rtype = 47 and utype = 24)
		   or (rtype = 39 and utype = 25)

	/* Handle unichar/univarchar */
	update #helpproc
		set Length = Length / @@unicharsize
		where rtype in (select type from systypes
			where name in ('unichar', 'univarchar'))

	/* Handle unsigned types by outputing user syntax */
	update #helpproc
		set Type = "unsigned " + 
			substring(Type, charindex("u", Type) + 1, 30)
		where utype in (44, 45, 46)

	/*  For display, group by group number too in case
	**  it is a procedure group
	*/
	if(@grp_count = 1)
	begin
		select @selectlist_str = "Parameter_name,Type,Length,Prec,Scale,Param_order,Mode"
		     , @orderby_str = "order by Param_order asc"
	end
	else
	begin
		select @selectlist_str = "Parameter_name,Type,Length,Prec,Scale,Param_order,Mode,Grp_number"
		     , @orderby_str = "order by Grp_number asc, Param_order asc"
	end

	exec sp_autoformat @fulltabname = #helpproc,
			   @selectlist = @selectlist_str,
			   @orderby = @orderby_str
	drop table #helpproc
go

if (@@sqlstatus != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_help_params', 'anymode'
go
grant execute on sp_help_params to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help')
begin
	drop procedure sp_help
end
go
print "Installing sp_help"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:38 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/help [Total 2]
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/help [Total 18]
**
** 17570, "Operating System File"
** 17571, "---------------------"
** 17573, "Object is Remote/External"
** 17574, "-------------------------"
** 17575, "Object created with 'existing' option"
** 17576, "Lock scheme Allpages"
** 17577, "Lock scheme Datapages"
** 17578, "Lock scheme Datarows"
** 17579, "Lock scheme is unknown or is corrupted"
** 17581, "Trigger is disabled."
** 17582, "Trigger is enabled."
** 18571, "The attribute '%1!' is not applicable to tables with allpages lock scheme."
** 18983, "The '%1!' attribute is not applicable to tables with datarow or datapage lock schemes."
** 19334, "Warning: Configuration Parameter 'allow select on syscomments.text' is set to 0. Only the object owner or user with sa_role can access the text. The text for the computed column(s) cannot be displayed."
** 19335, "Warning: Configuration Parameter 'allow select on syscomments.text' is set to 0. Only the object owner or user with sa_role can access the text. The text for the functional index key(s) cannot be displayed."
** 19337, "Text is encrypted."
** 19456, "Object is a computed column in table '%1!'."
** 19457, "Object is a function-based index key in table '%1!'."
*/
/*
** End spgenmsgs.pl output.
*/
go
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_help"               17570
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
** 17570, "Operating System File"
** 17571, "---------------------"
** 17573, "Object is Remote/External"
** 17574, "-------------------------"
** 17575, "Object existed prior to Omni"
** 17576, "Lock scheme is Allpages" 
** 17577, "Lock scheme is Datapages"
** 17578, "Lock scheme is Datarows" 
** 17579, "Lock scheme Unknown or Corrupted" 
** 17581, "Trigger is disabled."
** 17582, "Trigger is enabled."
** 18571, "The attribute '%1!' is not applicable to tables with allpages lock scheme."
** 17589, "computed column"
** 19456, "Object is a computed column in table '%1!'."
** 19457, "Object is a function-based index key in table '%1!'."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_help
@objname varchar(767) = NULL			/* object name we're after */
as

declare @typeid int				/* type of object in systypes */
declare @basetypeid int				/* base type in systypes */
declare @lenfactor int				/* length factor */
declare @sysstat smallint			/* the type of the object */
declare @OS_file varchar(255)			/* physical file for ext tab */
declare @msg varchar(1024)
declare @sptlang	int
declare @len1 int, @len2 int, @len3 int, @len4 int, @len5 int, @len6 int, @sysstat2 int
declare @sqltext varchar(1024)			/* SQL to execute using execute
						** immediate. */
declare @and_access	int /* cache bits in OBJECT.sysstat2 */
declare @or_access	int /* cache bits in OBJECT.sysstat2 */

declare @sqlj_proc      int /* indicates a sqlj proc */
declare @opt_ind_status	int /* status of optimistic index lock */
declare @opt_ind_value	int /* user input value of optimistic index lock */
declare @opt_ind_lock	int /* Server constant for optimistic index lock */
declare @opt_text_dealloc int
declare @opt_text_value int
declare @opt_ind2_ascinserts int /* Server constant for ascinserts */
declare @text_dealloc   int
declare @encrypted_col	int /* indicates encrypted col */	
declare @decrypt_def     int /* indicates decrypt default col */
declare @thiskey        varchar(30)		/* index key column of 
						** virtually hashed table. 
						*/ 
declare @indid          int			
declare @new_char_value varchar(255)		/* hash factors of virtually 
						** hashed table. 
						*/
declare @num_keys       int			/* #index keys columns. */
declare @key_count      int,
	@msgnum		int,
	@valstat3	int,
	@sysstat3	int,
	@sep		varchar(2),
	@sysopt_name	varchar(100)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	    select @sptlang = 0
end

set nocount on

/*
**  If no @objname given, give a little info about all objects.
**  Note: 0x80f is the mask for sysstats (=2063decimal).
** 	  800 is used by Stratus for external tables.
*/

select  @sqlj_proc = hextoint("0x2000000")

if @objname is NULL
begin
	/*
	** Instead of Triggers are sub_types of trigger
	** type; so first check for sysstat to be 8, then build the
	** prefix of "instead of" for the trigger if needed.
	*/
	    select Name = o.name,
		Owner = user_name(uid),
		Object_type = (case
				when ((o.sysstat & 15) = 8)
				then (case
					when (o.type = "IT")
					then "instead of "
					else    null
					end)
				else null
				end
				)
				+ (m.description + x.name)
	    into #sphelp1rs
			from sysobjects o, master.dbo.spt_values v,
			master.dbo.spt_values x, master.dbo.sysmessages m
		where o.sysstat & 2063 = v.number 
			 and ((v.type = "O" and 
	                    (o.type != "XP" and (o.sysstat2 & @sqlj_proc) = 0))
			    or (v.type = "O1" and o.type = "XP") or
			    (v.type = "O2" and (o.sysstat2 & @sqlj_proc) != 0)
			    or (v.type = "EK" and o.type = "EK"))
			and v.msgnum = m.error
			and isnull(m.langid, 0) = @sptlang
			and ((m.error between 17100 and 17109) or
			     (m.error between 17587 and 17589) or
			     (m.error between 18903 and 18904) or
			     (m.error = 17588 or m.error = 17139))			
			and x.type = "R"
			and o.userstat & -32768 = x.number
	    exec sp_autoformat @fulltabname = #sphelp1rs,
		@orderby = "order by 3 desc, 1 asc"
	    drop table #sphelp1rs

	    select User_type = s.name,
		Storage_type = st.name,
		Length = s.length,
		Nulls = s.allownulls,
		Default_name = object_name(s.tdefault),
		Rule_name = object_name(s.domain),
		Access_Rule_name = object_name(s.accessrule)
	   into #sphelp2rs
		from systypes s, systypes st
		    where s.type = st.type
			and s.usertype > 99
			and st.name not in ("sysname", "longsysname", "nchar", "nvarchar")
			and st.usertype < 100
	   exec sp_autoformat @fulltabname = #sphelp2rs,
		@orderby = "order by 1"
	   drop table #sphelp2rs

	/* Display list of Java classes installed in this database */
	print ""
	select Class_name =  x.xtname, 
		Jar_name = isnull(j.jname, '')
	into #sphelp3rs
		from sysxtypes x, sysjars j
		where x.xtcontainer *= j.jid
	exec sp_autoformat @fulltabname = #sphelp3rs,
		@orderby = "order by 1"
	drop table #sphelp3rs

	/* Display list of Java JARs installed in this database */
	print ""
	exec sp_autoformat @fulltabname = sysjars,
		@selectlist = "'Jar_name' = jname",
		@orderby = "order by 1"
	print ""
	return (0)
end

/*
** If this is a 4-part object name, mangle the name appropriately.
** [Note: this must be run in tempdb for successful results.]
*/
if @objname like "%.%.%.%"
begin
	select @objname = str_replace(@objname, '.', '_')
end

/*
**  Make sure the @objname is local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return  (1)
end

/*
**  Now check to see if the @objname is in sysobjects.  It has to be either
**  in sysobjects or systypes.
*/
if not exists (select *
	from sysobjects
		where id = object_id(@objname))

/*
**  It wasn't in sysobjects so we'll check in systypes.
*/
begin
	select @typeid = usertype, @basetypeid = type
		from systypes
			where name = @objname

	/*
	**  Time to give up -- @objname is not in sysobjects or systypes.
	*/
	if @typeid is NULL
	begin
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return  (1)
	end

	/*
 	** Get length factor: types based on unichar/univarchar
	** are 2 bytes per character.
	*/
	if (@basetypeid in (select type from systypes where
			name in ('unichar', 'univarchar')))
		select @lenfactor = @@unicharsize
	else
		select @lenfactor = 1

	/*
	** Print help about a data type
	*/

	    select Type_name = s.name,
		   Storage_type = st.name,
		   Length = s.length/ @lenfactor,
		   Nulls = s.allownulls,
		   Prec = s.prec,
		   Scale = s.scale,
		   Default_name = object_name(s.tdefault),
		   Rule_name = object_name(s.domain),
		   Access_Rule_name = object_name(s.accessrule),
		   Ident = s.ident
	    into #sphelp4rs
		from systypes s, systypes st
		    where s.usertype = @typeid
			and s.type = st.type
			and st.name not in ("timestamp", "sysname", "longsysname", "nchar", "nvarchar")
			and st.usertype < 100
	   exec sp_autoformat @fulltabname = #sphelp4rs,
		@selectlist = "Type_name, Storage_type,Length,Prec,Scale,Nulls,Default_name,Rule_name,Access_Rule_name,'Identity' = Ident"
	   drop table #sphelp4rs

	return (0)
end

/*
**  It's in sysobjects so print out the information.
*/

/* 
** Define status bit values for O2_ACCESS_CONTROL
** and O2_OR_ACCESS_CONTROL.
*/
select	@and_access = hextoint("0x1000000"),
	@or_access = hextoint("0x4000000")

select	Name = o.name, 
	Owner = user_name(uid), 

	/*
	** Decode object type, and figure out if its an access rule
	** type. Access rules are sub-types of the rule type; so
	** first check for sysstat to be 7. Build the prefix of
	** 'AND access', or 'OR access', or '' strings. The prefix
	** will be concatenated to the string 'rule' as obtained
	** from the other tables.
	** Meanwhile, Instead of Triggers are sub_types of trigger
	** type; so first check for sysstat to be 8, then build the
	** prefix of "instead of" for the trigger if needed.
	*/
	Object_type = (case	
			when ((o.sysstat & 15) = 7)
			then (case 
				when ( ((o.sysstat2 & @and_access) > 0)
					and ((o.sysstat2 & @or_access) > 0))
				then "OR access"
				when ((o.sysstat2 & @and_access) > 0)
				then "AND access"
				else          null
				end
				)
			 when ((o.sysstat & 15) = 8)
			 then (case
				when (o.type = "IT")
				then "instead of "
				else	null
				end)
			else null
			end
			)
			+ (m.description + x.name)
	, Object_status = convert(varchar(255), ' ')
	, Create_date = o.crdate
	into #sphelp5rs
	from sysobjects o, master.dbo.spt_values v,
		master.dbo.spt_values x, master.dbo.sysmessages m
	where o.id = object_id(@objname)
		and o.sysstat & 2063 = v.number
		and ((v.type = "O" and
		     (o.type != "XP" and (o.sysstat2 & @sqlj_proc) = 0)) or
		     (v.type = "O1" and o.type = "XP") or
		     (v.type = "O2" and (o.sysstat2 & @sqlj_proc) != 0) or
		     (v.type = "EK" and o.type = "EK"))
		and v.msgnum = m.error
		and isnull(m.langid, 0) = @sptlang
		and ((m.error between 17100 and 17199) or
		     (m.error between 17587 and 17589) or
		     (m.error between 18903 and 18904) or
		     (m.error = 17588)) 
		and x.type = "R"
		and o.userstat & -32768 = x.number

	/* Set Object_status to show any special status the object may have */
	select @sysstat3 = sysstat3
	from sysobjects
	where id = object_id(@objname)

	select @valstat3 = min(number), @sep = ''
	from master.dbo.spt_values
	where type = 'O3'
	  and number > 0
	  and number & @sysstat3 = number
	while (@valstat3 is not null)
	begin
		select @msgnum = msgnum, @sysopt_name = name
		from master.dbo.spt_values
		where type = 'O3' and number = @valstat3

		select @sysopt_name = isnull(description, @sysopt_name)
		from master.dbo.sysmessages
		where error = @msgnum
		  and isnull(langid, 0) = @sptlang

		update #sphelp5rs
		set Object_status = ltrim(Object_status + @sep + @sysopt_name)
		from #sphelp5rs a, master.dbo.spt_values v, sysobjects o
		where a.Name = o.name
		  and o.sysstat & 15 = 3
		  and o.sysstat3 & @valstat3 = @valstat3

		select @valstat3 = min(number), @sep = ', '
		from master.dbo.spt_values
		where type = 'O3'
		  and number > @valstat3
		  and number & @sysstat3 = number
	end

	update #sphelp5rs
	set Object_status = (select description
				from master.dbo.sysmessages
				where error = 17661
				  and isnull(langid, 0) = @sptlang)
	where datalength(Object_status) < 2

	exec sp_autoformat @fulltabname = #sphelp5rs
	drop table #sphelp5rs


/*
**  Objects have the following value for sysstat & 15:
**	0 - trigger
**	1 - system table
**	2 - view
**	3 - user table
**	4 - sproc
**	5 - predicated privilege
**	6 - default
**	7 - rule
**	8 - trigger
**	9 - referential constraint
**	10 - sql function  
**      12 - sqlj function
**      13 - computed column
**	
**
**  If the object is a system table, view, or user table, we want to check
**  out the objects columns here.
*/

select @sysstat = sysstat, @sysstat2 = sysstat2
	from sysobjects
		where id = object_id(@objname)

/*
**  Fix of bug 91669:
**  For the current design, a view having nameless column may be created,
**  e.g. create view view1 as select sum(column1) from table1. 
**  In this case, c.name is NULL. Using builtin function isnull() to  
**  make the following query work. 
*/

select  @encrypted_col = hextoint("0x00000080")
select  @decrypt_def = hextoint("0x00001000")

if @sysstat & 15 in (1, 2, 3)
begin
	select Column_name = isnull(c.name, 'NULL'),
	       Col_order = colid,
	       Type = isnull(convert(char(30), x.xtname), 
				isnull(convert(char(30),
					get_xtypename(c.xtype, c.xdbid)),
				t.name)), 
	       Length = c.length,
	       Prec = c.prec,
	       Scale = c.scale,
	       Nulls = convert(bit, (c.status & 8)),
	       Default_name = object_name(c.cdefault),
	       Rule_name = object_name(c.domain),
	       Access_Rule_name = object_name(c.accessrule),
	       Computed_Column_object = 
		case when (c.status3 & 1) = 1
		     then object_name(c.computedcol)+
				" (functional index key)"
		     when (c.status2 & 32) = 32
		     then object_name(c.computedcol)+" (materialized)"
		     when (c.status2 & 16) = 16
		     then object_name(c.computedcol)+" (virtual)" 
		     else object_name(c.computedcol)
		end,
	       rtype = t.type, utype = t.usertype, xtype = c.xtype,
	       Ident = convert(bit, (c.status & 0x80)),
	       Encrypted = 
			case when (c.status2 is null) then 0 
			     when (c.status2 & @encrypted_col) > 0 then 1
			end,
	       Decrypt_Default_name =
                        case when (c.status2 is null) then NULL 
			     when (c.status2 & @decrypt_def) > 0 then 
				(select object_name(a.object)
				 from sysattributes a
                                 where a.class = 25
                                    and a.attribute = 1
                                    and a.object_info1 = c.id
           			    and a.object_info2 = c.colid)
                             else NULL
			end,
	       Object_storage =                        
			case when (c.xstatus is null) then NULL
                             when (c.xstatus & 1) = 1 then "off row"
                             else                          "in row " end
	into #helptype
	from syscolumns c, systypes t, sysxtypes x
		where c.id = object_id(@objname)
			and c.usertype *= t.usertype
			and c.xtype *= x.xtid

	/* 
	** We truncate extended type names >30 characters to 30,
	** and print them with a trailing "+" character.
	*/
	update #helptype
		set Type = substring(Type, 1, 29) + "+"
		where xtype is not null
		      and substring(Type, 29, 1) != " "

	/* Handle National Characters */
	update #helptype
		set Length = Length / @@ncharsize
		where (rtype = 47 and utype = 24)
		   or (rtype = 39 and utype = 25)

	/* Handle unichar/univarchar */
	update #helptype
		set Length = Length / @@unicharsize
		where rtype in (select type from systypes
			where name in ('unichar', 'univarchar'))

        /* Handle unsigned types by outputing user syntax */
        update #helptype
                set Type = "unsigned " + 
			substring(Type, charindex("u", Type) + 1, 30)
                where utype in (44, 45, 46)

	/*
	** Construct the SQL query against #helptype. Be careful not to
	** exceed 255 characters, or the string will get truncated.
	*/
	    select @sqltext = "Column_name,Type, Length, Prec, Scale,Nulls,Default_name, Rule_name,Access_Rule_name,Computed_Column_object, 'Identity' = Ident"

	/* Display the Object_storage only if there are object columns. */
	if exists (select * from #helptype 
		   where Object_storage is not null)
	begin
		select @sqltext = @sqltext + ", Object_storage "
	end

	/* 
	** Display the Encrypted column status only if there are encrypted
	** columns.
	*/
	if exists (select * from #helptype 
		   where Encrypted != 0)
	begin
		select @sqltext = @sqltext + ", Encrypted "
	end


	/* 
	** Display the Decrypt_Default_name only if there 
	** are encrypted columns that have decrypt default values
	*/
	if exists (select * from #helptype 
		   where Decrypt_Default_name is not null)
	begin
		select @sqltext = @sqltext + ", Decrypt_Default_name"
	end

	exec sp_autoformat @fulltabname = #helptype,
		@selectlist = @sqltext,
		@orderby = "order by Col_order asc"
		
	drop table #helptype
end

/* 
** If this is a table object that has computed columns, display the
** computed column information.
*/
if (@sysstat & 15) in (1, 3)
begin
	if exists (select 1 from syscolumns where id = object_id(@objname) 
		and computedcol is not null and (status3 & 1) !=1) 
	begin
		print ""
		execute dbo.sp_helpcomputedcolumn @objname, 0
	end
end

/*
**  For procedures and sqlj functions, the parameters of the procedures 
**  are stored in syscolumns.
*/
if @sysstat & 15 in (4, 10, 12)
begin
	exec sp_help_params @objname
end

/*
**  If the object is an external table, show which OS file it's using.
*/
if @sysstat & 2063 = 2051
begin
	select @OS_file = name from sysindexes
		where id = object_id(@objname)
		and indid in (0,1)
	/*
	** 17570, "Operating System File"
	** 17571, "---------------------"
	*/
	print ""
	exec sp_getmessage 17570, @msg out
	print @msg
	exec sp_getmessage 17571, @msg out
	print @msg
	print @OS_file
	print ""
end
/*
**  If the object is an Omni-managed table, show its storage location.
*/
if (@sysstat2 & 1024 = 1024)
begin
	declare	@dbname varchar(255),
		@site  varchar(255),
		@owner varchar(255),
		@tabname varchar(255),
		@retcode int

	exec @retcode = sp_namecrack @objname, @site output, @dbname output,
			@owner output, @tabname output

	select @OS_file = char_value from sysattributes
			where class = 9 and attribute = 1 and 
			object_cinfo = @tabname

	/*
	**  17573, "Object is Remote/External"
	**  17574, "-------------------------"
	*/
	print ""
 	exec sp_getmessage 17573, @msg out
 	print @msg 
 	exec sp_getmessage 17574, @msg out
 	print @msg
	print @OS_file
	print ""

	if (@sysstat2 & 2048 = 2048)
	begin
		/*
		** 17575, "Object existed prior to Omni"
		*/
		exec sp_getmessage 17575, @msg out
 		print @msg 
 		print ""
	end
end

/* 
**  If the object is a table, display sysattributes information
**  if there is any.  It could be in the current database under
**  type "T".
*/

if @sysstat & 15 in (1, 3)
begin
	/*  Create temporary table for sysattributes data */
	create table #sphelpattr
	(
		class 		varchar(255),
		class_id	smallint,
		attribute 	varchar(255),
		attribute_id	smallint,
		int_value	int NULL,
		char_value	varchar(255) NULL,
		comments	varchar(255) NULL
	)

	/* 
	**  The join with master..sysattributes here is to
	**  get the string descriptions for the class and attribute.
	**  These should never be more than 30 chars, so it's okay to
	**  truncate them.
	*/

	insert #sphelpattr (class, class_id, attribute, attribute_id, int_value,
				 char_value, comments)
		select  c.char_value, 
			t.class,
			a.char_value,
			t.attribute,
			t.int_value, t.char_value, t.comments
		from sysattributes t, master.dbo.sysattributes c, 
			master.dbo.sysattributes a
		where t.object_type = "T"
		and t.object = object_id(@objname)
		and c.class = 0 and c.attribute = 0
		and a.class = 0 and a.attribute = 1
		and t.class = c.object
		and t.class = a.object
		and t.attribute = a.object_info1
	
        /*
        ** If the table is virtually hashed, then print the list of index key
        ** columns and their correspondig hash factors as char_value.
        */
	if(exists(select attribute from #sphelpattr
			where attribute = 'hash key factors'))
        begin
		/* The table is Virtually Hashed */
		exec sp_getmessage 19586, @msg out
		print @msg
		print ""

		select @new_char_value = ""
                select @num_keys = keycnt from sysindexes
                        where id = object_id(@objname)

                select @key_count = 1

                select @indid = min(indid)
                        from sysindexes
                        where id = object_id(@objname)
                                and indid > 0
                                and indid < 255

                set nocount on

                /*
                ** Get the list of index key columns.
                */
                while (@key_count <= @num_keys)
                begin
                        select @thiskey = 
				index_col(@objname, @indid, @key_count)

                        if (@thiskey is NULL)
                        begin
                                break
                        end

                        if(@key_count > 1)
                        begin
                                select @new_char_value = @new_char_value + ", "
                        end

                        select @new_char_value = @new_char_value + @thiskey

                        /*
                        ** In current 'char_value', we have an array of hash
                        ** factors of type 'double' that was written to
                        ** 'char_value' as byte string.
                        ** Hence to get the array of hash factors back:
                        **
                        ** 1. Divide 'char_value' into disjoint substrings,
                        **    each of length 8 (sizeof double).
                        ** 2. Convert the substring into binary type.
                        ** 3. Convert the binary value into 'double'.
                        **
                        ** Once obtained the value, convert it to character
                        ** type and append to @new_char_value
                        */
                        select @new_char_value = @new_char_value 
				+ ":" + 
				convert(varchar(255),
                                convert(double precision,
                                convert(binary,
                                substring(char_value, @key_count * 8 - 7, 8))))
                        from #sphelpattr
			where attribute = 'hash key factors'

                        select @key_count = @key_count + 1
                end


                /*
                ** Append the 'max_hash_key' to @new_char_value
                */
                select @new_char_value = @new_char_value + ", max_hash_key"

                select @new_char_value = @new_char_value + 
			"=" + 
			convert(varchar(255),
                        convert(double precision,
                        convert(binary,
                        substring(char_value, @key_count * 8 - 7, 8))))
                from #sphelpattr
		where attribute = 'hash key factors'

                update #sphelpattr set char_value = @new_char_value
			where attribute = 'hash key factors'
        end

	/*
	** It's possible a cache is deleted without doing an unbind first. After
	** a server reboot the binding is marked 'invalid' (int_value = 0).
	** If we have such an invalid binding, don't show it in the output.
	*/
	delete from #sphelpattr
	where class_id = 3
	and attribute_id = 0
	and int_value = 0

	if exists (select * from #sphelpattr)
	begin
		exec sp_autoformat @fulltabname = #sphelpattr,
			@selectlist = "'attribute_class' = class, attribute, int_value,char_value, comments"
	end
	drop table #sphelpattr
end

/* 
**  If the object is a procedure, display sysattributes information
**  if there is any.
*/

if @sysstat & 15 = 4
begin
	if exists (select * from sysattributes
			where  object_type = "P"
			and object = object_id(@objname))
	begin
		/* 
		**  The join with master..sysattributes here is to
		**  get the string descriptions for the class 
		**  (master.dbo.sysattributes c) and attribute
		**  (master.dbo.sysattributes a).
		*/

		select  attribute_class = c.char_value, 
			attribute = a.char_value,
			t.int_value, t.char_value, t.comments
		into #sphelp6rs
		from sysattributes t, master.dbo.sysattributes c, 
			master.dbo.sysattributes a
		where t.object_type = "P"
		and t.object = object_id(@objname)
		and c.class = 0 and c.attribute = 0
		and a.class = 0 and a.attribute = 1
		and t.class = c.object
		and t.class = a.object
		and t.attribute = a.object_info1

		exec sp_autoformat @fulltabname = #sphelp6rs
		drop table #sphelp6rs
	end
end

/*
**  If the object is a table, check out the indexes.
*/
if @sysstat & 15 in (1, 3)
	execute dbo.sp_helpindex @objname

/*
**  If the object is a table or view, check out the keys.
*/
if @sysstat & 15 in (1, 2, 3)
	execute dbo.sp_helpkey @objname

/*
**  If the object is a table, check out the slices/partitions
*/
if @sysstat & 15 in (1, 3)
	execute dbo.sp_helpartition @objname

/*
** If the object is a trigger, it is either enabled or disabled
*/
if @sysstat & 15 in (0,8)
begin
	/*
	** 1048676 <==> 0x100000 <==> insert trigger disabled
	** 2097152 <==> 0x200000 <==> delete trigger disabled
	** 4194304 <==> 0x400000 <==> update trigger disabled
	*/
	if exists (select 1 from sysobjects trig, sysobjects tab
		where trig.id = object_id(@objname)
		and   trig.deltrig = tab.id
		and ((trig.id = tab.deltrig and tab.sysstat2 & 2097152 <> 0)
		or   (trig.id = tab.updtrig and tab.sysstat2 & 4194304 <> 0)
		or   (trig.id = tab.instrig and tab.sysstat2 & 1048576 <> 0)))
			exec sp_getmessage 17581, @msg out
	else
			exec sp_getmessage 17582, @msg out

	print @msg
end

/*
** Print the lock scheme information for the table objects
*/
if @sysstat & 15 in (1, 3)
begin
	/*
	** the bits 0x2000, 0x4000 & 0x8000 represents any 
	** explicit lock scheme bits that can be set, so
	** get them out ( 0x2000 + 0x4000 + 0x8000 = 57344)
	*/
	select @sysstat2 = (sysstat2 & 57344)
		from sysobjects
			where id = object_id(@objname)
	/*
	** The value 0, refers that no lock scheme is 
	** specified (old style tables) so they support only
	** allpages locking
	*/
	if (@sysstat2 in (0, 8192, 16384, 32768))
	begin
		if (@sysstat2  = 8192 or @sysstat2 = 0)
		begin
			/* 17576, "Lock scheme is Allpages" */
        		exec sp_getmessage 17576, @msg out
        		print @msg
		        /* 18571, "The attribute '%1!' is */
                        /* not applicable to tables with  */
                        /* allpages lock scheme."         */
			exec sp_getmessage 18571, @msg out
			print @msg, 'exp_row_size'
			/* 18571, "The attribute '%1!' is */
			/* not applicable to tables with  */
			/* allpages lock scheme."         */
			exec sp_getmessage 18571, @msg out
			print @msg, 'concurrency_opt_threshold'
		end

		if ( @sysstat2 = 16384 )
		begin
			/* 17577, "Lock scheme is Datapages" */
        		exec sp_getmessage 17577, @msg out
        		print @msg

			/* 18983, "The '%1!' attribute is not applicable 
			** to tables with datarow or datapage lock schemes.
			*/
        		exec sp_getmessage 18983, @msg out
        		print @msg, 'ascinserts'
		end

		if (@sysstat2 = 32768)
		begin
			/* 17578, "Lock scheme is Datarows" */
        		exec sp_getmessage 17578, @msg out
        		print @msg

			/* 18983, "The '%1!' attribute is not applicable 
			** to tables with datarow or datapage lock schemes.
			*/
        		exec sp_getmessage 18983, @msg out
        		print @msg, 'ascinserts'
		end

		/* Server defined value for ascinserts 
		** if ascinserts is set, then master..sysindexes.status2=64 
		*/
		select @opt_ind2_ascinserts = 64
		
		print " "
		select  exp_rowsize "exp_row_size",
                        res_page_gap "reservepagegap",  
                        fill_factor "fillfactor",
                        maxrowsperpage "max_rows_per_page",
                        isnull(identitygap, 0) "identity_gap",
			(case when ((@opt_ind2_ascinserts & status2) > 0)
				then 1
				else 0
			end
			) "ascinserts"
			from sysindexes
			      where id = object_id(@objname)
				and indid <= 1

		/* Server defined constant for optimistic index lock */
		select @opt_ind_lock = 268435456

		/* Server defined constant for dealloc first txtpg */
		select  @text_dealloc = hextoint("0x020000000")

		select @opt_ind_status = (sysstat2 & @opt_ind_lock),
		       @opt_text_dealloc = (sysstat2 & @text_dealloc)
		from sysobjects where id = object_id(@objname)

		if (@opt_ind_status = 0)
			select @opt_ind_value = 0
		else
			select @opt_ind_value = 1

		if (@opt_text_dealloc = 0)
			select @opt_text_value = 0
		else
			select @opt_text_value = 1

		/*
		** Currently, the following information will be same
		** for all partitions, only need to print once for
		** one of the partitions
		*/
		select  distinct
			conopt_thld "concurrency_opt_threshold",
			@opt_ind_value "optimistic_index_lock",
			@opt_text_value "dealloc_first_txtpg"
			from systabstats
			where id = object_id(@objname)
			and indid <= 1

		return  (0)
	end
	else
	begin
		/* 17579, "Lock scheme Unknown or Corrupted" */
       		exec sp_getmessage 17579, @msg out
       		print @msg
       		return  (1)
	end
end



/* 
**  If the object is computed column, display 
**  computed column information.
**  We just simply follow the way sp_helpcomputedcolumn works.
*/
if (@sysstat & 15) = 13
begin
	declare @count int, @total int, @row_id int, @config_parm int, @mode int, @tab_name varchar(767)
	
	select @tab_name = object_name(id), @mode = status3 & 1
	from syscolumns
	where computedcol = object_id(@objname)

	/*
	** Create temporary table to stored computed column info 
	*/
	create table #helpcpc (colname varchar(255), computedcol int, 
				property varchar(15) null, row_id numeric identity)
	/* 
	** Get info on computed columns
	*/
	if @mode != 1
	begin
		insert into #helpcpc(colname, computedcol, property) 
			select name, 
			       computedcol, 
			       case when (status2 & 32 = 32) then "materialized"
				    else "virtual" end
			from syscolumns where 
			computedcol = object_id(@objname) and 
			status3 & 1 != 1 
			order by colid
	end
	/*
	** Get Info on functional index keys
	*/
	else
	begin
		insert into #helpcpc(colname, computedcol) 
			select name, computedcol from syscolumns where 
			computedcol = object_id(@objname) and 
			status3 & 1 = 1 
			order by colid
	end
	
	/*
	** Display the header
	*/
	if @mode != 1
	begin
		exec sp_getmessage 19456, @msg output
	end
	else
	begin
		exec sp_getmessage 19457, @msg output
	end
	print ""
	print @msg, @tab_name
	print ""
	
	/*
	** If the configuration parameter 'allow select on syscomments.text' 
	** is set to 0, then the user can access the text ONLY in the 
	** following cases
	** 
	**	1. if the user has sa_role
	**	2. if the object is owned by the user
	**
	*/
	select @config_parm = value 
		from master.dbo.syscurconfigs 
	where config = 258
	
	if @config_parm = 0 and user_id() != 1
	begin
		/*
		** The object needs to be owned by the user
		*/
		if not exists (select name from sysobjects 
					where uid = user_id() 
					and id = object_id(@objname))
		begin
			/* 
			** Inform the user the text cannot be displayed and 
			** print the rest info before return
			*/
			if @mode != 1
			begin
	        		exec sp_getmessage 19334, @msg output
				print @msg
				exec sp_autoformat #helpcpc, "'Column_Name' = colname,
					Property = property"
			end
			else
			begin
				exec sp_getmessage 19335, @msg output
				print @msg
				exec sp_autoformat #helpcpc, 
					"'Internal_Index_Key_Name' = colname"
			end
			
			drop table #helpcpc
			return(0)
		end
	end
	
	/*
	** Now display the text
	*/
	create table #helptxt (text varchar(255), row_id numeric (10) identity)
	create table #helpname (colname varchar(255), property varchar(15) null)
	
	select @count = 1
	select @total = max(row_id) + 1 from #helpcpc
	while @count < @total
	begin
		insert into #helpname(colname, property)
		select colname, property from #helpcpc where row_id = @count
	
		if @mode != 1
		begin	
			exec sp_autoformat #helpname, "'Column_Name' = colname, 
					Property = property"
		end
		else
		begin
			exec sp_autoformat #helpname, 
				"'Internal_Index_Key_Name' = colname"
		end
		
		/*
		** See if the object is hidden (SYSCOM_TEXT_HIDDEN will be set)
		*/	
		if exists (select 1 from syscomments m, #helpcpc h where
				(m.status & 1 = 1) and 
				m.id = h.computedcol and 
				h.row_id = @count)
		begin
	        	exec sp_getmessage 19337, @msg output
			print @msg
			print ""
			delete #helpname
			select @count = @count + 1
			continue
		end
	
		insert #helptxt (text) select text from syscomments, #helpcpc
		where row_id = @count and id = computedcol order by colid2, colid
	
		print ""
		if @mode != 1
		begin
			exec sp_autoformat #helptxt, "Text = text"
		end
		else
		begin
			select @row_id = min(row_id) from #helptxt
			update #helptxt set text = right(text, char_length(text)-4)
			where row_id = @row_id
	
			select @row_id = max(row_id) from #helptxt
			update #helptxt set text = left(text, char_length(text)-13)
			where row_id = @row_id
			exec sp_autoformat #helptxt, "Expression = text"
		end
		print ""
	
		select @count = @count + 1
		delete #helpname
		delete #helptxt
	end 
	
	drop table #helpcpc, #helpname, #helptxt	
end

return (0)
go
exec sp_procxmode 'sp_help', 'anymode'
go
grant execute on sp_help to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helprotect')
begin
	drop procedure sp_helprotect
end
go
print "Installing sp_helprotect"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/help */
/*
** Messages for "sp_helprotect"         17673
**
** 17431, "true"
** 17432, "false"
** 17460, "Object must be in the current database."
** 17232, "No user with the specified name exists in the current database."
** 17673, "All"
** 17674, "No such object or user exists in the database."
** 17675, "Illegal string found where the keyword grant is expected."
** 17676, "This may be a temporary object. Please execute procedure from your
**         temporary database."
** 17677, "sp_helprotect [name [, username [, 'grant' [,'none'|'granted'|'enabled'|role_name [,permission_name]]]]]"
** 17678, "Illegal role name '%1!' specified."
** 18349, "@rolename = 'enabled' option is allowed only for the current user."
** 18350, "An error was encountered in processing the group-level permissions."
** 18351, "An error was encountered in processing the user-level permissions."
** 18900, "Implicit grant to public for SQLJ functions."
** 19610, "%1! is an invalid permission name."
*/
create procedure sp_helprotect
@name varchar(767) = NULL,	/* name of object or user to check */
@username varchar(255) = NULL,	/* name of user to restrict check	*/
@option varchar(10) = NULL, 	/* keyword grant implies with grant option */
@rolename varchar(255) = NULL, 	/* the role to be taken into account when 
				** calculating the permissions. Can be set to
				** "granted", "enabled", "none" , NULL or a 
				** specific rolename
				*/
@permission_name varchar(30) = NULL  /* name of permission to
                                     ** restrict check
                                     */
as

declare @low int			/* range of userids to check */
declare @high int
declare @olow int			/* range of objectids to check */
declare @ohigh int
declare @invalid_uid int
declare @objid int			/* id of @name if object */
declare @msg	varchar(1024)
declare @msg_true varchar(9)		/* msg for "true" equivalent */
declare @msg_false varchar(9)		/* msg for "false" equivalent */
declare @is_user   int		     /* whether name specified is a username */
declare @user_suid int	     		/* user's suid if a username is 
					** specified 
				     	*/
declare @attr_udr_class	int	     /* value of UDR_CLASS in sysattributes */
declare @attr_udr_role_hierarchy int /* value of attribute in sysattributes
				     ** for rows corresponding to role 
				     ** hierarchy
				     */
declare @cur_id int		/* for holding object_id from cursor fetch */
declare @cur_uid int	/* for holding uid from cursor fetch */
declare @cur_action smallint	/* for holding action from cursor fetch */
declare @cur_protype tinyint	/* for holding protection type from fetch */
declare @cur_grantor int	/* for holding grantor from cursor fetch */
declare @cur_number int	        /* for holding column number from cursor fetch*/
declare @group_name varchar(255) /* group that the user belongs to */
declare @tmpstr varchar(255)	/* rolename */ 
declare @rolelist varchar(255)	/* list of roles from show_role() */
declare @maxsysrolenum int
declare @permission_number int
declare @cmd varchar(3000)
declare @dbcc_action int
declare @lowercase_permission_name	varchar(30)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
select @attr_udr_class = class 
from master.dbo.sysattributes 
where object_type = "UR"

select @maxsysrolenum = 31

select @attr_udr_role_hierarchy = 2
select @is_user = 0
select @permission_number = 0
/*
** dbcc_action used to distinguish between actions
** that use pseudo object ids
*/
select @dbcc_action = 317

/*
**  Check to see that the object names are local to the current database.
*/
if @name like "%.%.%" and
	substring(@name, 1, charindex(".", @name) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
end

/*  If this is a temporary table; object does not belong to 
**  this database; (we should be in our temporary database)
*/
if (@name like "#%" and db_name() != db_name(tempdb_id()))
begin
	/* 
	** 17676, "This may be a temporary object. Please execute 
	** procedure from your temporary database."
	*/
	raiserror 17676
	return (1)
end

/*
** Check if the grant keyword is correct
*/
if (@option is not null and lower(@option) != "grant")
begin
	/*
	** 17675, "Illegal string found where the keyword grant is expected."
	*/
	raiserror 17675
	return (1)
end

/* Trim blanks for rolename */
select @tmpstr = lower(ltrim(rtrim(@rolename)))

/*
** Check if the rolename parameter is correct
*/
if (@rolename is not NULL ) and
   (@tmpstr != "granted") and
   (@tmpstr != "enabled") and
   (@tmpstr != "none" ) and 
   (role_id(@rolename) is NULL)
begin
	/*
	** 17678, "Illegal rolename '%1!' specified"
	*/
	raiserror 17678, @rolename
	return(1)
end



/*
**  Initialize the range of user ids to check.  We will either check all
**  users (the initial values) or just one in particular (@low = @high)
**  NOTE: @low has been set to @@minuserid - 1 because the valid uid range is 
**  @@minuserid to @@maxuserid.  
**  For objects set the range from -MAXINT to MAXINT. There are no
**  global variables in the server to represent that, so use @@maxuserid.
*/
select @invalid_uid = @@minuserid - 1 /* uid outside -ve range */

select @low = @invalid_uid, @high = @@maxuserid

/*
** Initialize the range of object ids to include. There are
** some special negative object ids (such as the object id which
** represents execution of a DBCC command), so the range extends
** across the entire set of +ve and -ve integer values.
*/
select @olow = -@@maxuserid, @ohigh = @@maxuserid


/*
**  There are two cases handled by this procedure.  If the first parameter
**  is an object (table, view, procedure) then @name is taken as an object
**  name and the procedure will figure out permissions for the object.
**
**  If the first parameter is not one of the objects mentioned it will be
**  taken as user name and all the permissions for the user or group name
**  will be shown.
*/

if @name is not NULL
begin
	/*
	**  Check to see if it's an object.
	*/
	if exists (select *
			from sysobjects
				where id = object_id(@name)
					and (sysstat & 15 = 1	/* system table */
					or sysstat & 15 = 2	/* view */
					or sysstat & 15 = 3	/* user table */
					or sysstat & 15 = 4     /* procedure */
					or sysstat & 15 = 10    /* SQL UDF */
					or sysstat & 15 = 15))  /* encryption key */
	begin
		/*
		**  Set @olow and @ohigh so the search will be restricted to
		**  a particular object.
		*/
		select @olow = id, @ohigh = id
			from sysobjects
				where id = object_id(@name)
	end
	
	/* If this is a sqlj function then advise the user that the 
	** permission is implicitly public.
	*/
	else if exists (select *
			from sysobjects
				where id = object_id(@name)
					and sysstat & 15 = 12) /*sqlj function*/
	begin
		/*
		** 18900, "Implicit grant to public for SQLJ functions."
		*/
	                execute sp_getmessage 18900, @msg output
			print @msg
			return(1)
	end

	else
	begin
		/*
		**  Since @name is not an object let's try it as a user.
		*/

		/*
		**  Set @low and @high so the search will be restricted to
		**  a particular user.
		*/
		select @low = uid, @high = uid from sysusers 
				where name = @name
		/*
		**  Now check if it is a role.
		**  If not, then return.
		*/
		if (role_id(@name) is not NULL)
		begin
			/*
			** It is possible the role does not
			** exist in sysusers yet. Setting @high to 
			** @invalid_uid will restrict the search
			** in sysusers to zero rows.
			*/
			if (@low = @invalid_uid)
			begin
				select @high = @low
			end

			/* Assume it is only a role */
			select @rolename = @name
			select @name = NULL
			select @username = NULL
			select @option = NULL
		end

		else if (@low = @invalid_uid)
		begin
			/*
			** 17674, "No such object or user exists in the 
			** database."
			*/
			raiserror 17674
			return (1)
		end
	end
end

if @username is not NULL
begin
	/* Re-initialize @low to validate @username */
	select @low = @invalid_uid

	select @low = uid from sysusers where name = @username
	/*
	**  @username isn't valid.
	*/
	if @low = @invalid_uid
	begin
		/* 17232, "No user with the specified name exists in the current database." */
		raiserror 17232
		return (1)
	end
	else 
	begin
		/*
		** If we already have a userid in @high, then they
		** specified a user in @name as well.  The two
		** had better be the same.
		*/
		if @high != @@maxuserid
		begin
			if @low != @high
 			begin
				/* 
				** 17677, "sp_helprotect [name [, username
				** [, 'grant' [,'none'|'granted'|'enabled'|
				** role_name [,permission_name]]]]]"
				*/
				raiserror 17677
				return (1)
			end 	
		end
		else 
		begin
			select @high = @low
		end
	end
end

if @permission_name is not NULL
begin
	select @lowercase_permission_name = lower(@permission_name)
        if exists (select * from  master.dbo.spt_values
                        where lower(name) = @lowercase_permission_name and type ="T")
        begin
                select @permission_number = number from master.dbo.spt_values
                        where lower(name) = @lowercase_permission_name and type ="T"
        end
        else
        begin
                /*
                ** 19610, "%1! is an invalid permission name."
                */
                raiserror 19610, @permission_name
                return(1)
        end
end

/* 
** Check if this is for a specific user, role or group. If this is for a 
** specific user, @high will be set to uid of that user instead of @@maxuserid.
*/
if @high != @@maxuserid
begin

	/* check if this is for a specific user */
	if exists (select * from sysusers where uid = @high and uid != gid)
	begin
		select @is_user = 1
		select @user_suid = suid from sysusers where uid = @high
	end
	else
		select @is_user = 0
end

set nocount on
 
create table #sysprotects1 (id int, uid int, action smallint,
	protecttype tinyint, grantor int, number int)
	  
create table #sysprotects2 (id int, col_count int)
			 
insert into #sysprotects2 (id, col_count)
	select id, count (*) from syscolumns  group by id      

/*
** If the permissions are asked for a user, the logic below takes 
** the roles and groups also into account when calculating the permissions.
** The way the roles are to be taken into account depends on the value of
** the rolename parameter which can have following different values:
** 	rolename = "none" - roles are completly ignored
**	rolename = "granted"  - all roles granted to the user are taken into account
**	rolename = "enabled" - only enabled roles are taken into account -
**				this works only for the current user.
**	rolename = <rolename> - only the specified role is taken into account
**
** As far as the groups are concerned, the group's permissions are always 
** taken into account when computing the final permission.
**
** The logic used to implement this is as follows:
**	part1 - get all the roles and groups that are to be considered 
**		for computing the permissions for the user.
**	part2 - compute the permissions for all the roles and put them in
**		one table, compute the permissions for all the groups and
**		put them in another table and compute the permissions for
**		the individual user itself and put them in yet another table.
**	part3 - Compute the effective permissions for the user using the
**		permissions table created for the roles, groups and the user.
*/

if (@is_user = 1)
begin
	/* to compute the individual user's permissions, the roles possessed
	** by the user and the groups that the user belongs to must also be
	** taken into account.
	*/

	/*
	** Part 1: get all the roles and groups that are to be considered
	** for computing the permissions for the user.
	*/

	create table #rolenames (name varchar(255))

	/*
	** step1: parse the rolenames parameter
	*/

	/*
	** allow rolename = "enabled" only for current user
	*/
	if (@rolename = "enabled" and @user_suid != suser_id())
	begin
		/*
		** 18349, "@rolename = 'enabled' option is allowed only for 
		** the current user."
		*/
		raiserror 18349
		return (1)
	end

	/*
	** set the rolename parameter appropriately if not specified
	*/
	if (@rolename is NULL)
	begin
		/*
		** for current user the default corresponds to all 
		** enabled roles, wheras for other user the default 
		** corresponds to all granted roles
		*/
		if (@user_suid = suser_id())
			select @rolename = "enabled"
		else
			select @rolename = "granted"
	end

	/*
	** since role hierarchies are to be flattened at this point,
	** first create an intermediate temporary table to hold all 
	** the first-level roles 
	*/
	create table #intmdt_role_set ( name	varchar(255))
	/*
	** Create another table to store the list of granted user-defined
	** roles; we will call proc_role() on these.
	*/
	create table #intmdt2_role_set ( name	varchar(255))
	/*
	** step2: depending on the value of @rolename, populate 
	** the rolenames table
	*/
	if (@rolename = "granted" or @rolename = "enabled")
	begin

		/*
		** If the option is set to "enabled", put all the roles that
		** are currently granted to the user and enabled by the user
		** into the temporary table.
		*/
		if (@rolename = "enabled")
		begin
			/* Start by getting system roles */
			select @rolelist = show_role()
			insert into #intmdt_role_set 
				select r.name from master.dbo.syssrvroles r, 
					master.dbo.sysloginroles l
				where l.suid =  @user_suid
					and l.srid = r.srid
					and charindex(r.name, @rolelist) > 0
			/*
			** Get the user-defined roles for this user.  We will
			** then call proc_role() on these to determine which
			** are active.
			*/
			insert into #intmdt2_role_set
				select r.name from master.dbo.syssrvroles r,
					master.dbo.sysloginroles l
				where l.suid = @user_suid
					and l.srid = r.srid
					and r.srid > @maxsysrolenum
			/*
			** Now do the call to proc_role() to insert active
			** user-defined roles into #intmdt_role_set
			*/
			insert into #intmdt_role_set
				select i.name from #intmdt2_role_set i
				where proc_role(i.name) = 1
		end
		/*
		** Otherwise, put all the roles that are granted to the 
		** user into the temporary table
		*/
		else
			insert into #intmdt_role_set 
				select r.name from master.dbo.syssrvroles r, 
					master.dbo.sysloginroles l
				where l.suid =  @user_suid
					and l.srid = r.srid
		
	end
	else if @rolename != "none"
	begin
		/* The rolename parameter refers to a specific role */
		insert into #intmdt_role_set values (@rolename)
	end

	/* expand the rolenames table if required */
	if exists (select * from #intmdt_role_set)
	begin
		/*
		** to be able to expand the first-level role set into 
		** the expanded role set, we need two more temporary tables
		*/
		create table #cum_role_set (name varchar(255))
		create table #temp_role_set (name varchar(255))

		/*
		** The following while loop does the flattening of the role
		** hierarchy tree corresponding to the first level roles
		** contained in #indmdt_role_set. The processing in the loop
		** goes as follows:
		**
		** the start conditions are:
		**	#intmdt_role_set contains the base set of roles
		** 	#cum_role_set is empty
		**	#temp_role_set is empty
		** the loop processing is:
		**	- select the roles that are contained by the roles
		**	  in #intmdt_role_set and put them in #temp_role_set.
		**	- copy roles from #intmdt_role_set into #cum_role_set
		**	  if they are not already there in #cum_role_set.
		**	- move roles from #temp_role_set into #intmdt_role_set.
		** the loop exit condition is:
		**	#intmdt_role_set becomes empty.
		**	at that point, #cum_role_set contains the expanded
		**	list of roles
		*/

		while exists (select * from #intmdt_role_set)
		begin
			/*
			** select the roles that are contained by the roles
			** in #intmdt_role_set and put them in #temp_role_set.
			** Note that for the role-hierarchy type rows in
			** sysattributes, the object field contains the roleid
			** of the parent role and the object_info1 field 
			** contains the roleid of the child role.
			*/
			insert into #temp_role_set
			    select role_name(object_info1)
			    from master.dbo.sysattributes a,
				 #intmdt_role_set b
			    where a.class = @attr_udr_class
			    and a.attribute = @attr_udr_role_hierarchy
			    and a.object = role_id(b.name)

			/* copy from #intmdt_role_set to #cum_role_set */
			insert into #cum_role_set 
				select * from #intmdt_role_set
			where name not in (select name from #cum_role_set)

			delete from #intmdt_role_set 

			/* copy from #temp_role_set to #intmdt_role_set */
			insert into #intmdt_role_set 
				select * from #temp_role_set

			delete from #temp_role_set
		end

		/* 
		** At this point, the completly flattened role set is in
		** #cum_role_set - copy them over to #rolenames
		*/
		insert into #rolenames select distinct name 
					from #cum_role_set
	end

	/*
	** step3: populate the @groupnames table
	*/

	/*
	** create the #groupnames table
	*/
	create table #groupnames (name varchar(255))

	/* the user is always a member of the public group */
	insert into #groupnames values("public")

	/* if user belongs to any other group, insert that too */
	select @group_name = user_name(gid) from sysusers 
			where suid = @user_suid
	if @group_name is not null
	begin
		insert into #groupnames values(@group_name)
	end

	/*
	** part 2 : Generate protection data for each kind of grantee
	*/

	/*
	** step 1: create three tables, one for each kind of grantee
	*/

	create table #role_permissions (id int, uid int, action smallint,
		protecttype tinyint, grantor int, number int)

	create table #group_permissions (id int, uid int, action smallint,
		protecttype tinyint, grantor int, number int)

	create table #user_permissions (id int, uid int, action smallint,
		protecttype tinyint, grantor int, number int)

	/*
	** step 2: Generate the permission information for each of the
	** roles contained in the #roles table
	*/

	insert into #role_permissions(id,uid,action,protecttype,grantor,number)
	    select distinct
		p.id, p.uid, p.action, p.protecttype, p.grantor, c.number
	    from sysprotects p, master.dbo.spt_values c
	    where convert(tinyint,substring(isnull(p.columns,0x1), c.low,1)) 
		& c.high != 0
	    and c.type = "P" and c.number <= 1024
	    and p.uid in (select  user_id(name) from #rolenames)
	    and p.id between @olow and @ohigh
	/*
	** step 3: Generate permission information for each of the groups
	** present in #groupnames table
	*/
	insert into #group_permissions(id,uid,action,protecttype,grantor,number)
	    select distinct
		p.id, p.uid, p.action, p.protecttype, p.grantor, c.number
	    from sysprotects p, master.dbo.spt_values c
	    where convert(tinyint,substring(isnull(p.columns,0x1), c.low,1)) 
		& c.high != 0
	    and c.type = "P" and c.number <= 1024
	    and p.uid in (select  user_id(name) from #groupnames)
	    and p.id between @olow and @ohigh

	/*
	** step 4 : Generate permission information for the user himself
	*/
	insert into #user_permissions(id,uid,action,protecttype,grantor,number)
	    select distinct
		p.id, p.uid, p.action, p.protecttype, p.grantor, c.number
	    from sysprotects p, master.dbo.spt_values c
	    where convert(tinyint,substring(isnull(p.columns,0x1), c.low,1)) 
		& c.high != 0
	    and c.type = "P" and c.number <= 1024
	    and p.uid = @high
	    and p.id between @olow and @ohigh

	/*
	** part 3: Generate the final permission information
	**
	** The logic for determining the final permissions for a user,
	** the logic that is also used inside the server to actually decide
	** whether to allow a particular access to a user or not, is as
	** follows:
	**	if (there is a grant row found where the grantee is one
	**	   of the roles possessed by the user)
	**	then
	**		the user has the access
	**	else
	**		if (there is a grant row found where the grantee is 
	**		   the user himself)
	**		then
	**			the user has the access
	**		else
	**			if (there is a grant row found against the
	**			    group that the user belongs to)
	**					and
	**			    (there is no revoke found against the
	**			     user himself)
	**			then
	**				the user has the access
	**			else
	**				the user does not have the access
	**			fi
	**		fi
	**	fi
	**
	**	Note that if the access applies at column level, the logic
	**	needs to be applied to each column of the object
	*/

	/*
	** step1: create a table to hold the final permission information
	*/
	create table #final_permissions (id int, uid int, action smallint,
		protecttype tinyint, grantor int, number int)


	/*
	** step2: Select all rows from $role_permissions table and put them
	** in #final_permissions since the roles permissions override all
	** other permissions.
	*/
	insert into #final_permissions select * from #role_permissions

	/*
	** step3 : Select all grant (or grant_w_grant) rows from the user's
	** permissions table and put them in #final_permissions table since 
	** we know that there cannot be any revokes against roles (which can
	** override these grants), and user's permissions overrides the
	** group's permissions
	*/
	insert into #final_permissions select * from #user_permissions
		where protecttype = 0 or protecttype = 1
	
	/*
	** step 4: process rows in #group_permissions table
	*/

	declare group_cursor cursor for select id, uid, action,
		protecttype, grantor, number from #group_permissions
		where protecttype = 0 or protecttype = 1

	open group_cursor

	fetch group_cursor into @cur_id, @cur_uid, @cur_action, 
		@cur_protype, @cur_grantor, @cur_number

	while (@@sqlstatus = 0)
	begin
		/* if the row is for non-column level object */
		if not exists (select id from #sysprotects2 where id = @cur_id)
		begin
			/* if no revoke found in #user_permissions */
			if not exists (select * from #user_permissions 
				where     (id = @cur_id)
				      and (action = @cur_action)
				      and (protecttype = 2))
			begin
				insert into #final_permissions values(
					@cur_id, @cur_uid, @cur_action,
					@cur_protype, @cur_grantor, @cur_number)
			end
		end

		else
		/* if the object is a column level object */
		begin
			/* If all permission has been granted to the group 
			** and some permissions have been revoked from the
			** user
			*/
			if (col_name(@cur_id, @cur_number) is null
			   and exists (select * from #user_permissions
			   where id = @cur_id 
				and action = @cur_action
				and protecttype = 2
				and col_name(@cur_id, number) is not null))
			begin
				/* 
				** for each column of the object for which 
				** there is no revoke row in #user_permission
				** insert a grant row in #final_permissions
				*/
				insert into #final_permissions 
				select @cur_id, @cur_uid, @cur_action, 
				    @cur_protype, @cur_grantor, c.number 
				from master.dbo.spt_values c, #sysprotects2 p
				where   (c.type = "P")
				    and (c.number <= p.col_count)
				    and (c.number > 0)
				    and (p.id = @cur_id)
				    and c.number not in (select number from
					#user_permissions u where 
						(u.id = @cur_id)
					    and (u.action = @cur_action)
					    and (u.protecttype = 2))
			end
			/* otherwise, the current row fetched by the cursor
			** is for a specific column - insert the current row in 
			** #final_permissions if there is no revoke for
			** the specified column in #user_permissions
			*/
			else 
			begin
				if not exists (select * from #user_permissions
					where id = @cur_id 
					and action = @cur_action
					and ((number = @cur_number) or
					     col_name(@cur_id, number) is null)
					and protecttype = 2)
				begin
					insert into #final_permissions values(
					@cur_id, @cur_uid, @cur_action,
					@cur_protype, @cur_grantor, @cur_number)
				end
			end
		end /* end of processing for column-level objects */

		fetch group_cursor into @cur_id, @cur_uid, @cur_action, 
			@cur_protype, @cur_grantor, @cur_number

	end /* of while sqlstatus = 0 */

	if (@@sqlstatus = 1)
	begin
		/*
		** 18350, "An error was encountered in processing 
		** the group-level permissions."
		*/
		execute sp_getmessage 18350, @msg output
		print @msg
		return (1)
	end

	close group_cursor

	deallocate cursor group_cursor

	/*
	** step 5: process revoke rows in #user_permissions table
	*/


	declare user_cursor cursor for select id, uid, action,
		protecttype, grantor, number from #user_permissions
		where protecttype = 2

	open user_cursor

	fetch user_cursor into @cur_id, @cur_uid, @cur_action, 
		@cur_protype, @cur_grantor, @cur_number

	while (@@sqlstatus = 0)
	begin
		/* if the row is for non-column level object */
		if not exists (select id from #sysprotects2 where id = @cur_id)
		begin
			/* if no grant found in #role_permissions */
			if not exists (select * from #role_permissions 
				where     (id = @cur_id)
				      and (action = @cur_action)
				      and (protecttype = 0 or protecttype = 1))
			begin
				insert into #final_permissions values(
					@cur_id, @cur_uid, @cur_action,
					@cur_protype, @cur_grantor, @cur_number)
			end
		end

		/* the object is a column level object */
		else
		begin
			/* 
			** If permission on all columns have been revoked 
			** from the user and if some permissions have been
			** granted to any of the roles
			*/
			if (col_name(@cur_id, @cur_number) is null
			   and exists (select * from #role_permissions
			   where id = @cur_id 
				and action = @cur_action
				and (protecttype = 0 or protecttype = 1)
				and col_name(@cur_id, number) is not null))
			begin
				/* 
				** for each column of the object for which 
				** there is no grant row in #role_permission
				** insert a revoke row in #final_permissions
				*/
				insert into #final_permissions 
				select @cur_id, @cur_uid, @cur_action, 
				    @cur_protype, @cur_grantor, c.number 
				from master.dbo.spt_values c, #sysprotects2 p
				where   (c.type = "P")
				    and (c.number <= p.col_count)
				    and (c.number > 0)
				    and (p.id = @cur_id)
				    and c.number not in (select number from
					#role_permissions u where 
						(u.id = @cur_id)
					    and (u.action = @cur_action)
					    and (u.protecttype = 1 or
						 u.protecttype = 0))
			end
			/* otherwise, the current row fetched by the cursor
			** is for a specific column - insert the current row in 
			** #final_permissions if there is no grant for
			** the specified column in #role_permissions
			*/
			else 
			begin
				if not exists (select * from #role_permissions
					where id = @cur_id 
					and action = @cur_action
					and ((number = @cur_number) or
					     col_name(@cur_id, number) is null)
					and protecttype = 1 or protecttype = 0)
				begin
					insert into #final_permissions values(
					@cur_id, @cur_uid, @cur_action,
					@cur_protype, @cur_grantor, @cur_number)
				end
			end /* end of else for if(col_name(...)) is null */
		end /* end of else for if(column-level object) */

		fetch user_cursor into @cur_id, @cur_uid, @cur_action, 
			@cur_protype, @cur_grantor, @cur_number

	end /* end of while */


	if (@@sqlstatus = 1)
	begin
		/*
		** 18351, "An error was encountered in processing 
		** the user-level permissions."
		*/
		execute sp_getmessage 18351, @msg output
		print @msg
		return (1)
	end

	close user_cursor

	deallocate cursor user_cursor

        if @permission_number != 0
        begin
                insert into #sysprotects1 select * from #final_permissions
                        where action = @permission_number
        end
        else
        begin
                insert into #sysprotects1 select * from #final_permissions
        end

end /* end of @is_user = 1 */
else
begin
	select @cmd = "insert into #sysprotects1 (id, uid, action, 
	protecttype, grantor, number)
	select distinct
		p.id, p.uid, p.action, p.protecttype,
		p.grantor, c.number
		from sysprotects p, master.dbo.spt_values c
		where (~isnull (convert(tinyint, substring(p.columns, c.low, 1)), 0) & c.high != 0
			and c.number <= (select col_count from #sysprotects2 where id = p.id))
			and c.type = 'P'
			and c.number <= 1024
			and p.columns is not null
			and convert(tinyint, substring(p.columns, 1, 1)) & 0x1 != 0
			and (convert(tinyint, substring(p.columns, 1, 1)) & 0xfe != 0
				or substring(p.columns, 2, 1) is not null)
			and p.id between @olow and @ohigh
			and p.uid between @low and @high"
        if @permission_number != 0
                select @cmd = @cmd + " and p.action = @permission_number"
       exec(@cmd)

	select @cmd = "insert into #sysprotects1 (id, uid, action, 
	protecttype, grantor, number)
	select distinct
		p.id, p.uid, p.action, p.protecttype,
		p.grantor, c.number
		from sysprotects p, master.dbo.spt_values c
		where convert(tinyint, substring(isnull(p.columns, 0x1), c.low, 1))
			& c.high != 0
			and c.type = 'P'
			and c.number <= 1024
			and (p.columns is null
				or convert(tinyint, substring(p.columns, 1, 1)) & 0x1 = 0
				or (convert(tinyint, substring(p.columns, 1, 1)) & 0xfe = 0
					and substring(p.columns, 2, 1) is null))
			and p.id between @olow and @ohigh
			and p.uid between @low and @high"
        if @permission_number != 0
                 select @cmd = @cmd + " and p.action = @permission_number"
        exec(@cmd)
end

/*
** 17431, "true"
** 17432, "false"
*/
exec sp_getmessage 17431, @msg_true output
exec sp_getmessage 17432, @msg_false output

/* 17673, "All" */
exec sp_getmessage 17673, @msg out

/* Collect the information about object name */
create table #temp_obj(id int, number int, objname varchar(30))
/* 
** The population of #temp is split into two queries to reduce the joins in 
** each query in order to improve performance.
*/
insert into #temp_obj
	select distinct p.id, p.number, o.name
	from #sysprotects1 p, sysobjects o
	where p.id = o.id

/* 
** #temp populates valid column names for valid column IDs. 
** There exist pad columns in some system tables which do not appear
** in syscolumns. The #temp_obj table is populated with rows from these columns 
** IDs through #sysprotects1. These rows are removed in #temp.
** 
*/
create table #temp(id int, number int, objname varchar(30), colname varchar(30) null)
insert into #temp
	select distinct t.id, t.number, t.objname,
		colname = case t.number
			when 0 then null
			else c.name
		end
	from #temp_obj t, syscolumns c
	where ((t.number = 0)
		or (t.number = c.colid and t.id = c.id))

/*
** #temp is empty if the only granted permissions in sysprotects are
** non-object permissions, or permissions on dbcc commands or builtins.
** Insert a dummy row in #temp if empty. This is needed because #temp is
** used in a natural join with #sysprotects1 to display the final permissions
** output.
*/
if not exists (select 1 from #temp)
begin
	insert into #temp values(0, 0, "dummy", "dummy")
end

if @option is NULL
begin
	/*
	** print all the privileges
	** on normal columns. 
	** If there is no valid column name for 
	** a record in the #sysprotects1 p table
        ** and p.number=0, that means privilege is 
	** granted to all columns
	** For spt_values.name like 'Create Table', 'Create Rule', ....,
	** there is no object in sysobjects table. #sysprotects1 p has
	** p.id = 0 and p.number = 0 for them. Pseduo objects such as 
	** DBCC commands have a negative object ID.
	*/


	begin
	    select distinct
		grantor = user_name(p.grantor),
		grantee = user_name(p.uid),
		type = substring(b.name, 1, 8),
		action = case 
				when (p.id < 0 and p.action = @dbcc_action)
				then col_name(p.id, p.number)
			        else a.name
			 end,
		object = case 
				when ((p.id < 0 and p.action = @dbcc_action)
					or p.id = 0)
				then ""
			 	when (p.id < 0 and p.action <> @dbcc_action)
				then col_name(p.id, p.number)
				else t.objname
			 end,
		column = case 
				when ((p.number = 0) and (p.id >= 0)) then @msg 
				when (p.id < 0) then ""
				else t.colname
			 end,
		grantable = upper(@msg_false)
	    into #sphelprotect1rs
			from #sysprotects1 p, master.dbo.spt_values a,
				master.dbo.spt_values b, #temp t
			where a.type = "T"
				and a.number = p.action
				and b.type = "T"
				and b.number = (p.protecttype + 204)
                                and ((p.id = 0 and p.number = 0)
					or (p.id = t.id and p.number = t.number)
					or (p.id < 0))

	    union

	    select distinct
			grantor = user_name(p.grantor),
			grantee = user_name(p.uid),
			type = substring(b.name, 1, 8),
			action = case
					when (p.id < 0
						and p.action = @dbcc_action)
					then col_name(p.id, p.number)
                                	else a.name
				 end,
			object = case
					when ((p.id < 0
						and p.action = @dbcc_action)
						or p.id = 0)
					then ""
					when (p.id < 0
						and p.action <> @dbcc_action)
					then col_name(p.id, p.number)
                                	else t.objname
				 end,
			column = case 
					when ((p.number = 0) and (p.id >= 0)) then @msg
                                	when (p.id < 0) then ""
                                	else t.colname
				 end,
			grantable = upper(@msg_true)
			from #sysprotects1 p, master.dbo.spt_values a,
				master.dbo.spt_values b, #temp t
			where a.type = "T"
				and a.number = p.action
				and b.type = "T"
				and b.number = (p.protecttype + 205)
				and p.protecttype = 0
                                and ((p.id = 0 and p.number = 0)
					or (p.id = t.id and p.number = t.number)
					or (p.id < 0))

	   exec sp_autoformat @fulltabname  = #sphelprotect1rs,
			@orderby = "order by grantor, grantee, type, action, object, column"
	   drop table #sphelprotect1rs
	end
end
else
begin

	/*
	** print only the grantable privileges
	*/

		select distinct
			grantor = user_name(p.grantor),
			grantee = user_name(p.uid),
			type = substring(b.name, 1, 8),
			action = case
					when (p.id < 0
						and p.action = @dbcc_action)
					then col_name(p.id, p.number)
					else a.name
				 end,
			object = case 
					when ((p.id < 0
						and p.action = @dbcc_action)
						or p.id = 0)
					then ""
					when (p.id < 0
						and p.action <> @dbcc_action)
					then col_name(p.id, p.number)
					else t.objname
				 end,
			column = case 
					when ((p.number = 0) and (p.id >= 0)) then @msg
					when (p.id < 0) then ""
					else t.colname
			 	 end,
			grantable = upper(@msg_true)
		into #sphelprotect2rs
			from #sysprotects1 p, master.dbo.spt_values a,
				master.dbo.spt_values b, #temp t
			where a.type = "T"
				and a.number = p.action
				and b.type = "T"
				and b.number = (p.protecttype + 205)
				and p.protecttype = 0
                                and ((p.id = 0 and p.number = 0)
					or (p.id = t.id and p.number = t.number)
					or (p.id < 0))

		exec sp_autoformat @fulltabname  = #sphelprotect2rs,
			@orderby = "order by grantor, grantee, type, action, object, column"
		drop table #sphelprotect2rs
end
return (0)
go
exec sp_procxmode 'sp_helprotect', 'anymode'
go
grant execute on sp_helprotect to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showtext_usage')
begin
	drop procedure sp_showtext_usage
end
go
print "Installing sp_showtext_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showtext_print_line')
begin
	drop procedure sp_showtext_print_line
end
go
print "Installing sp_showtext_print_line"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showtext_check_print')
begin
	drop procedure sp_showtext_check_print
end
go
print "Installing sp_showtext_check_print"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showtext_sproc_tagline')
begin
	drop procedure sp_showtext_sproc_tagline
end
go
print "Installing sp_showtext_sproc_tagline"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showtext_output')
begin
	drop procedure sp_showtext_output
end
go
print "Installing sp_showtext_output"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showtext')
begin
	drop procedure sp_showtext
end
go
print "Installing sp_showtext"
go


/*
** Generated by spgenmsgs.pl on Thu Jan  3 21:51:25 2008 
*/
/*
** raiserror Messages for showtext [Total 11]
**
** 17260, "Can't run %1! from within a transaction."
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
** 17679, "There is no text for object '%1!'."
** 18180, "Configuration Parameter 'select on syscomments.text' is set to 0. Only the object owner or user with sa_role can run sp_helptext on this object."
** 18406, "Source text for compiled object %1! (id = %2!) is hidden."
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
** 18936, "You cannot use a grouping number for non-procedures."
** 18937, "There is no text for object '%1!' with grouping number %2!."
** 19060, "Procedure %1!, %2! must be a positive integer."
** 19859, "Argument '%1!' is not valid for '%2!'."
*/
/*
** sp_getmessage Messages for showtext [Total 4]
**
** 17587, "partition condition"
** 18406, "Source text for compiled object %1! (id = %2!) is hidden."
** 19263, "Usage: sp_monitor"
** 19639, "%1!Parameters '%2!' and '%3!' are mutually exclusive. Ignore '%4!'."
*/
/*
** End spgenmsgs.pl output.
*/
go

exec sp_dbxt_recreate_proc sp_showtext_usage
go

/*
** **************************************************************************
** sp_showtext_usage
**
**	Print help usage information for sp_showtext.
**
** Parameters:
**	Various args that are passed-in from caller. Essentially, hard-coded
**	string names such as 'linenumbers' etc., identifying various print
**	options.
{
*/
create procedure sp_showtext_usage(
			  @context_block	int
			, @opt_showsql		varchar(7)
			, @opt_linenumbers	varchar(11)
			, @opt_comments		varchar(8)
			, @opt_leftjustify	varchar(11)
			, @opt_rightjustify	varchar(12)
			, @opt_ddlgen		varchar(6)
			, @opt_context		varchar(7)
			, @opt_noparams		varchar(8)
) as
begin
	declare @helptext	varchar(30)
	      , @showtext_args	varchar(80)
	      , @msg		varchar(80)
	      , @msg_19263	varchar(10)
	      , @tabchar	char(1)
	      , @newline	char(1)
	      , @lineno		int
	      , @context	int


	select @tabchar	= char(9)
	     , @newline	= char(10)

	exec sp_getmessage 19263, @msg output
	select @showtext_args = "<object name> "
			      + @newline
			      + @tabchar
			      + @tabchar
			      + "[, <start line> [, <number of lines> [, '<print options>'] ] ]"
	     , @msg_19263 = "Usage: %1! %2!"

	print @msg_19263, "sp_helptext", @showtext_args
	print " "

	print "  @objname	- Name of compiled object local to current db."
	print "  @startline	- Starting line number from which to generate SQL text"
	print "  @num_lines	- Number of lines to print. If '%1!' is specified"
		, @opt_context
	print "		  in <print options>, treat this as the context block."
	print "  @printopts	- Print options, see below."
	print "  @trace	- Debugging traceflags for internal use."

	print " "
	print "<print options> is a comma-separated string of print option specifiers:"
	print "  %1!	: Print formatted SQL for compiled object.", @opt_showsql
	print "  %1!	: Print line numbers", @opt_linenumbers
	print "  %1!	: Print line numbers in comments", @opt_comments
	print "  %1!	: Generate script as a DDL script to recreate the object."
		, @opt_ddlgen
	print "  %1!	: Print <n> lines of context, starting from given starting line."
		, @opt_context
	print "  %1!	: Suppress parameter information in output."
		, @opt_noparams

	print " "
	print "Examples:"

	print "    -- Basic usage, without line #s."
	print "	sp_helptext sp_helptext, NULL, NULL, '%1!'", @opt_showsql
	print " "

	print "    -- Basic usage, with line #s right-justified."
	print "	sp_helptext sp_helptext, NULL, NULL, '%1!,%2!'"
			, @opt_showsql, @opt_linenumbers
	print " "

	print "    -- DDL script with line #s in comments."
	print "    -- (Can use 0 instead of NULL.)"
	print "	sp_helptext sp_helptext, 0, 0, '%1!, %2!, %3!'"
		, @opt_showsql, @opt_linenumbers,@opt_comments
	print " "

	print "    -- Show (default) context block of %1! lines starting from line 44", @context_block
	print "	sp_helptext sp_helptext, 44, NULL, '%1!, %2!'"
		, @opt_showsql, @opt_context
	print " "

	print "    -- Show context block of %1! lines starting from line 44", 10
	print "	sp_helptext sp_helptext, 44, %1!, '%2!, %3!'"
		, 10, @opt_showsql, @opt_context
	print " "

	select @lineno		= 102
	     , @context		= 10
	     , @showtext_args	= @opt_showsql
	     			+ ','
				+ @opt_context
				+ ','
				+ @opt_linenumbers
				+ ','
				+ @opt_noparams

	print "    -- Show context block of %1! lines starting from line %2!, with linenumbers"
		, @context, @lineno

	print "	sp_helptext sp_helptext, %1!, %2!, '%3!'"
		, @lineno, @context, @showtext_args

	print " "
	print "Here is a sample output from the last command shown:"
	print " "
	select @helptext = 'sybsystemprocs.dbo.sp_helptext'
	exec @helptext @helptext, @lineno, @context, @showtext_args

end	-- }
go

if (@@sqlstatus != 0) select syb_quit()
go

exec sp_dbxt_recreate_proc sp_showtext_print_line
go

/*
** **************************************************************************
** sp_showtext_print_line
**
** 	Common procedure to output a line of text depending on user-provided
** 	options of how to print.
**
** Parameters:
**	@print_lnumbers		- Boolean whether to print line#s.
**	@right_just		- Boolean; to right-justify line#s.
**	@print_lcomment		- Print line#s in comment /* */
**	@grep_ctxt		- Boolean whether we are in a context search
**	@linenum		- Line # of current line being output
**	@subtext		- Piece of SQL sub-text extracted, to print.
**	@tagline		- Code returned from sp_showtext_check_print
**				  (2=>line is the tag line in context block.)
**	@trace			- Trace flag user passed-in.
**	@trace_hang_for_debug	- Trace flag under which to hang here to debug.
**
{
*/
create procedure sp_showtext_print_line(
			  @print_lnumbers	tinyint
			, @right_just		tinyint
			, @print_lcomment	tinyint
			, @grep_ctxt		tinyint
			, @linenum		int
			, @subtext		varchar(1024)
			, @tagline		int
			, @trace		int 	= 0
			, @trace_hang_for_debug	int
) as
begin
	declare @ln_varchar	varchar(5)	-- Big enough for line#
	      , @linenum_char	char(5)		-- Large enough for line#s
	      , @tabstop	varchar(1)
	      , @tagmark	char(4)
	      , @printfmt	varchar(30)

	select    @tabstop 	= char(9)
		, @linenum_char	= space(5)
		, @tagmark	= case @tagline when 2 then " >>>" else "" end

	if (@print_lnumbers != 0)
	begin
		select @ln_varchar = convert(varchar,@linenum)

		-- Format line # in a char field, with left
		-- or right-justification.
		--
		select @linenum_char =
			case @right_just
			    when 1
			    then
				space(char_length(@linenum_char)
				   - char_length(@ln_varchar))
			    else NULL
			end
			+ @ln_varchar

		select @printfmt = case @print_lcomment
					when 1 then "/* %1! */%2!%3!%4!"
					else 	    "%1!%2!%3!%4!"
				   end
		print @printfmt, @linenum_char
				, @tagmark
				, @tabstop
				, @subtext
	end
	else
	begin
		select @printfmt = case @grep_ctxt
					when 1
					then case @tagline
						when 2 then ">>> %1!"
						else        "    %1!"
					     end
					else "%1!"
				   end
		print @printfmt, @subtext
	end

	-- Hang here, so that we can debug sp_procstack via the use 
	-- of this sproc.
	if (@trace = @trace_hang_for_debug)
		waitfor delay "0:0:10"
end	/* } */
go

if (@@error != 0) select syb_quit()
go

exec sp_dbxt_recreate_proc sp_showtext_check_print
go

/*
** sp_showtext_check_print
**
**	Check whether we should print this line. A line might need to be
**	printed depending on various parameters passed to the main sproc.
**
**	. If we are not looking for a context block (grep_ctxt = 0), then a
**	  line will be printed if all lines are requested (normal showtext
**	  usage, where numlines_or_ctxt is 0), or if the current line is
**	  within the # of lines requested (numlines_or_ctxt != 0).
**
**	. If we are looking for a context block output (grep_ctxt != 0),
**	  print the line if the current linenum is within the context block
**	  (i.e. min_ctxt_linenum and max_ctxt_linenum).
**
** Parameters:
**	@startline		- Starting line# to print from.
**	@numlines_or_ctxt	- Number of lines to print, or context window.
**	@grep_ctxt		- Whether we are in a context block print mode.
**	@min_ctxt_linenum	- Line # of lower range of context block.
**	@max_ctxt_linenum	- Line # of upper end of context block.
**	@linenum		- Current line#.
**	@ddlgen			- Whether DDL generation was requested.
**
** Returns:
**	0	- We don't need to print this line.
**	1	- Print this line.
**	2	- Print this line, and this is the 'startline'
**		  line (requested for context block).
{
*/
create procedure sp_showtext_check_print(
			  @startline		int
			, @numlines_or_ctxt	int
			, @grep_ctxt		int
			, @min_ctxt_linenum	int
			, @max_ctxt_linenum	int
			, @linenum		int
			, @gen_ddl		int
) as
begin
	declare @retval	int

	select @retval = 0	-- default; don't print.

	-- Option 'ddlgen' supersedes everything else. Line needs to be printed.
	if (@gen_ddl != 0)
	begin
		select @retval = 1
	end
	else if (@grep_ctxt = 0)
	begin
		-- Print this line as follows:
		-- =========	========	=========
		-- startline	Numlines	Remark:
		-- =========	========	=========
		-- NULL (0)	NULL (0)	Print all lines
		-- <s>		NULL (0)	Print all lines from line <s>
		-- NULL (0)	<n>		Print <n> lines from line 0
		-- <s>		<n>		Print <n> lines from line <s>
		--
		if ( (@startline = 0) and (@numlines_or_ctxt = 0))
			select @retval = 1

		else if ( (@numlines_or_ctxt = 0) and (@linenum >= @startline) )
			select @retval = 1

		else if (@linenum between @startline
		    		     and (@startline + @numlines_or_ctxt - 1) )
			select @retval = 1
	end
	else if (@linenum between @min_ctxt_linenum and @max_ctxt_linenum)
	begin
		select @retval = case @linenum
				  when @startline then 2
				  else 1
				 end
	end
	return @retval
end	-- }
go

exec sp_dbxt_recreate_proc sp_showtext_sproc_tagline
go

/*
** **************************************************************************
** sp_showtext_sproc_tagline
**
**	Wrapper routine to show the create procedure tagline for the
**	object that is being decoded.
**
** Parameters:
**	@objname	- Name of compiled object.
**
** Returns:
**	Nothing.
{
*/
create procedure sp_showtext_sproc_tagline(
			  @objname 	varchar(317)
			, @objtype	varchar(2)
) as
begin
	declare @command	varchar(300)

	if (object_id(@objname) IS NULL)
	begin
		raiserror 17461
		return 1
	end

	select @command = "CREATE "
			+ case @objtype
				when "P"  then "PROCEDURE"
				when "TR" then "TRIGGER"
				when "V"  then "VIEW"
				when "R"  then "RULE"
				when "D"  then "DEFAULT"
				when "F"  then "FUNCTION"
				else "<Unknown object type>"
			   end
			+ " " 
			+ @objname
	print " "
	print " %1!", @command

	-- Call the work-horse function to extract args from syscolumns.
	set nocount on

	exec sp_help_params @objname, @@langid

	print " " 

end	-- }
go


exec sp_dbxt_recreate_proc sp_showtext_output
go

/* Create the #temp table needed in both sprocs */
	select    line = identity(5), number
		, text = convert(varchar(257), text)
		, charlength_text = convert(int, 0)
		, colid2, colid
	into #syscomments
	from master.dbo.syscomments
	where 1 = 0
go

/*
** **************************************************************************
** sp_showtext_output()
**
** 	Work-horse procedure to generate the output from the rows collected in
** 	a #temp table. This is where all the grunt work happens. Read the
**	rows from the #temp table, and parse it looking for newlines. Keep a
**	count of the # of lines processed. Fold-in support for various print
**	options while processing each line. If the object is a procedure with
**	groups, process and spit out SQL for each group, resetting line#s at
**	the start of each group.
**
** Parameters:
**	@objname	- Name of object to generate DDL/SQL text for.
**	@objtype	- Type of object (used to generate DROP DDL).
**	@startline	- Starting line # from which to generate text.
**	@numlines_or_ctxt
**			- # of lines to print, from @startline. If the print
**			  option says, "context", treat this # as a context
**			  block around @startline.
**	@printopts	- Various print options decoded here.
**	@trace		- Debugging trace flags.
**	@art_terminator	- Artificial terminator byte added by caller.
**
** Print options:
** ==============
**	Comma-separated strings, each specifying a print style. In brief:
**
**	linenumbers	: Print line #s.
**	comments	: Print line #s in comments.
**	leftjustify	: Print line #s left-justified.
**	rightjustify	: Print line #s right-justified.
**	context		: Treat <numlines> param as a context block, and
**			  only print a context block starting from <startline>
** Tracing:
** =======
**	1	: Print each row as you find it in syscomments.text.
**	2	: Print each row from syscomments w/"'"-delimited text.
**	3	: Print each sub-text as we parse past newlines.
**	4	: Trace iterations while searching for multiple newlines.
**	99	: Hang in print-line sproc to debug sp_procstack.
**	-ve #	: Trace execution of this sproc while lines around that
**		  line# are being processed.
{
*/
create procedure sp_showtext_output (
			  @objname		varchar(317)
			, @objtype		varchar(2)
			, @startline		int = 0
			, @numlines_or_ctxt	int = 0
			, @printopts		varchar(256)
			, @trace		int = 0
			, @art_terminator	char(1)
) as
begin
	declare @linenum	int
	      , @dbname		varchar(30)
	      , @dropcmd	varchar(256)
	      , @newline	varchar(1)
	      , @tabchar	varchar(1)
	      , @print_lnumbers	tinyint		-- whether to print line #
	      , @right_just	tinyint		-- Justification of line# field
	      , @print_lcomment	tinyint		-- line # in comments.
	      , @grep_ctxt	tinyint		-- only print context block
	      , @gen_ddl	tinyint		-- Generate DDL for creation.
	      , @newline_loc	int
	      , @space_loc	int
	      , @grouping_num	int
	      , @curr_group	int
	      , @datalength	int		-- expected length of text
	      , @datalength_act	int		-- actual length of text
	      , @charlength_st	int		-- of sub-text column.
	      , @colid2		int
	      , @colid		int
	      , @do_print	int
	      , @text_is_hidden tinyint
	      , @proc_id	int
	      , @charlength	int

	      , @text			varchar(257)
						-- The maximum length required 
						-- for the text variable is
						-- 255 (total no of bytes from
						--      text column of 
						--      syscomments)
						-- + 1 (art_terminator byte)
						-- + 1 (new_line character 
						--      added in case of 
						--      multiple partition 
						--      condition rows)
						-- = 257
	      , @trace_newline_fmtstr1	varchar(80)
	      , @trace_newline_fmtstr2	varchar(80)
              , @multiple_groups        tinyint -- To identify, in case of 
						-- partition conditition, 
						-- whether a single row of it
						-- or the entire condition 
						-- needs to be printed.

	      -- We need longer buffers so that we can store repeated chunks
	      -- of 255 bytes that might appear in text column, w/o any
	      -- interleaving newline chars. For a table w/large # of columns,
	      -- and each column being very large, the list of columns that
	      -- 'SELECT *' expands can run into a long string, without any
	      -- interleaving newlines.
	      --
	      , @subtext	varchar(1024)

	      , @subtext_size		int	-- 1023
	      , @trace_linenum		int	-- line # to trace in particular
	      , @trace_linenum_ctxt	tinyint	-- context block around which
	      					-- to trace processing when
						-- doing particular line#
						-- tracing.

	      -- Supported print options
	      , @opt_sep		char(1)		-- option separator
	      , @sep_index		int		-- in @printopts
	      , @opt_showsql		varchar(7)
	      , @opt_linenumbers	varchar(12)
	      , @opt_comments		varchar(10)
	      , @opt_rightjustify	varchar(12)
	      , @opt_leftjustify	varchar(12)
	      , @opt_ddlgen		varchar(6)
	      , @opt_context		varchar(7)
	      , @opt_noparams		varchar(8)
	      , @opt_ctxt_sep		char(1)
	      , @opt_ctxt_num_pat	varchar(6)
	      , @option_item		varchar(16)	-- single option item

	      -- Context block min/max values.
	      , @context_block		int		-- value of ctxt block
	      , @min_ctxt_linenum	int
	      , @max_ctxt_linenum	int
	      , @default_numlines	tinyint
	      , @noparams		tinyint

	      -- Tracing levels.
	      , @trace_row		tinyint
	      , @trace_row_text		tinyint	-- unimplemented
	      , @trace_subtext		tinyint
	      , @trace_iterations	tinyint
	      , @trace_hang_for_debug	tinyint
	      , @retval			int
	      , @option_found		tinyint

	select @retval		= 0

	-- Avoid noise errors; validate input data.
	if (@startline < 0)
	begin
		select @text = "'@startline'=" + convert(varchar,@startline)
		raiserror 19060, "sp_showtext", @text
		select @retval = 1
	end

	if (@numlines_or_ctxt < 0)
	begin
		select @text = "'@numlines_or_ctxt'=" + convert(varchar,@numlines_or_ctxt)
		raiserror 19060, "sp_showtext", @text
		select @retval = 1
	end

	if (@retval != 0)
		return @retval

	set nocount on

	select    @linenum 		= 0	-- ASE counts from 0
		, @trace_linenum	= 0
		, @trace_linenum_ctxt	= 2
		, @subtext 		= NULL
		, @newline 		= char(10)
		, @tabchar		= char(9)
		, @trace_row 		= 1
		, @trace_row_text 	= 2	-- unimplemented
		, @trace_subtext 	= 3
		, @trace_iterations 	= 4
		, @trace_hang_for_debug	= 99
		, @text_is_hidden	= 0	-- assume text is not hidden
		, @min_ctxt_linenum	= 0
		, @max_ctxt_linenum	= 0
		, @default_numlines	= 5
		, @noparams		= 0

		-- Initialize print fmt strings for typical trace outputs.
		, @trace_newline_fmtstr1 = ">>> trace: (Curr line#=%1!) Found a newline at location %2!. text=[%3!]"
		, @trace_newline_fmtstr2 = ">>> trace: subtext=[%1!]"

		-- Initialize string constants for print options (documented)
		--
		, @opt_sep		= ","
		, @opt_showsql		= "showsql"
		, @opt_linenumbers	= "linenumbers"
		, @opt_comments		= "comments"
		, @opt_rightjustify	= "rightjustify"
		, @opt_leftjustify	= "leftjustify"
		, @opt_ddlgen		= "ddlgen"
		, @opt_context		= "context"
		, @opt_noparams		= "noparams"

		
	-- ###############################################################
	-- Remember whether we are working with procedure groups.
	-- Setup some default print options, and values
	--
	select	  @curr_group 		= 0
		, @multiple_groups      = 0
		, @print_lnumbers 	= 0
		, @right_just 		= 1	-- default
		, @print_lcomment 	= 0
		, @grep_ctxt		= 0
		, @context_block	= 5	-- default value
		, @gen_ddl 		= 0
		, @subtext_size		= 1023	-- max size of PRINT command
		, @dbname		= db_name()

	-- ###############################################################
	-- Extract out and identify each print option requested.
	--
	if (@printopts = 'help')
	begin
		exec @retval = sp_showtext_usage @context_block
						, @opt_showsql
						, @opt_linenumbers
						, @opt_comments
						, @opt_leftjustify
						, @opt_rightjustify
						, @opt_ddlgen
						, @opt_context
						, @opt_noparams
		return @retval
	end
	else if (@printopts IS NOT NULL)
	begin
		while (1 = 1)
		begin	-- {

			exec @option_found = sp_getopts @printopts
							, @opt_sep
							, @option_item output
							, @printopts output

			-- Terminate loop when we found all options.
			if (@option_found = 0)
				break

			-- Support lower and upper-case, and mixed-case.
			select @option_item = lower(@option_item)

			-- Decode option specified and set local variable.
			--
			if (@option_item = @opt_linenumbers)
			begin
				select @print_lnumbers = 1

				-- If we are already asked to print in DDL
				-- style, then line #s will only be printed in
				-- comments, so that the output can be used to
				-- create the DDL.
				if (@gen_ddl = 1)
					select @print_lcomment = 1
			end

			-- Option 'comments' => 'linenumbers'
			else if (@option_item = @opt_comments)
				select @print_lnumbers = 1, @print_lcomment = 1

			else if (@option_item = @opt_rightjustify)
				select @right_just = 1

			else if (@option_item = @opt_leftjustify)
				select @right_just = 0
			else if (@option_item = @opt_ddlgen)
			begin
				select @gen_ddl = 1
				
				-- This option is not supported for the object
				-- type 'partition condition'
				if (@objtype = "N")
				begin
					exec sp_getmessage 17587, @text output
					select @text = @text + " (" + @objname + ")"
					raiserror 19859, 'showsql, ddlgen', @text
					return (1)
				end
				-- If we are also asked to print line#s, then
				-- always print line#s in comments, so that the
				-- resulting DDL is usable as a script.
				--
				if (@print_lnumbers = 1)
					select @print_lcomment = 1

				-- Suppress it so that we don't get any
				-- messages from isql, in the output script,
				-- that needs to be run as a stand-alone DDL
				-- script.
				--
				set proc_return_status OFF
			end

			else if (@option_item = @opt_context)
			begin
				-- This option is not supported for the object
                                -- type 'partition condition'
                                if (@objtype = "N")
                                begin
					exec sp_getmessage 17587, @text output
                                        select @text = @text + " (" + @objname + ")"
                                        raiserror 19859, 'showsql, context', @text
                                        return (1)
                                end

				-- Once the user has specified 'context' in
				-- the print options, we *are* going to give 
				-- some context block. Use the user given
				-- context block value if it's non-zero.
				-- If it is 0, use a default value.
				--
				select @context_block =
						case 
						  when (@numlines_or_ctxt > 0)
						  then @numlines_or_ctxt
						  else @default_numlines
						end
				     -- , @print_lnumbers = 1
				     , @grep_ctxt = 1
			end

			else if (@option_item = @opt_noparams)
			begin
				select @noparams = 1
			end
			else if (@option_item != @opt_showsql)
			begin
				-- Build the list of valid option.
				select @text = @opt_showsql
					     + @opt_sep
					     + @opt_linenumbers
					     + @opt_sep
					     + @opt_comments
					     + @opt_sep
					     + @opt_rightjustify
					     + @opt_sep
					     + @opt_leftjustify
					     + @opt_sep
					     + @opt_ddlgen
					     + @opt_sep
					     + @opt_context
					     + @opt_sep
					     + @opt_noparams

				raiserror 18640 , "'print'", @option_item 
					, @text
				return 1
			end

		end	-- }
	end

	/*
	** See if the object is hidden (SYSCOM_TEXT_HIDDEN will be set)
	*/
	if exists (select 1
		   from syscomments
		   where (status & 1 = 1)
		     and id = object_id(@objname))
	begin
		select @text_is_hidden = 1
	end

	-- ###############################################################
	-- Validate options; check for mutually exclusive ones.
	--
	if (@grep_ctxt = 1) and (@gen_ddl = 1)
	begin
		-- Inject comment marker in 1st arg of this info msg.
		exec sp_getmessage 19639, @text output
		print @text, '--', @opt_context, @opt_ddlgen, @opt_context

		-- Reset local vars relating to context-block generation.
		select @grep_ctxt 		= 0
		     , @context_block		= 0
		     , @numlines_or_ctxt	= 0
	end

	-- ###############################################################
	-- Start generating DDL if requested.

	if (@gen_ddl = 1)
	begin
		-- Generate 'use <dbname>' with blank line after 'go'
		print "use %1!%2!go%3!%4!"
			, @dbname, @newline, @newline , @newline

		select @text = user_name()
		print "IF EXISTS (SELECT 1 FROM sysobjects"
	   	print "           WHERE name = '%1!'" , @objname
	     	print "             AND id = object_id('%1!')", @objname
	     	print "             AND type = '%1!')" , @objtype

		-- We don't have to deal with compiled objects of type RI
		-- as these don't have rows in syscomments.
		--
		select @dropcmd = @tabchar
				+ "DROP "
				+ case @objtype
				     when "P"  then 'PROCEDURE %1!'
				     when "TR" then 'TRIGGER %1!'
				     when "V"  then 'VIEW %1!'
				     when "R"  then 'RULE %1!'
				     when "D"  then 'DEFAULT %1!'
				     when "F"  then 'FUNCTION %1!'
				     else "print '-- Unknown object type: '"
				     		+ @objtype
				  end
		print @dropcmd, @objname
		print "go"

		if (@text_is_hidden = 1)
		begin
			select @proc_id = object_id(@objname)
			raiserror 18406, @objname, @proc_id
			return (1)
		end
	end

	-- ###############################################################
	-- If we are asked to generate a context block of SQL text, help
	-- the user by printing the sproc's name, and extract out some
	-- arguments from syscolumns. This will give a bit more context to
	-- the context block.
	--
	if (@grep_ctxt = 1)
	begin
		if (@noparams = 0)
		begin
			exec @retval = sp_showtext_sproc_tagline
							  @objname
							, @objtype
			if (@retval != 0)
				return @retval
		end

		-- If text is hidden, we can't do much else trying to get a
		-- context block. Bail out after generating the parameter
		-- info. DON'T raise an error here, but just print a message,
		-- so that if this proc is called from other procs (that are
		-- drilling-down to the sproc's text using data from other
		-- sources), the caller procs don't get a needless error.
		-- Getting an error from here might affect the execution
		-- logic of the caller proc.
		--
		if (@text_is_hidden = 1)
		begin
			exec sp_getmessage 18406, @text output
			select @proc_id = object_id(@objname)
			print @text, @objname, @proc_id
			return 0
		end
	end

	-- Now that the only thing left is to extract the text, raise an
	-- error if the text is hidden. There is nothing we can do here.
	if (@text_is_hidden = 1)
	begin
		select @proc_id = object_id(@objname)
		raiserror 18406, @objname, @proc_id
		return 1
	end

	-- Setup min/max context block line numbers, depending on whether
	-- we are searching for a context block, or simply serching for
	-- a given # of lines.
	--
	if (@grep_ctxt = 1)
	begin
		select @min_ctxt_linenum = (@startline - @context_block)
		     , @max_ctxt_linenum = (@startline + @context_block)
	end
	else if (@numlines_or_ctxt > 0)
	begin
		-- Leave this as-is, and don't try to do "- 1 " for loop
		-- termination. In some cases, we still have to process
		-- after we do "goto end_cursor" whatever is the remaining
		-- SQL fragment of the 'last' line that gets  printed
		-- inside this loop.
		--
		select @max_ctxt_linenum = (@startline + @numlines_or_ctxt)
	end

	-- ###############################################################
	if (@trace = @trace_row)
	begin
		print ">>> trace print_lnumbers: %1! right_just: %2! print_lcomment: %3! gen_ddl: %4! trace: %5! startline=%6! min_ctxt_linenum=%7! max_ctxt_linenum=%8! grep_ctxt=%9!"
			, @print_lnumbers, @right_just, @print_lcomment, @gen_ddl
			, @trace
			, @startline
			, @min_ctxt_linenum
			, @max_ctxt_linenum
			, @grep_ctxt
	end

	-- ###############################################################
	-- Process each text row from syscomments.
	-- ###############################################################

	declare curline cursor for
	select number, text, charlength_text, colid2, colid
	from #syscomments
	order by line

	open curline

	while (1 = 1)
	begin	-- {
		fetch curline into @grouping_num
				 , @text
				 , @datalength
				 , @colid2
				 , @colid
		if (@@sqlstatus != 0)
			break

		-- bail out early if we are already past the # of lines
		-- needed to be processed.
		--
		if (    ( (@grep_ctxt = 1) or (@numlines_or_ctxt > 0))
		    and (@linenum >= @max_ctxt_linenum) )
		begin
			goto end_cursor
		end

		select @datalength_act = datalength(@text)

		-- Print a leader line if procedure group changes or
		-- in case of object type being partition condition,
		-- print a newline character to mark the change of
		-- the partition condition row
		if (@curr_group != @grouping_num)
		begin
			if (@gen_ddl = 1) and (@grouping_num >= 2)
				print "go%1!", @newline

			if (@objtype = "N") and (@grouping_num >= 2)
			begin
				-- Only in case of multiple partition condition
				-- rows to be printed, add a newline at the
				-- beginning of the row. Otherwise, keep it as 
				-- it is to avoid extra leading empty line.
				if (@multiple_groups = 1)
					select @text = @newline + @text
			end

			select    @curr_group = @grouping_num
                                , @multiple_groups = 1

				-- In case of partition condition object, see
				-- that the linenumber starts with 1 and 
		                -- continues to be the same value provided by 
				-- the previous loop(as the increment by 1 for 
				-- every encounter of newline is taken care of 
				-- in the previous loop).However, in case of 
				-- procedure object, linenumber is set back to 
				-- 1 as the procedure group changes.

		                , @linenum = case @objtype
                                             when "N"
                                                then case @linenum
                                                     when 0 then 1
                                                     else @linenum
                                                     end
                                             else 1
                                             end
		end

		if (@trace = @trace_subtext)
		begin
			print ">>> trace: (line#=%1! colid2=%2! colid=%3!) Found a new row of length=%4!, actual length=%5! text: [%6!]"
				, @linenum, @colid2, @colid
				, @datalength, @datalength_act, @text
		end

		-- Find if this text line has a newline char in it.
		select @newline_loc = charindex(@newline, @text)

		-- Passing in a -ve trace level means user
		-- is interested in tracing the processing of
		-- SQL around that line number. Convert the
		-- trace to a real line number.
		--
		if (@trace < 0)
		begin
			select @trace_linenum = abs(@trace)

			if (@trace_linenum between
				     (@linenum - @trace_linenum_ctxt)
				 and (@linenum + @trace_linenum_ctxt))
			begin
				print @trace_newline_fmtstr1
					, @linenum, @newline_loc, @text
				print @trace_newline_fmtstr2
					, @subtext
			end
		end

		-- While there are newline chars embedded, output ind. lines.
		--
		while (@newline_loc != 0)
		begin	-- {
			if (@trace < 0)
			begin
				-- Passing in a -ve trace level means user
				-- is interested in tracing the processing of
				-- SQL around that line number. Convert the
				-- trace to a real line number.
				--
				select @trace_linenum = abs(@trace)

				if (@trace_linenum between
					     (@linenum - @trace_linenum_ctxt)
					 and (@linenum + @trace_linenum_ctxt))
				begin
					print @trace_newline_fmtstr1
						, @linenum, @newline_loc, @text
					print @trace_newline_fmtstr2
						, @subtext
				end
			end

			else if (@trace = @trace_iterations)
			begin
				print @trace_newline_fmtstr1
					, @linenum, @newline_loc, @text
				print @trace_newline_fmtstr2
					, @subtext
			end

			-- Extract out the prefix portion of the line.
			-- If there is a blank line in the code, we will
			-- get it here as a 1st char in the newline. In
			-- that case, pass that one through, so that we
			-- print blank lines also.
			--
			select @subtext = substring(@subtext, 1,
						    (char_length(@subtext) - 1) )
					+ case @newline_loc
					     when 1 then @newline
					     else substring(@text, 1,
					     		@newline_loc - 1)
					  end

			-- Skip this logic when applying it to this *very*
			-- sproc. Otherwise, we will end up incorrectly
			-- decrementing line#s for this sproc, whereas the
			-- embedded string is really in code, and not generated
			-- by SELECT * expansion.
			--
			if (    (@subtext LIKE
					"%Adaptive Server has expanded all%")
			    and (@grep_ctxt = 1)
			    and (@objname != 'sp_showtext_output') )
			begin
				-- In 12.5.x, we didn't use to leave any 
				-- newlines before and after the generated
				-- message. In 15.0 onwards, we leave two
				-- blank lines. Account for that in this 
				-- line# book-keeping logic.
				--
				select @linenum = @linenum
						   - (case @@version_as_integer
						       when 12500 then 0
						       else 2
						      end)
			end

			-- Generate line number as a 5-char wide string,
			-- right justified.
			--
			exec @do_print = sp_showtext_check_print
						  @startline
						, @numlines_or_ctxt
						, @grep_ctxt
						, @min_ctxt_linenum
						, @max_ctxt_linenum
						, @linenum
						, @gen_ddl
			if (@do_print != 0)
			begin
				exec sp_showtext_print_line
						  @print_lnumbers
						, @right_just
						, @print_lcomment
						, @grep_ctxt
						, @linenum
						, @subtext
						, @do_print
						, @trace
						, @trace_hang_for_debug
			end

			select @linenum = @linenum + 1

			-- Strip out the leading part before newline
			-- that just got printed above. The remaining portion
			-- will be what we will process further looking for
			-- more newlines to break out.
			--
			select @text = stuff(@text, 1, @newline_loc, NULL)

			select @newline_loc = charindex(@newline, @text)
			     , @subtext = NULL
		end	-- }

		-- Retain the balance remaining to be concatenated with the 
		-- start of the next line. When we saved off the text data
		-- into a #temp table in the caller, an artificial terminator
		-- byte was padded to avoid truncation of trailing blanks
		-- when the FETCH would happen. This artificial terminator will
		-- be skipped when re-generating the text back.
		--
		select @charlength = char_length(@text)

		if (@charlength = 1 and (@text = @newline) )
		begin
			print "%1!", @text
		end
		else if ( (@charlength = 2)
		      and (@text = @newline + @art_terminator) )
		begin
			select @text = substring(@text, 1, 1)
			print "%1!", @text
		end
		else if (@charlength != 0)
		begin	-- {
			-- We might have accumulated an internally generated
			-- terminator byte. Strip that out first before
			-- we concatenate the subtext from the previous
			-- iteration to the text.
			--
			-- If we are already full in the sub-text buffer
			-- that we've been accumulating, dump that out now,
			-- so that the user at least gets some data even
			-- though the newline might not be at at the right
			-- location. (This restriction arises from SQL PRINT
			-- command that has a limit of 1024 bytes.)
			--
			select @charlength = char_length(@subtext)

			if (datalength(@subtext) + datalength(@text)
					> @subtext_size)
			begin	-- {
				select @subtext = substring(@subtext, 1,
							(@charlength - 1))

				-- Find the last ", " character in the string,
				-- which is most likely the separator for the
				-- list of columns in the expanded SELECT *
				-- output. Truncate the list there and print
				-- this piece on one line. As we are doing
				-- the charindex() search on the reverse of
				-- the string, search for " ,".
				--
				select @charlength_st = char_length(@subtext)

				select @space_loc = @charlength_st
						  - (charindex(' ,',
						  	reverse(@subtext)) )

				-- Save trailing piece for now, so that we
				-- can restore it after printing header piece.
				-- (Reuse variable to save space.)
				--
				if (@space_loc > 0)
				begin
					select @dropcmd = substring(@subtext,
							    @space_loc,
							    (@charlength_st
							    	- @space_loc))

					select @subtext = substring(@subtext, 1,
							    (@space_loc - 1))
				end

				if (    (@subtext LIKE
						"%Adaptive Server has expanded all%")
				    and (@grep_ctxt = 1)
				    and (@objname != 'sp_showtext_output') )
				begin
					select @linenum = @linenum - 2
				end

				-- Generate line number as a 5-char wide string,
				-- right justified.
				--
				-- Do *NOT* increment the line#s here, as all
				-- we are doing is dumping out stuff that
				-- we don't have room for in our buffers. This
				-- text is (probably) internally generated
				-- by SELECT * expansion and there are no new
				-- lines in this generated text.
				--
				exec @do_print = sp_showtext_check_print
							  @startline
							, @numlines_or_ctxt
							, @grep_ctxt
							, @min_ctxt_linenum
							, @max_ctxt_linenum
							, @linenum
							, @gen_ddl
				if (@do_print != 0)
				begin
					exec sp_showtext_print_line
							  @print_lnumbers
							, @right_just
							, @print_lcomment
							, @grep_ctxt
							, @linenum
							, @subtext
							, @do_print
							, @trace
							, @trace_hang_for_debug
				end

				/*
				** Don't increment any line# variable here
				** as this is for a lapsed case where the
				** text in syscomments is essentially one
				** long line, but PRINT can't print it in
				** one piece. So we print it in sub-chunks.
				*/

				-- Restore trailing piece that was saved off,
				-- if any. @subtext will be retained for the
				-- next iteration, and is known to not
				-- contain any more newlines. This piece
				-- will be prependended to the next text
				-- fragment found.
				--
				select @subtext = case @space_loc
						     when 0 then NULL
						     else @dropcmd
						  end
						+ @text

			end	-- }
			else
			begin
				-- @subtext was retained as the trailing text
				-- fragment from the previous row. It would
				-- have contained the artificial terminator
				-- char. Strip that off first, before appending
				-- the currently found text fragment to the
				-- trailing fragment from the previous row.
				--
				select @subtext
					= substring(@subtext, 1,
						    (@charlength - 1))
						+ @text

				if (@trace = @trace_subtext)
				begin
					print ">>> trace: subtext:[%1!]", @subtext
				end
			end
		end	-- }
		else
		begin
			select @subtext = NULL
		end

	end	-- }

end_cursor:
	close curline

	deallocate cursor curline

	-- ###############################################################
	-- There still might be a last piece of text left over after the
	-- cursor has finished. This happens when non-isql applns create
	-- a procedure (e.g. through CT-lib appln) and do not provide a
	-- newline terminator for the last line. Print that out.
	--

	exec @do_print = sp_showtext_check_print
				  @startline
				, @numlines_or_ctxt
				, @grep_ctxt
				, @min_ctxt_linenum
				, @max_ctxt_linenum
				, @linenum
				, @gen_ddl
	if ((@subtext != "," and char_length(@subtext) > 1)
	and (@do_print != 0) )
	begin
		select @subtext = substring(@subtext, 1,
					    (char_length(@subtext) - 1))
		if (    (@subtext LIKE
				"%Adaptive Server has expanded all%")
		    and (@grep_ctxt = 1)
		    and (@objname != 'sp_showtext_output') )
		begin
			select @linenum = @linenum - 2
		end

		exec sp_showtext_print_line
				  @print_lnumbers
				, @right_just
				, @print_lcomment
				, @grep_ctxt
				, @linenum
				, @subtext
				, @do_print
				, @trace
				, @trace_hang_for_debug
	end

	-- Just one \n after go is enough. Don't inject what user's scripts
	-- might now already have.
	--
	if (@gen_ddl = 1)
	begin
		print "go%1!", @newline
	end
end
go	-- }


if (@@error != 0) select syb_quit()
go

drop table #syscomments
go

exec sp_dbxt_recreate_proc sp_showtext
go

/*
** sp_showtext
**
**	Procedure to extract SQL text from syscomments and display it
**	with the actual line numbers that were present in the original
**	script used to create the compiled object. Supports options
**	via 'printopts' to produce line #s in comments, left/right-
**	justified, as a DDL script (i.e. with matching DROP command
**	generated) etc. See comments in sp_showtext_output for various
**	print options.
**
**	This procedure derives its main skeleton from sp_helptext but
**	then very soon diverges into SQL text parsing code that produces
**	properly formatted SQL text with line #s, and much more.
**
** Parameters:
**	@objname	- Name of compiled object to generate text for.
**			  (Use ';n' to specify grouping # for sprocs.)
**	@startline	- Display text starting from this line #.
**	@numlines	- Number of lines to print, or context block to show 
**			  around SQL at line @startline
**	@printopts	- Various print options. See callee.
**	@trace		- Debugging trace flag. (Internal use only.)
{
*/
create procedure sp_showtext
	  @objname		varchar(325)	= NULL
	, @startline		int		= 0
	, @numlines_or_ctxt	int		= 0
	, @printopts		varchar(256)	= NULL
	, @trace		int		= 0
as
begin
declare @text_count	int
      , @sitename	varchar(30)	-- unused
      , @dbname		varchar(30)
      , @ownername	varchar(30)
      , @obj_name	varchar(260)	-- allow for 5-byte <nnnnn> group #.
      , @grouping_num	int
      , @group_num_str	varchar(10)
      , @config_parm 	int
      , @issystemproc 	int
      , @procval 	int
      , @proc_id 	int
      , @charindex	int		-- of ';' separator for groups
      , @objtype 	varchar(2)
      , @tot_members 	int
      , @retval		int
      , @error		int	
      , @ins_select_str	varchar(1024)
      , @nrows_inserted	int
      , @art_terminator	char(1)		-- artificial terminator byte

/* If @objname is NULL, show some help info and quit. */
if (@objname IS NULL)
begin
	exec sp_showtext_usage  5
				, 'showsql'
				, 'linenumbers'
				, 'comments'
				, 'leftjustify'
				, 'rightjustify'
				, 'ddlgen'
				, 'context'
				, 'noparams'
	return 0
end

if (@@trancount > 0)
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_showtext"
	return (1)
end

set chained off
set transaction isolation level 1
set nocount ON

-- Crack open the name into its individual components.
exec sp_namecrack @objname, @sitename output
			  , @dbname output
			  , @ownername output
			  , @obj_name output
	
/*
**  Make sure the @obj_name is local to the current database.
*/
if (@dbname IS NOT NULL) and (@dbname != db_name())
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
end

/* See if @obj_name has a group # reference. Strip it out first. */
select @charindex = charindex(';', @obj_name)
if (@charindex != 0)
begin
	-- This is the piece of string following ';'
	select @group_num_str = ltrim(rtrim(substring(@obj_name,
						      (@charindex + 1),
						      (char_length(@obj_name)
						        - @charindex)) ) )

	if (patindex("%[^0-9]%", @group_num_str) = 0)
	begin
		select @grouping_num = convert(int, @group_num_str)
		     , @obj_name = substring(@obj_name, 1, (@charindex - 1))
	end
	else
	begin
		raiserror 19060, 'sp_showtext', @group_num_str
		return 1
	end
end

--  See if @objname exists. Reconstruct @objname from its parts.
select @objname = case when @dbname IS NULL then NULL else @dbname + '.' end
		+ case when (@ownername IS NULL and @dbname IS NULL)
			then NULL
		       when @ownername IS NULL then "."
		       else @ownername + '.'
		  end
		+ @obj_name

if (object_id(@objname) is NULL)
begin
	/* 17461, "Object does not exist in this database." */
	raiserror 17461
	return (1)
end

/*
** If the configuration parameter 'allow select on syscomments.text' is set to
** 0, then  the user can use sp_showtext ONLY in the following cases
** 
**	1. if the user has sa_role
**	2. if the object is a system stored procedure
**	3. if the object is owned by the user
**
*/
select @config_parm = value 
from master.dbo.syscurconfigs 
where config = 258

select @issystemproc = 1		/* It is a system stored procedure */

if (@config_parm = 0)
begin
	/*
	** If the user is DBO or an account with sa_role, it's all fine
	*/
	if (user_id() != 1)
	begin
		if (db_name() != "master" and db_name() != "sybsystemprocs")
		begin
			/*
			** System Stored Procedures can only be in master or
			** sybsystemsprocs database.
			*/
			select @issystemproc = 0
		end
		else
		begin
			/*
			** We are in either sybsystemprocs or master database.
			** See if the name starts with "sp_" and is owned by
			** the DBO.
			*/
			select @obj_name = name
			from sysobjects
			where id = object_id(@objname)
			  and uid = 1
			if (substring(@obj_name,1,3) != "sp_")
				select @issystemproc = 0
		end

		/*
		** If it is not a system stored procedure, then it needs to be
		** owned by the user.
		*/
		if @issystemproc = 0
		begin
			/*
			** The object needs to be owned by the user
			*/
			if not exists (select name from sysobjects
				       where uid = user_id()
				         and id = object_id(@objname))
			begin
				raiserror 18180
				return(1)
			end
		end
	end
	else
	begin
		/*
		** Audit this as a successful sa command execution if the user
		** has sa role.
		*/
		if charindex("sa_role", show_role()) > 0
			select @procval = proc_role ("sa_role")
	end
end

/*  Validate grouping number */
select @objtype = rtrim(type) from sysobjects where id = object_id(@objname)

/*
** The group number is for stored procedures, but is overloaded
** for the partition order of the partition condition object.
** Using @grouping_num n means to get the nth partition condition
** text.
*/
if (@objtype NOT IN ('P', 'N')) and (@grouping_num is not null)
begin
	-- You cannot use a grouping number for non-procedures.
	raiserror 18936
	return(1)
end

/*
** Find out how many lines of text are coming back.
** and return if there are none.
*/
select @text_count = count(*)
from syscomments
where id = object_id(@objname)
  and ( (@grouping_num IS NULL) OR (number = @grouping_num))

if (@text_count = 0)
begin
	if (@grouping_num IS NULL)
	begin
		/* 17679, "There is no text for object @objname." */
		raiserror 17679, @objname
	end
	else
	begin
		raiserror 18937, @objname, @grouping_num
	end
	return 1
end

-- Create a template temp table for use in all cases.
-- The charlength_text column is used to first save off the length of the text
-- column that will be fetched. That length is needed if in case the text
-- column has any trailing blanks that get truncated, we need to re-gen those
-- missing blanks during printing. Use 'master.dbo.syscomments' to avoid any
-- unnecessary catalog b/locking issues in tempdb.
--
select    line = identity(5), number
	, text = convert(varchar(257), "")
	, charlength_text = convert(int, 0)
	, colid2, colid
into #syscomments
from master.dbo.syscomments
where 1 = 0

-- Start generating the INSERT SELECT SQL statement that will then be
-- changed based on whether the user has requested for a sproc with a
-- particular group #.
--
select @art_terminator = '`'
select @ins_select_str = "INSERT #syscomments(number, text, charlength_text"
		       + ", colid2, colid)"
		       + " SELECT number"
		       + ", text + '" + @art_terminator + "'"
		       + ", char_length(text + '" + @art_terminator + "')"
		       + ", colid2, colid"
		       + " FROM syscomments"
		       + " WHERE id = object_id('" + @objname + "')"

		/*
		NOTE: If you add an ORDER BY to do some improved INSERT SELECT,
		we seem to be running in an issue (at least in 15.0) where the
		'text' column is being truncated before the ORDER BY is applied.
		So this messes up the result lengths etc., and we end up losing
		trailing blanks if the 'text' column had some trailing blanks.

		order by number, colid2, colid
		print "Data from SELECT ..."
		select number
		     , charlength_text = char_length(text + ']') -- - 1
		     , colid2, colid
		from syscomments
		where id = object_id(@objname)
		  and colid IN (9, 13, 21, 26, 4245, 46)

		print "Data from INSERTED table #syscomments..."
		select number, charlength_text, colid2, colid
		from #syscomments
		where colid IN (9, 13, 21, 26, 4245, 46)
		*/

/* procs with @grouping_num >= 0 */
if (@grouping_num is NOT NULL)
begin
	select @ins_select_str = @ins_select_str
			       + " AND number = "
			       + str(@grouping_num)
end

-- Ensure that we select rows to be inserted in the proper order, so that the
-- text can be re-generated in the order it was created. In all possible cases,
-- the correct order of rows is achieved  by the key (number, texttype, colid2, 
-- colid). 
select @ins_select_str = @ins_select_str
			  + " ORDER BY texttype, colid2, colid"

-- Execute the INSERT SELECT, and bail out if there are errors.
exec (@ins_select_str)
select @error = @@error, @nrows_inserted = @@rowcount
if (@error != 0) or (@nrows_inserted != @text_count)
begin
	print "Internal error. Inserted %1! rows to temporary table '%2!'. Expected to insert %3! rows.",
		@nrows_inserted, "#syscomments", @text_count
	return @error
end

-- Hopefully a faster access method with ORDER BY line clause.
create index syscomm_ncind_line on #syscomments(line)

-- Handle NULL args for those that we really want defaults.
--
if (@startline IS NULL) 	select @startline = 0
if (@numlines_or_ctxt IS NULL)	select @numlines_or_ctxt = 0

exec @retval = sp_showtext_output @objname, @objtype
				, @startline
				, @numlines_or_ctxt
				, @printopts
				, @trace
				, @art_terminator
if (@retval != 0)
	return (@retval)
end		-- }
go
go
exec sp_procxmode 'sp_showtext_usage', 'anymode'
go
grant execute on sp_showtext_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_showtext_print_line', 'anymode'
go
grant execute on sp_showtext_print_line to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_showtext_check_print', 'anymode'
go
grant execute on sp_showtext_check_print to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_showtext_sproc_tagline', 'anymode'
go
grant execute on sp_showtext_sproc_tagline to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_showtext_output', 'anymode'
go
grant execute on sp_showtext_output to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_showtext', 'anymode'
go
grant execute on sp_showtext to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helptext_usage')
begin
	drop procedure sp_helptext_usage
end
go
print "Installing sp_helptext_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helptext')
begin
	drop procedure sp_helptext
end
go
print "Installing sp_helptext"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:38 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/helptext [Total 9]
**
** 17460, "Object must be in the current database."
** 17461, "Object does not exist in this database."
** 17679, "There is no text for object '%1!'."
** 18180, "Configuration Parameter 'select on syscomments.text' is set to 0. Only the object owner or user with sa_role can run sp_helptext on this object."
** 18406, "Source text for compiled object %1! (id = %2!) is hidden."
** 18936, "You cannot use a grouping number for non-procedures."
** 18937, "There is no text for object '%1!' with grouping number %2!."
** 19060, "Procedure %1!, %2! must be a positive integer."
** 19384, "The '%1!' parameter is required with '%2!' parameter."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/helptext [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

exec sp_dbxt_recreate_proc sp_helptext_usage
go

/*
** sp_helptext_usage
**
**	Print help/usage information for sp_helptext procedure, with
**	useful examples. Help info is generated by default when sp_helptext
**	is invoked with no arguments. This then calls into the extended
**	sproc, sp_showtext, which will generate its help/usage information.
{
*/
create procedure sp_helptext_usage
as
begin
	declare @procname	varchar(12)

	print "Usage: sp_helptext [ '@objname' [, @grouping_num] [, ... ] ]"

	print " "
	print "  -- Generate text for a given procedure in a group, use either one of:"
	print "	sp_helptext grouped_proc, 3"
	print "	sp_helptext 'grouped_proc;3'"

	print " "
	print "  -- To generate formatted SQL, use 'showsql' in @printopts, as:"
	print "	sp_helptext sp_helptext, 5, 10, 'showsql'"

	print " "
	select @procname = 'sp_showtext'
	exec @procname

end	-- }
go

if (@@error != 0) select syb_quit()
go

/*
** NOTE about @objname length:
**
** @objname can be <dbname>.<ownername>.<objectname>;<nnnnnnn>
**                  (30)      (30)         (255)       (5, randomly chosen)
**
** where <nnnnnnn> is the partition number (for partition condition object)
** or procedure group number. Hence total length is 318 + some change for
** <nnnn>, for a total of 325 bytes.
**
*/
exec sp_dbxt_recreate_proc sp_helptext
go

/*
** sp_helptext
**
**	Top-level procedure to generate text for a compiled object from
**	syscomments. This interface supports the standard interface to extract
**	255-byte chunks of text from syscomments, and also provides an
**	interface to call into the expanded text-reporting utility procedure,
**	sp_showtext. The call-out to that procedure is through the extended
**	@printopts argument.
**
** Parameters:
**	@objname	- Name of compiled object to generate text for.
**	@grouping_num	- Sproc grouping number.
**
** If the @printopts arg is used to specify the 'showsql' argument, then
** the meaning of various parameters is as follows:
**
**	@grouping_num	- Starting line # from which to generate text.
**	@numlines	- Number of lines of text to generate.
**	@printopts	- Comma-separated string of qualifiers for the
**			  generated text.
**	@trace		- Trace facility; for internal use only.
**
** The @objname arg can be used in one of two ways:
**
**	sp_helptext <objname>, 3
**	sp_helptext "<objname>;3", 5, 20, 'showsql'
**
** In the first way, '3' is the procedure group number (for procedure
** groups), or is the partition condition number when <objname> is a partition
** condition type.
**
** In the second way, the group number or partition condition number '3' is
** snuck away as part of the object name. Then, as we are running in 'showsql
** mode, the next two args are (starting line#, # of lines).
**
** See the help/usage info for more details on the interface with examples.
{
*/
create procedure sp_helptext(
		  @objname 		varchar(325)	= NULL
		, @grouping_num 	int 		= NULL
		, @numlines		int 		= NULL
		, @printopts		varchar(256)	= NULL
		, @trace		int		= 0
) as
begin
declare @text_count int
declare @name varchar(255)
declare @config_parm int
declare @issystemproc int
declare @procval int
declare @proc_id int
declare @type char(2)
declare @tot_members 	int
      , @objname_orig	varchar(325)	-- What user entered.
      , @group_num_str	varchar(10)
      , @opt_showsql	varchar(7)
      , @char_index	int
      , @retval		int

if (@objname IS NULL)
begin
	exec sp_helptext_usage
	return 0
end

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @objname_orig = @objname
     , @opt_showsql = 'showsql'

/* See if @objname has a group # reference. Strip it out first. */
select @char_index = charindex(';', @objname)
if (@char_index != 0)
begin
	-- This is the piece of string following ';'
	select @group_num_str = ltrim(rtrim(substring(@objname,
						      (@char_index + 1),
						      (datalength(@objname)
						        - @char_index)) ) )

	-- Retrieve just the, possibly multi-part, object name.
	select @objname = substring(@objname, 1, (@char_index - 1))
end
/*
**  Make sure the @objname is local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return (1)
end

/*
**  See if @objname exists.
*/
if (object_id(@objname) is NULL)
begin
	/* 17461, "Object does not exist in this database." */
	raiserror 17461
	return (1)
end

/*
** If the configuration parameter 'select on syscomments.text' is set to
** 0, then  the user can use sp_helptext ONLY in the following cases
** 
**	1. if the user has sa_role
**	2. if the user is dbo or aliased to dbo
**	3. if the object is a system stored procedure
**	4. if the object is owned by the user
**
** For SMP or SDC, only one row is expected.
*/
select @config_parm = value 
	from master.dbo.syscurconfigs 
where config = 258 


select @issystemproc = 1		/* It is a system stored procedure */

if @config_parm = 0
begin
	/*
	** If the user is DBO or an account with sa_role, it's all fine
	*/
	if (user_id() != 1)
	begin
		if (db_name() != "master" and db_name() != "sybsystemprocs")
		begin
			/*
			** System Stored Procedures can only be in master or
			** sybsystemsprocs database.
			*/
			select @issystemproc = 0
		end
		else
		begin
			/*
			** We are in either sybsystemprocs or master database.
			** See if the name starts with "sp_" and is owned by
			** the DBO.
			*/
			select @name = name from sysobjects where
				id = object_id(@objname)
				and uid = 1
			if (substring(@name,1,3) != "sp_")
				select @issystemproc = 0
		end

		/*
		** If it is not a system stored procedure, then it needs to be
		** owned by the user.
		*/
		if @issystemproc = 0
		begin
			/*
			** The object needs to be owned by the user
			*/
			if not exists (select name from sysobjects 
				where uid = user_id() 
				and id = object_id(@objname))
			begin
				raiserror 18180
				return(1)
			end
		end
	end
	else
	begin
		/*
		** Audit this as a successful sa command execution if the user
		** has sa role.
		*/
		if charindex("sa_role", show_role()) > 0
			select @procval = proc_role ("sa_role")
	end
end

-- ============================================================================ 
-- Check to see if user is running in improved 'showsql' mode, where they
-- are interested in getting text formatted as it was input. If so, call
-- the new sub-proc, and return from here. (Otherwise, we end up calling
-- in legacy mode with pre-showsql semantics for the arguments.)
--
if (@printopts IS NOT NULL)
begin
	if (@printopts LIKE "%" + @opt_showsql + "%")
	begin
		exec @retval = sp_showtext @objname_orig, @grouping_num
					 , @numlines, @printopts, @trace
		return @retval
	end
	else
	begin
		-- A non-NULL @printopts *must* have  at least 'showsql',
		-- otherwise, it's meaningless.
		--
		raiserror 19384, @opt_showsql, "@printopts"
		return 1
	end
end


/*  Validate grouping number */
select @type = type from sysobjects
where id = object_id(@objname)

/*
** The group number is for stored procedures, but is overloaded
** for the partition order of the partition condition object.
** Using @grouping_num n means to get the nth partition condition
** text.
*/
if (@type NOT IN ('P', 'N')) and (@grouping_num is not null)
begin
	/*
	** You cannot use a grouping number for non-procedures.
	*/
	raiserror 18936
	return(1)
end
	
-- Validate the case when both "table;<n>", <m> interface is used, but the
-- user didn't say 'showsql'. That's an error. We only allow "sproc;<n>"
-- notation when sp_showtext will be called.  It's ambiguous to decide
-- what grouping # user means when they have specified it both ways
-- via "proc;3" and the @grouping_num == 5. Error out.
--
if (@group_num_str IS NOT NULL)
begin
	if (@grouping_num IS NOT NULL)
	begin
		-- We will really never come here as the missing 'showsql'
		-- has been trapped earlier, already. Just in case, report
		-- a generic error.
		--
		raiserror 19384, @opt_showsql, @objname_orig
		return 1
	end
	else if (patindex("%[^0-9]%", @group_num_str) = 0)
	begin
		-- Allow "proc;<n>" notation to extract SQL for just one group.
		select @grouping_num = convert(int, @group_num_str)
	end
	else
	begin
		-- Reuse variable to create 2nd arg to error message.
		select @objname_orig = "@grouping_num='"
				     + @group_num_str
				     + "'"
		raiserror 19060, 'sp_helptext', @objname_orig
		return 1
	end
end

if @grouping_num is null
begin
	/*
	** Find out how many lines of text are coming back.
	** and return if there are none.
	*/
	select @text_count = count(*)
		from syscomments
	where id = object_id(@objname)

	if @text_count = 0
	begin
		/* 17679, "There is no text for object @objname." */
		raiserror 17679, @objname
		return (1)
	end
end
else
begin
	/*
	** Find out how many lines of text are coming back.
	** and return if there are none.
	*/
	select @text_count = count(*)
		from syscomments
	where id = object_id(@objname) and 
		number = @grouping_num

	if @text_count = 0
	begin
		raiserror 18937, @objname, @grouping_num
		return (1)	
	end
end

/*
** See if the object is hidden (SYSCOM_TEXT_HIDDEN will be set)
*/
if exists (select 1
        from syscomments where (status & 1 = 1)
        and id = object_id(@objname))
begin
        /*
        ** 18406, "Source text for compiled object %!1
        ** (id = %!2) is hidden."
        */
        select @proc_id = object_id(@objname)
        raiserror 18406, @objname, @proc_id
        return (1)
end
	
/*
**  Return # howmany lines of text that are about to come back.
**  This is required by the "old" report writer.
*/
select "# Lines of Text" = @text_count

/*
**  Now get the text.
*/
if @grouping_num is null
begin
	/* Are there multiple group members? */
	select @tot_members = count(distinct number)
		from syscomments
		where id = object_id(@objname)

	if @tot_members > 1
	begin
		/*
		** Display text of all grouped procedures.
		** Include grouping number in output.
		*/
		select number, text = convert(char(255) not null, text)
			from syscomments
			where id = object_id(@objname)
			order by number, texttype, colid2, colid
	end
	else
	begin
		/*
		** Display text of non-grouped procedures and
		** non-procedure objects.  Do not display a grouping
		** number.
		*/
		select text = convert(char(255) not null, text)
			from syscomments
			where id = object_id(@objname)
			order by texttype, colid2, colid
	end
end
else	/* procs with @grouping_num >= 0 */
begin
	/* Display text for an individual group member */
	select text = convert(char(255) not null, text)
		from syscomments 
		where id = object_id(@objname)
		and number = @grouping_num
		order by number, texttype, colid2, colid
end
return (0)
end	-- }
go

if (@@error != 0) select syb_quit()
go
go
exec sp_procxmode 'sp_helptext_usage', 'anymode'
go
grant execute on sp_helptext_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_helptext', 'anymode'
go
grant execute on sp_helptext to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpthreshold')
begin
	drop procedure sp_helpthreshold
end
go
print "Installing sp_helpthreshold"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_helpthreshold"     17910
**
** 17910, "Database '%1!' has no thresholds -- table '%2!' does not exist."
** 17911, "Segment '%1!' does not exist."
*/

create procedure sp_helpthreshold
@segname	varchar(255)=NULL
as

	declare	 @dbname	varchar(255)

select @dbname = db_name()

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
** Make sure our database is recent enough to contain Systhresholds
*/
if (select name from sysobjects
	where	name = 'systhresholds'
	  and	type = 'S')
   is NULL
begin
	/*
	** 17910, "Database '%1!' has no thresholds -- table '%2!' does not
	**	  exist."
	*/
	raiserror 17910, @dbname, "systhresholds"
	return (1)
end

/*
** If user wants a specific segment's thresholds, show those.
*/
if (@segname is not NULL)
begin
	if (select segment from syssegments where name = @segname) is NULL
	begin
		/*
		** 17911, "Segment '%1!' does not exist."
		*/
		raiserror 17911, @segname
		return (2)
	end

	/*
	** Get the threshold information for all the user-defined ones.
	*/
	select	segment_name=s.name,
		free_pages=t.free_space,
		last_chance=t.status,
		threshold_procedure=t.proc_name
	into #sphelpthreshold1rs
	from syssegments s, systhresholds t
	where s.segment = t.segment
	  and s.name = @segname
	  and t.status != 1

	UNION

	/*
	** Get the threshold information for the last chance threshold
	*/
	select  segment_name=s.name,
		free_pages=lct_admin("reserve", 0),
		last_chance=t.status,
		threshold_procedure=t.proc_name
	from syssegments s, systhresholds t
	where s.segment = t.segment
	  and s.name = @segname
	  and t.status = 1
	exec sp_autoformat @fulltabname = #sphelpthreshold1rs,
		@selectlist = "'segment name' = segment_name,'free pages' = free_pages, 'last chance?' = last_chance, 'threshold procedure' = threshold_procedure"
	drop table #sphelpthreshold1rs
	return (0)
end

/*
** Show all thresholds for all segments.
*/
select	segment_name=s.name,
	free_pages=t.free_space,
	last_chance=t.status,
	threshold_procedure=t.proc_name
into #sphelpthreshold2rs
from syssegments s, systhresholds t
where s.segment = t.segment
  and t.status != 1

UNION

select  segment_name=s.name,
	free_pages=lct_admin("reserve", 0),
	last_chance=t.status,
	threshold_procedure=t.proc_name
from syssegments s, systhresholds t
where s.segment = t.segment
  and t.status = 1
exec sp_autoformat @fulltabname = #sphelpthreshold2rs,
	@selectlist = "'segment name' = segment_name,'free pages' = free_pages, 'last chance?' = last_chance, 'threshold procedure' = threshold_procedure"
drop table #sphelpthreshold2rs
return (0)
go
exec sp_procxmode 'sp_helpthreshold', 'anymode'
go
grant execute on sp_helpthreshold to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_lock')
begin
	drop procedure sp_lock
end
go
print "Installing sp_lock"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */
/*
** Messages for "sp_lock"
**
** 18052, "The class column will display the cursor name for locks associated
**	  with a cursor for the current user and the cursor id for other 
**	  users."
*/


create procedure sp_lock
@spid1 int = NULL,		/* server process id to check for locks */
@spid2 int = NULL,		/* other process id to check for locks */
@verbose int = NULL,		/* if set, print object name of locked objects */
@instanceid int = NULL		/* instance id for the locks output */
as

declare @length int
declare @msg varchar(1024)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*  Print warning message about cursor lock info:
**  18052, "The class column will display the cursor name for locks associated
**	   with a cursor for the current user and the cursor id for other 
**	   users."
*/
exec sp_getmessage 18052, @msg out
print @msg


/*
**  Show the locks for both parameters.
*/
if (@verbose IS NULL) AND (@spid1 is not NULL)
begin
	select @length = max(datalength(db_name(dbid)))
	from master..syslocks
		where spid in (@spid1, @spid2)

	if (@length > 15)
	begin

			select fid, spid, loid, locktype = v1.name, table_id = id,
				page, row, dbname = db_name(dbid), class,
				context=v2.name
			from	master..syslocks l,
				master..spt_values v1,
				master..spt_values v2
			where 	l.type = v1.number
				and v1.type = "L"
				and (l.context+2049) = v2.number
				and v2.type = "L2"
				and spid in (@spid1, @spid2)
			order by fid, spid, loid, dbname, table_id, page,
				row, locktype
	end				
	else
	begin

			select fid, spid, loid, locktype = v1.name, table_id = id,
				page, row, dbname = convert(char(15), db_name(dbid)),
				class,context=v2.name
			from	master..syslocks l,
				master..spt_values v1,
				master..spt_values v2
			where 	l.type = v1.number
				and v1.type = "L"
				and (l.context+2049) = v2.number
				and v2.type = "L2"
				and spid in (@spid1, @spid2)
			order by fid, spid, loid, dbname, table_id, page, row, locktype
	end
end	

/*
**  No parameters, so show all the locks.
*/
else if (@verbose IS NULL)
begin
	select @length = max(datalength(db_name(dbid)))
	from master..syslocks

	if (@length > 15)
	begin

			select fid, spid, loid, locktype = v1.name, table_id = id,
				page, row, dbname = db_name(dbid), class,
				context=v2.name
			from	master..syslocks l,
				master..spt_values v1,
				master..spt_values v2
			where	l.type = v1.number
				and v1.type = "L"
				and (l.context+2049) = v2.number
				and v2.type = "L2"
			order by fid, spid, loid, dbname, table_id, page, row, locktype
	end			
	else
	begin

			select fid, spid, loid, locktype = v1.name, table_id = id,
				page, row, dbname = convert(char(15), db_name(dbid)),
				class, context=v2.name
			from	master..syslocks l,
				master..spt_values v1,
				master..spt_values v2
			where 	l.type = v1.number
				and v1.type = "L"
				and (l.context+2049) = v2.number
				and v2.type = "L2"
			order by fid, spid, loid, dbname, table_id, page, row, locktype
	end
end

/*
**  Show the locks for both parameters.
**  Best viewed in wide format. After all we will have long
**  identifiers soon.
*/
else if (@verbose is not NULL) AND (@spid1 is not NULL)
begin

		select fid, spid, loid, locktype = v1.name,
			page, row,
			objectName = rtrim(db_name(dbid)) + '..' +
				     rtrim(object_name(id,dbid)), 
			id,
			class, context=v2.name
		from	master..syslocks l,
			master..spt_values v1,
			master..spt_values v2
		where	l.type = v1.number
			and v1.type = "L"
			and (l.context+2049) = v2.number
			and v2.type = "L2"
			and spid in (@spid1, @spid2)
		order by fid, spid, loid, objectName, page, row, locktype
end

/*
**  No parameters, so show all the locks.
*/
else if (@verbose is not NULL)
begin
		
		select fid, spid, loid, locktype = v1.name,
			page, row,
			objectName = rtrim(db_name(dbid)) + '..' +
				     rtrim(object_name(id,dbid)), 
			id,
			class, context=v2.name
		from	master..syslocks l,
			master..spt_values v1,
			master..spt_values v2
		where	l.type = v1.number
			and v1.type = "L"
			and (l.context+2049) = v2.number
			and v2.type = "L2"
		order by fid, spid, loid, objectName, page,
			row, locktype
end

return (0)
go
exec sp_procxmode 'sp_lock', 'anymode'
go
grant execute on sp_lock to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_logdevice')
begin
	drop procedure sp_logdevice
end
go
print "Installing sp_logdevice"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	5.0	14.2	11/12/91	sproc/src/logdevice */

/*
** Messages for "sp_logdevice"          17710
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices."
** 17281, "The specified device is not used by the database."
** 17710, "This command has been ignored.  The device specified
**	   is the only non-log device available for the database and
**	   cannot be made log-only."
** 17711, "Syslogs moved."
** 17715, "The last-chance threshold for database %1! is now %2! pages."
** 17716, "Could not update the last-chance threshold for database %1!"
** 17289, "Set your curwrite to the hurdle of current database."
*/

create procedure sp_logdevice
@dbname	varchar(30),		/* database name that has the syslogs */
@devname	varchar(30)	/* device name to put syslogs on */

as

declare @dbid	smallint	/* dbid of the database to be changed */
declare @dbuid	int		/* id of the owner of the database */
declare @logbit	int		/* this is the bit to turn on in sysusages */
declare @lct	int		/* last-chance threshold value */
declare @msg    varchar(1024)
declare @bitdesc varchar(30)	/* bit description for the db */
declare @tempdb_mask   int	 /* All database status bit for a tempdb */
declare @isatempdb	int	/* Is this a temp. db ? */



/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_logdevice"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

select @logbit = 4		/* bit 3 is the one to turn on */

/*
**  Verify the database name and get the @dbid and @dbuid
*/
select @dbid = dbid, @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so and list the databases.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA authorization can execute it.
**  Call proc_role() with the required SA authorization.
*/
if ((suser_id() != @dbuid) and (proc_role("sa_role") < 1))
	return(1)

/*
** Determine if we are dealing with a temporary database.
*/
select @tempdb_mask = number
	from master.dbo.spt_values
	where type = "D3" and name = "TEMPDB STATUS MASK"

if (@dbid = 2) or exists (select * from master.dbo.sysdatabases
	     	            where dbid = @dbid
	     	            and (status3 & @tempdb_mask) != 0)
begin
	select @isatempdb = 1
end
else
begin
	select @isatempdb = 0
end

/* 
** Check single user bit (4096).
** Database must be in single user mode so that no log allocation
** or deallocation take place while recalculing the free space counter.
** However, this requirement is relaxed for temporary databases.
*/ 
if @isatempdb = 0
begin
	select @bitdesc = null 
	select @bitdesc = v.name
		from master.dbo.spt_values v, master.dbo.sysdatabases d 
			where d.dbid = @dbid
				and v.type = "D" 
				and d.status & v.number = 4096 

	if @bitdesc is null
	begin 
		/*
		** 17793, "System Administrator (SA) must set database '%1!' to single-user mode with sp_dboption before using '%2!'."
		*/
		raiserror 17793, @dbname, "sp_logdevice"
		return(1)  
	end  
end

/*
**  See if the device exists.
*/
if not exists (select *
		from master.dbo.sysdevices
			where name like @devname)
begin
	/*
	** 17471, "No such device exists -- run sp_helpdevice to list the DataServer devices."
	*/
	raiserror 17471



	return (1)
end

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if ((suser_id() != @dbuid) and (proc_role("sa_role") < 1))
	return(1)

/*
**  Now see if the @dbname uses the @devname
*/
if not exists (select *
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = @dbid)
begin
	/*
	** 17281, "The specified device is not used by the database."
	*/
	raiserror 17281
	return (1)
end

/*
**  Check if there are any additional segments on original device to be made
**  into log only (don't want to make the only segment not usable for data!)
*/
if (select count(*)
	from master.dbo.sysusages u, master.dbo.sysdevices d
		where d.name != @devname
			and u.vdevno = d.vdevno
			and u.dbid = @dbid
			and u.segmap != @logbit
			and d.cntrltype = 0) = 0
begin
	/*
	** 17710, "This command has been ignored.  The device specified
	** is the only non-log device available for the database and
	** cannot be made log-only."
	*/
	raiserror 17710
	return (1)
end

/*
**  Set the segments on @devname as log-only.
*/

/* Encapsulate sysusages/anchor change in a transaction */
begin transaction

update master.dbo.sysusages
	set segmap = @logbit
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where d.name = @devname
				and u.vdevno = d.vdevno
				and u.dbid = @dbid
/*
**  Clear the bit from any database segments on other devices that aren't
**  already log only.
*/
update master.dbo.sysusages
	set segmap = segmap & ~@logbit
		from master.dbo.sysusages u, master.dbo.sysdevices d
			where u.dbid = @dbid
			and u.vdevno = d.vdevno
			and d.name != @devname
			and u.segmap != @logbit

if @@rowcount = 0
begin
	rollback transaction
	return (1)
end

dbcc dbrepair(@dbname, "upd_usg")
if (@@error != 0)
begin
	rollback transaction
	return (1)
end

commit transaction

/*
**  Now we need to activate the new segment map.
*/
dbcc dbrepair (@dbname, remap)

/*
** We might be extending onto a segment that used to contain user data,
** so we need to look for stranded objects.
*/
dbcc dbrepair (@dbname, findstranded, NULL, @isatempdb)

/*
** Recalculate the last-chance threshold
*/
select @lct = lct_admin("lastchance", @dbid)

/*
** 17711, "Syslogs moved."
*/
exec sp_getmessage 17711, @msg output
print @msg

/*
** Show what the last-chance threshold changed to
*/
if (@lct > 0)
	exec sp_getmessage 17715, @msg output
else
	exec sp_getmessage 17716, @msg output
print @msg, @dbname, @lct

return (0)
go
exec sp_procxmode 'sp_logdevice', 'anymode'
go
grant execute on sp_logdevice to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_lookup')
begin
	drop procedure sp_lookup
end
go
print "Installing sp_lookup"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */

create procedure sp_lookup
@typearg int,
@owname	varchar(255) = "%", /* owner of the desired objects (except indexes) */
@obname	varchar(255) = "%", /* name of the desired objects (including indexes) */
@indtab	varchar(255) = "%", /* table associated with the desired index */
@indown varchar(255) = "%"  /* owner of the desired index */
as
	create table #ddtab
		(name	varchar(255),
		 owner	varchar(255),
		 type	int,
		 indtab	varchar(255))

declare @table	int
declare @view	int
declare @index	int
declare @sproc	int
declare @trgr	int
declare @dflt	int
declare @rule	int
declare @dtype	int
declare @db	int
declare @report int



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @table = 1, @view = 2, @index = 4, @sproc = 8, @trgr = 16, @dflt = 32,
	@rule = 64, @dtype = 128, @db = 256, @report = 512

if (@typearg & @table = @table)
	insert into #ddtab
		select name, user_name(uid), @table, '' from dbo.sysobjects
			where name like @obname
				and user_name(uid) like @owname
				and (sysstat & 7 = 1	/* system table */
		  		or sysstat & 7 = 3)	/* user table */


if (@typearg & @view = @view)
	insert into #ddtab
		select name, user_name(uid), @view, '' from dbo.sysobjects
			where name like @obname
				and user_name(uid) like @owname
			  	and sysstat & 7 = 2		/* view */

if (@typearg & @index = @index)
	insert into #ddtab
		select i.name, user_name(o.uid), @index, o.name
			from dbo.sysindexes i, dbo.sysobjects o
				where i.name like @obname
					and i.indid > 0
					and i.id = o.id
					and user_name(o.uid) like @indown
					and o.name = object_name(o.id)
					and o.name like @indtab

if (@typearg & @report = @report)
	insert into #ddtab
		select name, user_name(uid), @report, '' from dbo.sysobjects
			where name like @obname
				and user_name(uid) like @owname
				and sysstat & 7 = 4		/* sproc */
				and userstat & -32768 = -32768	/* report */

if (@typearg & @sproc = @sproc)
begin
	/*
	**  If we also wanted reports, don't pick up reports again as sprocs.
	*/
	if (@typearg & @report = @report)
	begin
		insert into #ddtab
			select name, user_name(uid), @sproc, '' from dbo.sysobjects
			 where name like @obname
				and user_name(uid) like @owname
				and sysstat & 7 = 4	/* stored procedure */
				and userstat & -32768 != -32768	/* report */
	end
	else
	begin
		insert into #ddtab
			select name, user_name(uid), @sproc, '' from dbo.sysobjects
			 where name like @obname
				and user_name(uid) like @owname
				and sysstat & 7 = 4	/* stored procedure */
	end
end

if (@typearg & @trgr = @trgr)
	insert into #ddtab
		select name, user_name(uid), @trgr, '' from dbo.sysobjects
			where name like @obname
				and user_name(uid) like @owname
			  	and sysstat & 7 = 0	/* trigger */

if (@typearg & @dflt = @dflt)
	insert into #ddtab
		select name, user_name(uid), @dflt, '' from dbo.sysobjects
			 where name like @obname
			 	and user_name(uid) like @owname
			 	and sysstat & 7 = 6		/* default */

if (@typearg & @rule = @rule)
	insert into #ddtab
		select name, user_name(uid), @rule, '' from dbo.sysobjects
			 where name like @obname
			 	and user_name(uid) like @owname
			 	and sysstat & 7 = 7		/* rule */

if (@typearg & @dtype = @dtype)
	insert into #ddtab
		select name, user_name(uid), @dtype, '' from dbo.systypes
			where name like @obname
				and user_name(uid) like @owname

if (@typearg & @db = @db)
	insert into #ddtab
		select name, suser_name(suid), @db, ''
			from master.dbo.sysdatabases
				where (name like @obname)
					and suser_name(suid) like @owname

exec sp_autoformat @fulltabname = #ddtab,
	@orderby = "order by name"

drop table #ddtab

return (0)
go
exec sp_procxmode 'sp_lookup', 'anymode'
go
grant execute on sp_lookup to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpremotelogin')
begin
	drop procedure sp_helpremotelogin
end
go
print "Installing sp_helpremotelogin"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
** Messages for "sp_helpremotelogin"    17680
**
** 17680, "There are no remote servers defined."
** 17681, "There are no remote logins for the remote server '%1!'."
** 17682, "There are no remotelogins defined."
** 17683, "There are no remote logins for '%1!'."
** 17684, "There are no remote logins."
** 17685, "There are no remote logins for '%1!' on remote server '%2!'."
** 17686, "** mapped locally **"
** 17687, "** use local name **"
** 17661, "-- none --"
*/
create procedure sp_helpremotelogin
@remoteserver varchar(255) = NULL,	/* remote server name */
@remotename varchar(255) = NULL		/* remote login name */
as

declare	@msg	varchar(1024)
declare @sptlang	int
declare @len1 int, @len2 int, @len3 int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

/*
**  If no server given, get 'em all.
*/
if @remoteserver is null
begin
	select @remoteserver = "%"
end

else
begin
	if not exists (select *
			from master.dbo.sysservers s,
				master.dbo.sysremotelogins r
			where s.srvid = r.remoteserverid
				and s.srvname like @remoteserver
				and s.srvid > 0)
	begin
		if @remoteserver = "%"
		begin
			/* 17680, "There are no remote servers defined." */
			exec sp_getmessage 17680, @msg out
			print @msg
			return (1)
		end

		/* 17681, "There are no remote logins for the remote server '%1!'." */
		exec sp_getmessage 17681, @msg out
		print @msg, @remoteserver
		return (1)
	end
end

/*
**  If no remotename given, get 'em all.
*/
if @remotename is null
begin
	select @remotename = "%"
end

else
begin
	if not exists (select *
			from master.dbo.sysremotelogins
			where isnull(remoteusername, "") like @remotename)
	begin
		if @remotename = "%"
		begin
			/* 17682, "There are no remotelogins defined." */
			exec sp_getmessage 17682, @msg out
			print @msg
			return (1)
		end

		/* 17683, "There are no remote logins for '%1!'." */
		exec sp_getmessage 17683, @msg out
		print @msg, @remotename
		return (1)
	end
end

/*
**  Check for empty results.
*/
if not exists (select *
		from master.dbo.sysremotelogins r, master.dbo.sysservers s
		where isnull(r.remoteusername, "") like @remotename
			and s.srvid = r.remoteserverid
				and s.srvname like @remoteserver)
begin
	if ((@remoteserver = '%') and (@remotename = '%'))
		/* 17684, "There are no remote logins." */
		exec sp_getmessage 17684, @msg out
	else 
		/* 17685, "There are no remote logins for '%1!' on remote server '%2!'." */
		exec sp_getmessage 17685, @msg out

	print @msg, @remotename, @remoteserver
	return (1)
end

/*
**  Select the information.
*/
declare @maplocal varchar(22)
declare @uselocal varchar(22)

/* 17686, "** mapped locally **" */
/* 17687, "** use local name **" */
exec sp_getmessage 17686, @maplocal out
exec sp_getmessage 17687, @uselocal out

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17070 and 17079
		and langid = @@langid)
	    select @sptlang = 0
end


if @sptlang = 0	/* us_english */
	begin
	    select server = s.srvname,
		remote_user_name = isnull(r.remoteusername, @maplocal),
		local_user_name = isnull(suser_name(r.suid), @uselocal),
		options = name
	    into #sprmtlogin1rs
	    	    from master.dbo.sysservers s, master.dbo.sysremotelogins r,
			master.dbo.spt_values v
	            where s.srvid = r.remoteserverid
			and s.srvname like @remoteserver
			and s.srvid > 0
			and isnull(r.remoteusername, "") like @remotename
			and v.type = "F"
			and v.number = r.status
	    exec sp_autoformat @fulltabname = #sprmtlogin1rs,
		@orderby = "order by server, remote_user_name"
	    drop table #sprmtlogin1rs
	end
else /* non us_english */
	begin
	    select server = s.srvname,
		remote_user_name = isnull(r.remoteusername, @maplocal),
		local_user_name = isnull(suser_name(r.suid), @uselocal),
		options = m.description
	    into #sprmtlogin2rs
		from master.dbo.sysservers s, master.dbo.sysremotelogins r,
			master.dbo.spt_values v, master.dbo.sysmessages m
		where s.srvid = r.remoteserverid
			and s.srvname like @remoteserver
			and s.srvid > 0
			and isnull(r.remoteusername, "") like @remotename
			and v.type = "F"
			and v.number = r.status
			and v.msgnum = m.error
			and m.langid = @sptlang
	    exec sp_autoformat @fulltabname = #sprmtlogin2rs,
	  	@orderby = "order by server, remote_user_name"
	    drop table #sprmtlogin2rs
	end
return (0)
go
exec sp_procxmode 'sp_helpremotelogin', 'anymode'
go
grant execute on sp_helpremotelogin to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpsegment')
begin
	drop procedure sp_helpsegment
end
go
print "Installing sp_helpsegment"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
** Messages for "sp_helpsegment"        17nnn
**
** 17520, "There is no such segment as '%1!'."
** 19341, "Objects currently bond to segment '%1!':"
** 19342, "Objects on segment '%1!':"
*/
create procedure sp_helpsegment
@segname varchar(255) = NULL		/* segment name */
as

declare @segbit         int,    /* this is the bit version of the segment # */
	@segment        int,    /* the segment number of the segment */
	@free_pages     int,    /* unused pages in segment */
	@factor         float,  /* conversion factor to convert to MB */
	@clr_pages	int,	/* Space reserved for CLRs */
	@total_pages	int,	/* total allocatable log space */
	@used_pages	int,	/* allocated log space */
	@ismixedlog	int,	/* mixed log & data database ? */  
	@msg		varchar(1024)	/* message text */


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

/*
**  If no segment name given, get 'em all.
*/
if @segname is null
begin
	exec sp_autoformat @fulltabname = "syssegments",
		@orderby = "order by segment" 
	return (0)
end

/*
**  Make sure the segment exists
*/
if not exists (select *
	from syssegments
		where name = @segname)
begin
	/* 17520, "There is no such segment as '%1!'." */
	raiserror 17520, @segname
	return (1)
end

/*
**  Show the syssegment entry, then the fragments and size it is on,
**  then any dependent objects in the database.
*/
select *
into #sphelpsegment2rs
	from syssegments
		where name = @segname
exec sp_autoformat @fulltabname = #sphelpsegment2rs
drop table #sphelpsegment2rs
/*
**  Set the bit position for the segment.
*/
select @segment = segment
	from syssegments
		where name = @segname

/*
**  Now set the segments on @devname sysusages.
*/
if (@segment < 31)
	select @segbit = power(2, @segment)
else
	/*
	**  Since this is segment 31, power(2, 31) will overflow
	**  since segmap is an int.  We'll grab the machine-dependent
	**  bit mask from spt_values to set the right bit.
	*/
	select @segbit = low
		from master.dbo.spt_values
			where type = "E"
				and number = 2

/*
** Get factor for conversion of pages to megabytes from spt_values
*/
select @factor = convert(float, low) / 1048576.0
        from master.dbo.spt_values
        where number = 1 and type = "E"

select @total_pages = sum(u.size)
	from master.dbo.sysusages u
	where u.segmap & @segbit = @segbit
	and u.dbid = db_id()

select @ismixedlog = status2 & 32768
	from master.dbo.sysdatabases where dbid = db_id()

/*
** Select the sizes of the segments
*/
if (@segbit = 4)
begin
    select device = d.name,
	size = convert(varchar(20), round((sum(u.size) * @factor), 0)) + "MB"
    into #sphelpsegment3rs
	from master.dbo.sysusages u, master.dbo.sysdevices d
	    where u.segmap & @segbit = @segbit
		and u.dbid = db_id()
		and ((d.status & 2 = 2)  or (d.status2 & 8 = 8))
		and u.vdevno = d.vdevno
	    group by d.name
    exec sp_autoformat @fulltabname = #sphelpsegment3rs,
		@orderby = "order by 1"
    drop table #sphelpsegment3rs

    select @clr_pages = lct_admin("reserved_for_rollbacks", db_id())
    select @free_pages = lct_admin("logsegment_freepages", db_id())
			- @clr_pages

    select free_pages = @free_pages

    if(@ismixedlog = 32768)
    begin
	/* 
	** For a mixed log and data database, we cannot
	** deduce the log used space from the total space
	** as it is mixed with data. So we take the expensive
	** way by scanning syslogs.
	*/
	select @used_pages = lct_admin("num_logpages", db_id())

	/* Account allocation pages as used pages */
	select @used_pages = @used_pages + (@total_pages / 256)
    end
    else
    begin
	/* Dedicated log database */
	select @used_pages = @total_pages - @free_pages 
			   - @clr_pages
    end
end
else
begin
    select device = d.name,
	size = convert(varchar(20), round((sum(u.size) * @factor), 0)) + "MB",
	free_pages = sum(curunreservedpgs(db_id(), u.lstart, u.unreservedpgs))
    into #sphelpsegment4rs
	from master.dbo.sysusages u, master.dbo.sysdevices d
            where u.segmap & @segbit = @segbit
		and u.dbid = db_id()
		and ((d.status & 2 = 2)  or (d.status2 & 8 = 8))
		and u.vdevno = d.vdevno
	    group by d.name
    exec sp_autoformat @fulltabname = #sphelpsegment4rs,
		@orderby = "order by 1"
    drop table #sphelpsegment4rs
    select @free_pages = sum(curunreservedpgs(db_id(), u.lstart, u.unreservedpgs))
	from master.dbo.sysusages u
	    where u.segmap & @segbit = @segbit
		and u.dbid = db_id()

    select @used_pages = @total_pages - @free_pages
    select @clr_pages = 0
end

/*
** Select the dependent objects
** The segment information for a table is stored at both
** sysindexes and syspartitions. The segment in syspartitions
** tells where the future location of data in this partition.
** The segment in sysindexes is the default segment specified
** for the whole table/index. Any partitions under this table/
** index that doesn't have the segment specification for its
** own will use this default segment in sysindexes.
*/
if exists (select *
	   from syspartitions p, syssegments s
	   where s.name = @segname
	     and s.segment = p.segment)
begin
	print " "
	/* 19342, "Objects on segment '%1!':" */
	exec sp_getmessage 19342, @msg output
	print @msg, @segname
	print " "
	select table_name = object_name(p.id), index_name = i.name, i.indid,
	       partition_name = p.name
	into #result1
	from sysindexes i, syssegments s, syspartitions p
	where s.name = @segname
	  and s.segment = p.segment
	  and p.id = i.id
	  and p.indid = i.indid
	exec sp_autoformat @fulltabname='#result1', @orderby='order by 1,3,4'
end


if exists (select *
	   from syssegments s, sysindexes i
	   where s.name = @segname
	     and s.segment = i.segment)
begin
	print " "
	/* 19341, "Objects currently bond to segment '%1!':" */
	exec sp_getmessage 19341, @msg output
	print @msg, @segname
	print " "
	select table_name = object_name(i.id), index_name = i.name, i.indid
	into #result2
	from sysindexes i, syssegments s
	where s.name = @segname
	  and s.segment = i.segment
	exec sp_autoformat @fulltabname='#result2', @orderby='order by 1,3'
	print " "
end

/*
** Print total_size, total_pages, free_pages, used_pages and reserved_pages
*/

select total_size = convert(varchar(15), 
	round(@total_pages * @factor, 0)) + "MB",
	total_pages = convert(char(15), @total_pages),
	free_pages = convert(char(15), @free_pages),
	used_pages = convert(char(15), @used_pages),
	reserved_pages = convert(char(15), @clr_pages)
		
return (0)
go
exec sp_procxmode 'sp_helpsegment', 'anymode'
go
grant execute on sp_helpsegment to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpsort')
begin
	drop procedure sp_helpsort
end
go
print "Installing sp_helpsort"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
** Messages for "sp_helpsort"           17690
**
** 17690, "Character Set = "
** 17691, "Sort Order = "
** 17692, "Sort Order Description"
** 17693, "Characters, in Order"
** 17694, "Class 2 Character Set"
*/
create procedure sp_helpsort
AS
set nocount on

declare @sortid tinyint, @charid tinyint, @status tinyint
declare @csclass int
declare @image binary(1)
declare @count int, @end_flag int
    

declare @string varchar(66)
declare @msg varchar(1024)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

create table #helpsort3 (string varchar(66))

/*
** Get the sortorder ID, character set ID, and status
** For SMP or SDC, one row is expected.
*/
select @sortid = value from master..syscurconfigs where config = 123 


select @charid = value from master..syscurconfigs where config = 131 


select @image = convert(binary(1), definition)
    	from master.dbo.syscharsets where id = @sortid and csid = @charid

/*
** Get the name and description of the character set and sort order
*/


if (@sortid is NULL)
 BEGIN
    select @sortid = 0, @charid = 0, @status = 0, @csclass = 0
	/* 17690, "Character Set = " */
    exec sp_getmessage 17690, @msg out
    insert #helpsort3 values (@msg + " 0, ascii_8")
    insert #helpsort3 values ("    8-bit ASCII Character Set - System Default")
	/* 17691, "Sort Order = " */
    exec sp_getmessage 17691, @msg out
    insert #helpsort3 values (@msg + " 0, bin_ascii_8")
    insert #helpsort3 values ("    Binary Ordering - System Default")
 END
else
 BEGIN
    select @status = convert(tinyint, @image)

	/* 17690, "Character Set = " */
	/* When "type" > 2000, the row represents a Unilib sort order. */
	/* Need to check both "id" and "type" fields when mapping a charid. */
    exec sp_getmessage 17690, @msg out
    select @string = @msg + " " + convert(varchar(4), id) + ", " + name,
	   @csclass = type
	    from master.dbo.syscharsets 
	    where id = @charid and type <= 2000

    insert into #helpsort3 values (@string)

    select @count = 1
    select @end_flag = 1

    while (@end_flag != 0)
    begin
	    select @string = substring(description, @count, 62)
		    from master.dbo.syscharsets 
		    where id = @charid and type <= 2000
	    select @end_flag = isnull(ascii(@string), 0)

	    if (@end_flag != 0)
	    begin
		    select @string = "    " + @string
		    insert #helpsort3 values (@string)
	    end
	    select @count = @count + 62
    end

    /* Check if class 2 character set.  If so, tell 'em. */
    if (@csclass = 1002)
    begin
	/* 17694, "Class 2 Character Set" */
	exec sp_getmessage 17694, @msg out
    	insert #helpsort3 values ("    " + @msg)
    end

	/* 17691, "Sort Order = " */
    exec sp_getmessage 17691, @msg out
    select @string = @msg + " " + convert(varchar(4), id) + ", " + name
	    from master.dbo.syscharsets 
	    where id = @sortid and csid = @charid

    insert into #helpsort3 values (@string)

    select @count = 1
    select @end_flag = 1

    while (@end_flag != 0)
    begin
	    select @string = substring(description, @count, 62)
		    from master.dbo.syscharsets 
		    where id = @sortid and csid = @charid
	    select @end_flag = isnull(ascii(@string), 0)

	    if (@end_flag != 0)
	    begin
		    select @string = "    " + @string
		    insert #helpsort3 values (@string)
	    end

	    select @count = @count + 62
    end
END

/*
** Insert the list of built-in and external Unilib 
** sort orders into syscharsets. This is a special
** feature of the sortkey built-in function.
*/
select @image = sortkey(null, "all")

/* List of sort order names, ids and table names */
print ""

select
	"Collation Name" = name,
	"Collation ID" = id
from 
	master.dbo.syscharsets
where 
	type = 2003
print ""
select
	"Loadable Sort Table Name" = name,
	"Collation ID" = id
from
	master.dbo.syscharsets
where
	type = 2004

print ""

/* 17692, "Sort Order Description" */
exec sp_getmessage 17692, @msg out
print @msg
select "" = string from #helpsort3

/*
** If we have a class 2 character set, then we are unable 
** to output the multi-byte characters in their proper
** sort sequence from here... we're done.
*/
if (@csclass = 1002)
begin
	return (0)
end

/*
** Build the sorted list of printable characters for this sort order.
** If it's not stored in spt_values yet, then put the results in there.
*/
if not exists
(select * from master.dbo.spt_values where type = 'Z' and low = @charid and high = @sortid)
BEGIN
    
    create table #helpsort1 (char_val char(1))



    if @charid = 0       /* ascii_8 has printable chars from 32-126 */
        begin
                select @count = 32
                while @count <= 126
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end

        end

 /* iso_1 and iso15 have printable chars from 32-126 and 160-255 */
    if (@charid = 1 or @charid = 14) 
        begin
                select @count = 32
                while @count <= 126
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end

                select @count = 160
                while @count <= 255
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end
        end

    /* cp850 and cp858 have printable chars from 32-255 */
    if (@charid = 2 or @charid = 197) 
        begin

                select @count = 32
                while @count <= 255
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end
        end

    if @charid = 3      /* cp437 has printable chars from 32-255 */
        begin
                select @count = 32
                while @count <= 255
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end
        end

    /* roman8 and roman9 have printable chars from 32-126 and 161-254 */
    if (@charid = 4 or @charid = 218)
        begin
                select @count = 32
                while @count <= 126
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end

                select @count = 161
                while @count <= 254
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end
        end

     /* mac and mac_euro have printable chars from 32-126 and 128-216 */
    if (@charid = 5 or @charid = 198) 
        begin
                select @count = 32
                while @count <= 126
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end

                select @count = 128
                while @count <= 216
                begin
                        insert #helpsort1 (char_val)
                                values (char(@count))
                        select @count = @count + 1
                end
        end

    /* cp1252 has undefined chars at 127, 129, 141, 143, 144, 157 */
    if @charid = 13
	begin
		select @count = 32
		while @count <= 255
		begin
			if @count not in (127, 129, 141, 143, 144, 157)
			begin
				insert #helpsort1 (char_val)
					values (char(@count))
			end
			select @count = @count + 1
		end
	end

     /* For character sets that are not in the above list */
     if @charid not in (0, 1, 2, 3, 4, 5, 13, 14, 197, 198, 218) 
        begin
                return (0)
        end

    
    select (char_val) into #helpsort2
    	from #helpsort1
        order by char_val
    
    declare @char char(1)
    declare @char_str varchar(20)
    declare @incr int
    declare @seq_num int
    declare @rel char(1)
    declare @old_char char(1)
    
    select @char = char(0), @seq_num = 0, @count = 0, @incr = 8, @end_flag = 1
    select @rel = " ", @old_char = NULL
    
    set rowcount 1
   
    while @end_flag != 0
    begin
    
        select @char_str = ""
    
	/* If PST_NOTUNIQ is set, then possibly caseless */
	if (@status & 8 = 8)
            while (@count < @incr  and  @end_flag != 0)
            begin
                select @char = char_val
    	            from #helpsort2
                    where char_val >= @char
                select @end_flag = @@rowcount

		if (@end_flag != 0)
		begin
		    if (@char = @old_char)
			select @rel = "="
		    else
			select @rel = " "

		    select @old_char = @char
		    select @char_str = @char_str + @rel + @char
                    delete from #helpsort2 where ascii(@char) = ascii(char_val)
    
		    select @count = @count + 1
		end
            end
	else
            while (@count < @incr  and  @end_flag != 0)
            begin
                select @char = char_val
    	            from #helpsort2
                    where char_val > @char
                select @end_flag = @@rowcount

		if (@end_flag != 0)
		begin
		    select @char_str = @char_str + @rel + @char
                    delete from #helpsort2 where ascii(@char) = ascii(char_val)

		    select @count = @count + 1
		end
            end

        select @incr = @incr + 8, @seq_num = @seq_num + 1
        insert master.dbo.spt_values (name, number, type, low, high) 
		values (@char_str, @seq_num, 'Z', @charid, @sortid)
    end
    
    set rowcount 0
    
END

/*
** Display the sorted list of characters.
*/
select @count = 1
select @end_flag = 1
select @incr = 5

truncate table #helpsort3

while @end_flag != 0
BEGIN
	select @string = ""

	while @count < @incr
	begin
		select @string = @string + substring(name, 2, 19) 
			from master.dbo.spt_values
			where type = 'Z' and number = @count and low = @charid
				and high = @sortid
		select @end_flag = @@rowcount
		select @count = @count + 1
	end

	select @incr = @incr + 4

	insert into #helpsort3 values (@string)
END

/* 17693, "Characters, in Order" */
if @charid in (0, 1, 2, 3, 4, 5, 13, 14, 197, 198, 218) 
begin
	exec sp_getmessage 17693, @msg out
	print @msg
	select "" = string from #helpsort3

end

set nocount off

return(0)
go
exec sp_procxmode 'sp_helpsort', 'anymode'
go
grant execute on sp_helpsort to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpserver')
begin
	drop procedure sp_helpserver
end
go
print "Installing sp_helpserver"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/fixindex */
/*
** Messages for "sp_helpserver"
**
** 17270, "There is not a server named '%1!'."
** 17680, "There are no remote servers defined."
** 19958, "Backup Server policy is set to '%1!'."
*/
create procedure sp_helpserver
@server varchar(255) = NULL		/* server name */
as

declare @msg	varchar(1024)
declare @len1 int, @len2 int
declare @bs_policy      varchar(255)

begin

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

/*
**  If no server name given, get 'em all.
*/
if @server is null
begin
	select @server = "%"
end

if @server = "SYB_BACKUP"
begin
	select @bs_policy = srvnetname from master..sysservers where srvname = "SYB_BACKUP"

	if ((lower(@bs_policy) = "$dedicated") or (lower(@bs_policy) = "$roundrobin"))
	begin
		select @server = "%_BS"

		/* 19958, "Backup Server policy is set to '%1!'." */
		exec sp_getmessage 19958, @msg output
		print @msg, @bs_policy
	end
end

/*
**  Does the server exist?
*/
if not exists (select *
		from master.dbo.sysservers 
			where srvname like @server
				or srvnetname like @server)
begin
	if @server = "%"
	begin
		/* 17680, "There are no remote servers defined." */
		exec sp_getmessage 17680, @msg output
		print @msg
	end
	else 
		/* 17270, "There is not a server named '%1!'." */
		raiserror 17270, @server
	return (1)
end
	
/*
**  Display server information.
**  First put it into a temp table so we can examine the status 
**  bits and turn them into english.
*/
create table #spt_server
(
	name	varchar(255),
	network	varchar(32),
	secmech varchar(255) NULL,
	class	varchar(15) NULL,
	status	varchar(255),
	id	smallint,
	cost	smallint NULL
)

/*
**  Initialize #spt_server from sysservers.
*/
insert into #spt_server
        select s.srvname, s.srvnetname, s.srvsecmech, v.name, "",
                id = s.srvid, s.srvcost
	from master.dbo.sysservers s, master.dbo.spt_values v
		where (s.srvname like @server
			or s.srvnetname like @server)
			and s.srvclass *= v.number 
			and v.type = 'X' and v.name != 'access_server'

/* 
**  Now for each nonlocal server in #spt_server, build the server
**  status description.  Logic patterned after helpdb.
*/

declare @cursrvid smallint	/* the current server we're working on. */
declare @srvdesc varchar(255)	/* the server description string. */
declare @bitdesc varchar(30)    /* the bit description for the server */

/*
**  Set @cursrvid to the first server id.
*/
select @cursrvid = min(id)
	from #spt_server
	where id != 0

/*
**  Parse the status.
*/
while @cursrvid is not NULL
begin
	/*
	**  Initialize @srvdesc.
	*/
	select @srvdesc = ""

	/* 
	**  Check timeout bit.  Note special kludgy handling
	**  due to previous definition of timeout and no timeout
	**  in spt_values.
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
			where v.type = "A"
				and v.number = 0

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
			where s.srvid = @cursrvid
				and s.srvstatus & v.number = 1)
	begin
		select @srvdesc = "no " + @bitdesc
	end
	else
	begin
		select @srvdesc = @bitdesc
	end

	/* 
	**  Check network password encryption status.
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
			where v.type = "A"
				and v.number = 2

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
			where s.srvid = @cursrvid
				and s.srvstatus & v.number = 2)
	begin
		if @srvdesc != ""
			select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end
	else
	begin
		if @srvdesc != ""
			select @srvdesc = @srvdesc + ", no " + @bitdesc
		else
			select @srvdesc = "no " + @bitdesc
	end

	/*
	** if OMNI is configured, handle the readonly status
	*/
	if exists (select * from master.dbo.sysconfigures cf,
		master.dbo.syscurconfigs cc
			where cf.config = cc.config 
				and cc.value = 1
				and cf.name = 'enable cis')
	begin
		select @bitdesc = null
		select @bitdesc = v.name
			from master.dbo.spt_values v
				where v.type = "A"
					and v.number = 4
		if exists (select * 
			from master.dbo.spt_values v, master.dbo.sysservers s
				where s.srvid = @cursrvid
					and s.srvstatus & v.number = 4)
		begin
			if @srvdesc != ""
				select @srvdesc = @srvdesc + ", " + @bitdesc
			else
				select @srvdesc = @bitdesc
		end
		else
		begin
			if @srvdesc != ""
				select @srvdesc = @srvdesc + ", writable "
			else
				select @srvdesc = "writable "
		end
	end

	/* 
	**  Check "rpc security model A".
	**  RPC security model A, B, and C are mutually exclusive.
	**  Default is model A.
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
		where v.type = "A"
		and v.number = 8

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid
		and s.srvstatus & v.number = 8)
	begin
		if @srvdesc != ""
			select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

	/*
	** Check "rpc security model B".
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
		where v.type = "A"
		and v.number = 16

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid
		and s.srvstatus & v.number = 16)
	begin
		if @srvdesc != ""
			select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
		/*
		** Further check security options for model B. namely, 
		** "use confidentiality", "use message integrity", or
		** "mutual authentication". Notice that these three options 
		** can co-exist for a given remote server.
		*/
	        select @bitdesc = null
		select @bitdesc = v.name
			from master.dbo.spt_values v
			where v.type = "A"
			and v.number = 64

		if exists (select * 
			from master.dbo.spt_values v, master.dbo.sysservers s
			where s.srvid = @cursrvid
			and s.srvstatus & v.number = 64)

		begin
			/*
			** We are sure that @srvdesc is not empty at this point.
			*/
			select @srvdesc = @srvdesc + ", " + @bitdesc
		end

	        select @bitdesc = null
		select @bitdesc = v.name
			from master.dbo.spt_values v
			where v.type = "A"
			and v.number = 128

		if exists (select * 
			from master.dbo.spt_values v, master.dbo.sysservers s
			where s.srvid = @cursrvid
			and s.srvstatus & v.number = 128)

		begin
			/*
			** We are sure that @srvdesc is not empty at this point.
			*/
			select @srvdesc = @srvdesc + ", " + @bitdesc
		end

	        select @bitdesc = null
		select @bitdesc = v.name
			from master.dbo.spt_values v
			where v.type = "A"
			and v.number = 256

		if exists (select * 
			from master.dbo.spt_values v, master.dbo.sysservers s
			where s.srvid = @cursrvid
			and s.srvstatus & v.number = 256)

		begin
			/*
			** We are sure that @srvdesc is not empty at this point.
			*/
			select @srvdesc = @srvdesc + ", " + @bitdesc
		end
	end

	/*
	** Check "rpc security model C".
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
		where v.type = "A"
		and v.number = 32

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid
		and s.srvstatus & v.number = 32)
	begin
		if @srvdesc != ""
			select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

	/*
	** Check for 'server logins'
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
		where v.type = "A"
		and v.number = 512

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid
		and s.srvstatus & v.number = 512)
	begin
		if @srvdesc != ""
			select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

	/*
	** Check for 'external engine auto start', this option is for the
	** EJB Class of servers only hence when reporting the various servers
	** for the ejb server only this option should be shown in the status
	*/
	select @bitdesc = null
	select @bitdesc = v.name
		from master.dbo.spt_values v
		where v.type = "A"
		and v.number = 1024

	if exists (select * 
		from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid
		and s.srvstatus & v.number = 1024)
	begin
			select @srvdesc = @bitdesc
	end
	else
	begin
		if exists (select * from master.dbo.sysservers s
				where s.srvid = @cursrvid and s.srvclass = 10)
		begin
			select @srvdesc = ""
		end
	end

	/* 
	** Check for 'negotiated logins'
	*/
	select @bitdesc = null
	select @bitdesc = v.name from master.dbo.spt_values v
		where v.type = 'A' and v.number = 4096
	if exists (select * from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid and s.srvstatus & v.number = 4096)
	begin
		if @srvdesc != ""
                        select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

       	/* 
	** Check for 'relocated joins'
	*/
	select @bitdesc = null
	select @bitdesc = v.name from master.dbo.spt_values v
		where v.type = 'A2' and v.number = 1 
	if exists (select * from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid and s.srvstatus2 & v.number = 1)
	begin
		if @srvdesc != ""
                        select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

       	/* 
	** Check for 'incompatible sort order'
	*/
	select @bitdesc = null
	select @bitdesc = v.name from master.dbo.spt_values v
		where v.type = 'A2' and v.number = 8 
	if exists (select * from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid and s.srvstatus2 & v.number = 8)
	begin
		if @srvdesc != ""
                        select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

	/*
	** Check for 'enable login redirection'
	*/
	select @bitdesc = null
	select @bitdesc = v.name from master.dbo.spt_values v
		where v.type = 'A2' and v.number = 2
	if exists (select * from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid and s.srvstatus2 & v.number = 2)
	begin
		if @srvdesc != ""
                        select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end
	/*
	** Check for 'cluster instance'
	*/
	select @bitdesc = null
	select @bitdesc = v.name from master.dbo.spt_values v
		where v.type = 'A2' and v.number = 4
	if exists (select * from master.dbo.spt_values v, master.dbo.sysservers s
		where s.srvid = @cursrvid and s.srvstatus2 & v.number = 4)
	begin
		if @srvdesc != ""
                        select @srvdesc = @srvdesc + ", " + @bitdesc
		else
			select @srvdesc = @bitdesc
	end

	/*
	**  Save the description.
	*/
	update #spt_server
		set status = @srvdesc
			from #spt_server
				where id = @cursrvid

	/*
	**  Now get the next, if any, server id.
	*/
	select @cursrvid = min(id)
		from #spt_server
			where id > @cursrvid
end

/*
**  Display the information we got.
*/
if exists (select * from master.dbo.sysconfigures cf,
	master.dbo.syscurconfigs cc
		where cf.config = cc.config 
			and cc.value = 1
			and cf.name = 'enable cis')
begin
	/*
	** OMNI is configured, display the server class and cost as well
	*/
	
	exec sp_autoformat @fulltabname = #spt_server,
	    @selectlist = " name, 'network_name' = network, class, status,id, cost", 
	    @orderby = "order by name"
end
else
begin

	exec sp_autoformat @fulltabname = #spt_server,
	    @selectlist = " name, 'network_name' = network, 'security_mechanism' = secmech, status,id",
	    @orderby = "order by name"
end

return (0)
end
go
exec sp_procxmode 'sp_helpserver', 'anymode'
go
grant execute on sp_helpserver to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_hidetext')
begin
	drop procedure sp_hidetext
end
go
print "Installing sp_hidetext"
go

/* Can be Executed in any database */

/*
** Syntax:
**
** execute sp_hidetext with no parameter hides text for every compiled
** object in the current database. This only reserves to user with SA role.
**
** User John can hide the text of his complied object john_proc using the 
** following two ways:
**
**	 execute sp_hidetext @objname = "john_proc", @username = "John"
** or 
**	 execute sp_hidetext @objname = "john_proc"
**
** User John can hide the text of all the check constraints and 
** declaractive defaults defined on his table john_tab using the following
** two ways:
**
**	 execute sp_hidetext @tabname = "john_tab", @username = "John"
** or 
**	 execute sp_hidetext @tabname = "john_tab"
**
** User John can hide the text of all the check constraints and declaractive
** defaults defined on this table john_tab2 and also his view john_vu as
** following:
**
**	execute sp_hidetext @objname = "john_vu", @tabname = "john_tab2" 
**
** or
**
**	execute sp_hidetext @objname = "john_vu", @tabname = "john_tab2" ,
**		@username = "John"
**
** User John can hide the text of all the compiled objects owned by him
** using the following way:
**
**	execute sp_hidetext @username = "John"
**
** User John can not hide the text of Mary's view mary_vu as following:
**
**	execute sp_hidetext @objname = "mary_vu". @username = "Mary"
**
** But the user with SA role can do the above.
**
** Parameters:
**	objname - Compiled object name
**	tabname - table name
**	username - user name
**
** Returns:
**	1 - if error.
**	0 - if no error.
*/
create procedure sp_hidetext
@objname varchar(255) = NULL,
@tabname varchar(255) = NULL,
@username varchar(255) = NULL
as
declare @ret int
execute @ret = sp_aux_text @objname, @tabname, @username, 2
return @ret
go
exec sp_procxmode 'sp_hidetext', 'anymode'
go
grant execute on sp_hidetext to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_markreport')
begin
	drop procedure sp_markreport
end
go
print "Installing sp_markreport"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */

/*
** Messages for "sp_markreport"         17712
**
** 17712, "Report must be in your current database."
** 17713, "No such report exists."
*/

create procedure sp_markreport
@reportname varchar(767)		/* proc name we want to mark as report */
as

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Make sure the @reportname is local to the current database.
*/
if @reportname like "%.%.%" and
	substring(@reportname, 1, charindex(".", @reportname) - 1) != db_name()
begin
	/*
	** 17712, "Report must be in your current database."
	*/
	raiserror 17712
	return (1)
end

/*
**  Make sure that it actually exists as a sproc.
*/
if not exists (select *
		from sysobjects
			where id = object_id(@reportname)
			and sysstat & 7 = 4	/* stored procedure */
			and uid = user_id())
begin
	/*
	** 17713, "No such report exists."
	*/
	raiserror 17713
	return (1)
end

update sysobjects
	set userstat = userstat | -32768	/* high bit means report */
		from sysobjects
			where id = object_id(@reportname)
			and sysstat & 7 = 4		/* stored procedure */
			and uid = user_id()

return (0)
go
exec sp_procxmode 'sp_markreport', 'anymode'
go
grant execute on sp_markreport to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dbxt_recreate_proc')
begin
	drop procedure sp_dbxt_recreate_proc
end
go
print "Installing sp_dbxt_recreate_proc"
go


/* AutoDBExtend */
/*
** Generated by spgenmsgs.pl on Sun Aug 10 03:54:03 2003 
*/
/*
** raiserror Messages for dbxt_common [Total 1]
**
** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
*/
/*
** sp_getmessage Messages for dbxt_common [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
** This is the first file of dbxt* sprocs that gets loaded in installdbextend
** script. Stick in here the initial setup stuff that needs to happen in 
** this script.
*/
print "Installing procedures from dbxt_common ..."
go

use sybsystemprocs
go

if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go

-- ===========================================================================
-- Create the procedure to drop other sprocs first. This will also report
-- the message that the proc is being dropped and recreated.
--
if exists (select 1 from sysobjects
	   where name = "sp_dbxt_recreate_proc"
	     and type = 'P'
	     and sysstat & 7 = 4
	   )
	drop procedure sp_dbxt_recreate_proc
go

/*
{
*/
create procedure sp_dbxt_recreate_proc (@procname varchar(256)) as
begin
	if exists (select 1 from sysobjects
		    where id = object_id(@procname)
		      and type = 'P'
		      and sysstat & 7 = 4
	)
	begin
		print "Re-installing %1!", @procname
		exec ("drop procedure " + @procname)
	end
	else
	begin
		print "Installing %1!", @procname
	end
end
go
go
exec sp_procxmode 'sp_dbxt_recreate_proc', 'anymode'
go
grant execute on sp_dbxt_recreate_proc to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_check_permission')
begin
	drop procedure sp_monitor_check_permission
end
go
print "Installing sp_monitor_check_permission"
go


/*
** sp_monitor_check_permission is a subordinate stored procedure of sp_monitor*
** family of stored procedures which provides proper permission checks.
*/
use sybsystemprocs
go

if (db_name() != "sybsystemprocs")
begin
        /*
        ** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
        */
        raiserror 19529, "sybsystemprocs"
        select syb_quit()
end
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_check_permission"
go

/*
** This stored procedure checks if the user has sa_role or mon_role
** It also calls proc_role() which generates appropriate audit records
**
** Parameters:
**      @procname       - Name of the caller
**
** Returns:
**      0 in case of success
**      1 in case of failure
*/
create procedure sp_monitor_check_permission @procname varchar(30)
as
declare @retstat int
declare @sa_role int             /* has sa role */
declare @mon_role int            /* has mon role */

select @sa_role = charindex("sa_role", show_role()),
                @mon_role = charindex ("mon_role", show_role())

if ((@sa_role = 0) and (@mon_role = 0))
begin
/*
** We succeed if both proc_role call returns success
** This is for the unlikely event when a user gains privilege just before
** calls to proc_role are made.
** This avoids, no error message but yet the permission failed scenario
*/
         select @retstat = proc_role("mon_role")
         if (@retstat > 0)
         begin
                return(0)
         end
         return(1)
end
else
begin
/* We fail if proc_role fails */
         if (@sa_role > 0)
         begin
                select @retstat = proc_role("sa_role")
                if (@retstat = 0)
                begin
                        return(1)
                end
         end
         if (@mon_role > 0)
         begin
                select @retstat = proc_role("mon_role")
                if (@retstat = 0)
                begin
                        return(1)
                end
         end
end
return(0)
go

go
exec sp_procxmode 'sp_monitor_check_permission', 'anymode'
go
grant execute on sp_monitor_check_permission to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_help')
begin
	drop procedure sp_monitor_help
end
go
print "Installing sp_monitor_help"
go

exec sp_dbxt_recreate_proc sp_monitor_help
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_help [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_help [Total 10]
**
** 19263, "Usage: sp_monitor"
** 19266, "Usage: sp_monitor [ event, [spid]]"
** 19267, "Examples: sp_monitor 'event', '5'"
** 19268, "Usage: sp_monitor [ procedure, [ dbname , [ procname, [, summary | detail]]]]"
** 19269, "Examples: sp_monitor 'procedure'"
** 19274, "Usage: sp_monitor [ statement, [ cpu | diskio | elapsed time]]"
** 19275, "Examples: sp_monitor 'statement', 'elapsed time'"
** 19280, "Examples: sp_monitor 'procedure', 'employee_db', 'sp_get_salary'"
** 19281, "Examples: sp_monitor 'procedure','detail'"
** 19282, "Examples: sp_monitor 'procedure', 'employee_db', 'sp_get_employee_id', 'detail'"
*/
/*
** End spgenmsgs.pl output.
*/
go

/*
** This stored procedure is a subordinate stored procedure that is invoked by
** the parent stored procedure sp_monitor when "help" is passed as the
** argument. This stored procedure provides help related information pertaining
** to all the parameters to sp_monitor.
** The procedure provides Usage and Example information for each of the options
** supported by sp_monitor. If "help" is sought without any additional parameter
** then all the options are listed with examples.
**
** User can invoke the 'help' facility in one of two ways:
**
**   sp_monitor 'help'
**
**	This will produce 1st level of help information for each type of
**	entity that can be monitored.
**
**   sp_monitor 'help', 'deadlock'	['deadlock' is only an example.]
**
**	This produces a bit more detailed help information for the entity
**	being monitored. Currently, only few commands have extensive
**	help information built-in, which is produced under this usage.
**
** Parameters:
**      @cmdtype 	- The specific command for which help is required.
**      @listall	- Indicate if help is required for all commands.
**			  0	: Brief info on each command
**			  1	: Verbose info on specific command
**			  2	: Verbose info on all commands
**
** Returns:
**      0       - upon sucessful completion
{
*/
create procedure sp_monitor_help(
			  @cmdtype varchar(30)	= NULL
			, @listall int
) as
begin
declare @sqlmsg varchar(255)	-- varchar so as to truncate trailing blanks
      , @monprocname	varchar(256)
      , @validcmd_names	varchar(256)

-- Reuse variable to build list of monitoring types allowed.
--
select @validcmd_names = "'enable' | 'disable' | 'connection' | 'procedure' | 'statement' | 'event' | 'deadlock' | 'procstack' | 'archive' | 'report'" 

exec sp_getmessage 19263, @sqlmsg output

-- Fix this when @msg_19263 is updated in a major release.
select @sqlmsg = "Usage: %1! %2!"

if (@listall != 0)
begin
	-- Show the possible optional arguments in help info.
	select @monprocname = "[ " + @validcmd_names + " [, ...] ] "
	print @sqlmsg, "sp_monitor", @monprocname
end

-- Show the syntax for the basic help command.
--
if (@cmdtype = "HELP" OR @listall != 0)
begin
	select @monprocname = "help " + "[, " + @validcmd_names + "]"
	print @sqlmsg, "sp_monitor", @monprocname
	print @sqlmsg, "sp_monitor", "help, 'all'"
end

if (@cmdtype = "CONNECTION" OR @listall != 0)
begin
	select @sqlmsg = case @listall when 1 then 'terse' else 'verbose' end
	     , @monprocname = "sybsystemprocs.dbo.sp_monitor_connection_usage"
	exec @monprocname @sqlmsg
end
if (@cmdtype = "EVENT" OR @listall != 0)
begin
	print " "
	exec sp_getmessage 19266, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19267, @sqlmsg output	
	print @sqlmsg
end

if (@cmdtype = "PROCEDURE" OR @listall != 0)
begin
	print " "
	exec sp_getmessage 19268, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19269, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19280, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19281, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19282, @sqlmsg output	
	print @sqlmsg
end

if (@cmdtype = "ENABLE" OR @listall != 0)
begin
	select @sqlmsg = case @listall when 1 then 'terse' else 'verbose' end
	     , @monprocname = "sybsystemprocs.dbo.sp_monitor_enable_usage"
	exec @monprocname @sqlmsg, @validcmd_names
end

if (@cmdtype = "DISABLE" OR @listall != 0)
begin
	select @sqlmsg = case @listall when 1 then 'terse' else 'verbose' end
	     , @monprocname = "sybsystemprocs.dbo.sp_monitor_disable_usage"
	exec @monprocname @sqlmsg, @validcmd_names
end

if (@cmdtype = "STATEMENT" OR @listall != 0)
begin
	print " "
	exec sp_getmessage 19274, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19275, @sqlmsg output	
	print @sqlmsg
end

select @sqlmsg = case @listall when 1 then 'terse' else 'verbose' end

if (@cmdtype = "DEADLOCK" OR @listall != 0)
begin
	select @monprocname = "sybsystemprocs.dbo.sp_monitor_deadlock"
	exec @monprocname 'help', @sqlmsg
end

if (@cmdtype = "PROCSTACK" OR @listall != 0)
begin
	select @monprocname = "sybsystemprocs.dbo.sp_monitor_procstack_usage"
	exec @monprocname @sqlmsg
end

if (@cmdtype = "ARCHIVE" OR @listall != 0)
begin
	select @monprocname = "sybsystemprocs.dbo.sp_monitor_archive_usage"
	exec @monprocname @sqlmsg
end

if (@cmdtype = "REPORT" OR @listall != 0)
begin
	select @monprocname = "sybsystemprocs.dbo.sp_monitor_report_usage"
	exec @monprocname @sqlmsg
end
return(0)
end	-- }
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_monitor_help', 'anymode'
go
grant execute on sp_monitor_help to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_server')
begin
	drop procedure sp_monitor_server
end
go
print "Installing sp_monitor_server"
go


/*
** Generated by spgenmsgs.pl on Tue Dec  2 17:55:42 2003
**
** raiserror Messages for monitor_server [Total 0]
**
** sp_getmessage Messages for monitor_server [Total 0]
**
** End spgenmsgs.pl output.
**
*/

/*
** This stored procedure is a subordinate stored procedure that is invoked from the
** parent stored procedure sp_monitor when "server" is passed as the
** argument or when no argument is passed. 
** This stored procedure provides monitoring information pertaining
** to the server as a whole.
**
** Parameters:
**	None.
**
** Returns:
**      0       - upon sucessful completion
**      1       - If an error resulted.
*/

create procedure sp_monitor_server 
as

/*
**  Declare variables to be used to hold current monitor values.
*/
declare @now 		datetime
declare @cpu_busy 	int
declare @io_busy	int
declare @idle		int
declare @pack_received	int
declare @pack_sent	int
declare @pack_errors	int
declare @connections	int
declare @total_read	int
declare @total_write	int
declare @total_errors	int
declare @engonline	int
declare @interval	int
declare @mspertick	float	/* milliseconds per tick */
declare @rptline char(255)
declare @procval	int
declare @whoami		varchar(30)
declare @rtnstatus 	int
declare @monprocname	varchar(255)

select @whoami = object_name(@@procid, db_id('sybsystemprocs'))

select @monprocname = 'sybsystemprocs.dbo.sp_monitor_check_permission'

exec @rtnstatus = @monprocname @whoami

if (@rtnstatus = 1)
        return(1)

/*
**  Set @mspertick.  This is just used to make the numbers easier to handle
**  and avoid overflow.
*/

select @mspertick = (@@timeticks / 1000.0)
/*
**  Set engonline to number of engines currently on line (so busy/idle
**  figures are correct). If this changes under us, the figures will not
**  necessarily be accurate for the next sp_monitor call; this should not
**  be a tremendous problem.
*/

	select @engonline = count(*) from master.dbo.sysengines


/*
**  Get current monitor values.
*/
select
	@now = getdate(),
	@cpu_busy = @@cpu_busy,
	@io_busy = @@io_busy,
	@idle = @@idle,
	@pack_received = @@pack_received,
	@pack_sent = @@pack_sent,
	@connections = @@connections,
	@pack_errors = @@packet_errors,
	@total_read = @@total_read,
	@total_write = @@total_write,
	@total_errors = @@total_errors

/*
**  Check to see if DataServer has been rebooted.  If it has then the
**  value of @@boottime will be more than the value of spt_monitor.lastrun.
**  If it has update spt_monitor.
*/
update master.dbo.spt_monitor
	set
		lastrun = @now,
		cpu_busy = @cpu_busy,
		io_busy = @io_busy,
		idle = @idle,
		pack_received = @pack_received,
		pack_sent = @pack_sent,
		connections = @connections,
		pack_errors = @pack_errors,
		total_read = @total_read,
		total_write = @total_write,
		total_errors = @total_errors
	where datediff(ss,lastrun,@@boottime) > 0

/*
**  Now print out old and new monitor values.
*/
set nocount on
select @interval = datediff(ss, lastrun, @now)
	from master.dbo.spt_monitor
/* To prevent a divide by zero error when run for the first
** time after boot up
*/
if @interval = 0
        select @interval = 1
select last_run = lastrun, current_run = @now, seconds = @interval
	from master.dbo.spt_monitor
select
cpu_busy = convert(char(25),
	   	   convert(varchar(11),
			   convert(int,
				   (@cpu_busy * (@mspertick / 1000))))
		+ "("
		+  convert(varchar(11),
			   convert(int,
				   ((@cpu_busy - cpu_busy) * (@mspertick / 1000))
				  / @engonline))
		+ ")"
		+ "-"
		+  convert(varchar(11),
			   convert(int,
				   (((@cpu_busy - cpu_busy)
				     * (@mspertick / 1000))
				    / @engonline)) * 100
				   / @interval)
		+ "%"),

io_busy = convert(char(25),
		  convert(varchar(11),
			  convert(int,
				  (@io_busy * (@mspertick / 1000))
				  / @engonline))
		+ "("
		+ convert(varchar(11),
			  convert(int,
				  ((@io_busy - io_busy) * (@mspertick / 1000))
				  / @engonline))
		+ ")"
		+ "-"
		+ convert(varchar(11),
			  convert(int,
				  (((@io_busy - io_busy) * (@mspertick / 1000))
				    / @engonline))
				   * 100
				  / @interval)
		+ "%"),
idle =    convert(char(25),
	          convert(varchar(11),
		          convert(int,
			          (@idle * (@mspertick / 1000))
			          / @engonline))
		+ "("
		+ convert(varchar(11),
			  convert(int,
				  ((@idle - idle) * (@mspertick / 1000))
				  / @engonline))
		+ ")"
		+ "-"
		+ convert(varchar(11),
			  convert(int,
				  (((@idle - idle) * (@mspertick / 1000))
				    / @engonline))
				   * 100
				  / @interval)
		+ "%")

from master.dbo.spt_monitor

select
	packets_received = convert(char(25), convert(varchar(11), @pack_received) + "(" +
		convert(varchar(11), @pack_received - pack_received) + ")"),
	packets_sent = convert(char(25), convert(varchar(11), @pack_sent) + "(" +
		convert(varchar(11), @pack_sent - pack_sent) + ")"),
	packet_errors = convert(char(25), convert(varchar(11), @pack_errors) + "(" +
		convert(varchar(11), @pack_errors - pack_errors) + ")")
from master.dbo.spt_monitor

select
	total_read = convert(char(19), convert(varchar(11), @total_read) + "(" +
		convert(varchar(11), @total_read - total_read) + ")"),
	total_write = convert(char(19), convert(varchar(11), @total_write) + "(" +
		convert(varchar(11), @total_write - total_write) + ")"),
	total_errors = convert(char(19), convert(varchar(11), @total_errors) + "(" +
		convert(varchar(11), @total_errors - total_errors) + ")"),
	connections = convert(char(18), convert(varchar(11), @connections) + "(" +
		convert(varchar(11), @connections - connections) + ")")
from master.dbo.spt_monitor

/*
**  Now update spt_monitor
*/
update master.dbo.spt_monitor
	set
		lastrun = @now,
		cpu_busy = @cpu_busy,
		io_busy = @io_busy,
		idle = @idle,
		pack_received = @pack_received,
		pack_sent = @pack_sent,
		connections = @connections,
		pack_errors = @pack_errors,
		total_read = @total_read,
		total_write = @total_write,
		total_errors = @total_errors

return (0)
go
exec sp_procxmode 'sp_monitor_server', 'anymode'
go
grant execute on sp_monitor_server to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor')
begin
	drop procedure sp_monitor
end
go
print "Installing sp_monitor"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:39 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor [Total 6]
**
** 17260, "Can't run %1! from within a transaction."
** 18826, "Procedure '%1!' not found."
** 18889, "The specified command '%1!' does not exist."
** 19060, "Procedure %1!, %2! must be a positive integer."
** 19122, "%1! is not installed. Please run '%2!' script with appropriate role %3!"
** 19260, "Invalid argument or unsupported command. Use sp_monitor 'help' to get usage information."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

sp_dbxt_recreate_proc sp_monitor
go

/*
** NOTE: The lengths of the input arguments to this sproc are restricted by
**	 the length of identifiers such as table/db names. These are 30 in
**	 12.5.x, hence, it's sufficient to create this sproc with args of
**	 size 30 bytes. However, when this is ported to 15.0.x., as we now
**	 allow identifiers to be 255 bytes, the args to this sproc should be
**	 sized so that users can work with larger sized table/db names.
**	 For instance, the 'archive', 'report' commands allow for a 'prefix'
**	 sub-clause which specifies the prefix sub-string of the archive
**	 table. In 12.5.x, this prefix is restricted by the identifier's
**	 length of 30 bytes, but in 150x, there is no reason why users can't
**	 ask for "a_very_long_prefix_name" as a prefix sub-string.
**
** NOTE: There is a subtle reason why the call to sp_monitor_deadlock is
**	 not prefixed with the dbname, as follows:
**
**	The point is that the ancilliary support sprocs are all living
**	in sybsystemprocs, so to be sure that we are running the right
**	version, we hard-code the full path name.
**
**	sp_monitor_deadlock is different. It wants to select data from either
**	the main master..monDeadLock table, or the archived table. If we
**	hard-coded sybsystemprocs to the call, then sp_monitor_deadlock
**	would have to go through exec-immediate mess to constantly refernece
**	to either "master..monDeadLock" or the named archive in a named db.
**	
**	What we wanted to have happen here is:
**	
**	a) If the user runs from master, by default, we lookup monDeadLock
**	   in master and so all calls can be directly to monDeadLock.
**	
**	b) If the user calls this sproc from some other db that is also the
**	   archive db, and then *if* the archive is also named the default
**	   name (i.e. monDeadLock), then the SQL inside sp_monitor_deadlock
**	   does not have to change. It would work just as well accessing
**	   the archive named as monDeadLock as when it were called from the
**	   master db to report on the currently found monitoring entries in
**	   the main monitoring table.
**	   
**	Hence, this gimmickery. It's a bit subtle issue, and this calling
**	convention seems to work ok the way it's coded now.
*/
go

/*
** sp_monitor is the wrapper for any stored procedure that chooses to
** display data from monitoring tables.
** 
** A new subordinate stored procedure should be created for each specific
** option to sp_monitor. 
** Consider the example for statement monitoring.
** A new option "statement" is provided to sp_monitor and a sub-ordinate
** stored procedure sp_monitor_statement gets invoked when this option
** is passed in. Additional parameters could also be passed in for 
** specific options as seen fit.
{
*/
create procedure sp_monitor @entity varchar(30)=NULL, 
			    @dbname varchar(30)=NULL,
			    @OrderBy_OR_Procname varchar(30)=NULL,
			    @option varchar(30)=NULL
as
begin
declare @listall int
declare @u_entity 	varchar(30)
      , @l_entity 	varchar(30)
      , @entity_arg	varchar(30)	-- user supplied argument.
      , @charindex	int
declare @u_dbname 	varchar(30)
      , @l_dbname	varchar(30)
declare @u_option 	varchar(30)
declare @monprocname 	varchar(255)
      , @crt_procname	varchar(100)	-- For sp_monitor_crt_mon_config
declare @rtnstatus 	int
declare @spid		int
      , @context	int
      , @valid_entity	tinyint		-- @entity is valid
      , @valid_montype	tinyint		-- @dbname is a valid monitoring type

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_monitor"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

-- Trim off leading/trailing spaces to make parsing simpler.
--
select @entity = ltrim(rtrim(@entity))

-- Save off the user-input 1st arg, as we might reuse it for a substring.
--
select @entity_arg = @entity

-- If 1st arg is 'archive', or 'report', it might have a substring naming the
-- archive table's prefix, starting with ' using' clause. Extract out the
-- basic command first.
--
select @charindex = charindex(' ', @entity)
if (@charindex != 0)
begin
	select @entity = substring(@entity, 1, (@charindex - 1))
end

-- Convert to upper and lower case, for future re-use
select @u_entity = upper(@entity)
     , @l_entity = lower(@entity)
     , @u_dbname = upper(@dbname)
     , @l_dbname = lower(@dbname)
     , @u_option = upper(@option)

     -- Assume some error in control flow till we validate all arguments.
     , @rtnstatus = 1

     -- Assume invalid arguments till we know otherwise.
     , @valid_entity	= case when @entity IS NOT NULL then 0 else 1 end
     , @valid_montype	= case when @dbname IS NOT NULL then 0 else 1 end
     , @context = NULL

-- Cache status of valid entity and monitoring type (for reuse).
--
if (   (@u_entity is not NULL)
    and (@u_entity IN (   "ENABLE"
    			, "DISABLE"
			, "PROCEDURE"
			, "CONNECTION"
			, "STATEMENT"
			, "EVENT"
			, "DEADLOCK"
			, "PROCSTACK"
			, "ARCHIVE"
			, "REPORT"
			, "HELP"
			, "LIST"
			, "TRACE"	-- undocumented option; internal use
			)
	)
)
begin
	select @valid_entity = 1
end

if (   (@u_dbname is not NULL)
    and (@u_dbname IN (   "ENABLE"
    			, "DISABLE"
			, "PROCEDURE"
			, "CONNECTION"
			, "STATEMENT"
			, "EVENT"
			, "DEADLOCK"
			, "PROCSTACK"
			, "ARCHIVE"
			, "REPORT"
			, "HELP"	-- 2nd arg can be 'help'.
			, "ALL"		-- 2nd arg can be 'help', 'all'.
			)
	)
)
begin
	select @valid_montype = 1
end

/* 
** Verify if the parameters passed in are valid. Note that it is not possible
** to do all parameter passing here but effort is made to do as much of checking
** as possible. In cases where decisions on parameters cannot be made, they are 
** deferred to the individual stored procedure.
*/

if (
	(@valid_entity = 0)
     OR
	((@u_entity = "HELP") AND (@valid_montype = 0))
     OR
	(@u_entity in ("CONNECTION", "STATEMENT", "ENABLE", "DISABLE", 
				"EVENT", "HELP", "") AND
				((@OrderBy_OR_Procname is NOT NULL) OR (@option is NOT NULL)))
	OR
	(@u_entity = "PROCEDURE" AND ((@u_option not in ("SUMMARY", "DETAIL"))
			AND (@option is NOT NULL)))
	OR
	(      @u_entity in ("CONNECTION", "STATEMENT")
	  AND (@u_dbname not in ("CPU", "DISKIO", "ELAPSED TIME", ""))
	  AND (@u_dbname is not NULL)
	)
   )
begin
	-- Reuse variable to report help message. In the error generate the
	-- sp_monitor invocation to get the appropriate help, depending on the
	-- monitoring type requested.
	--
	-- . If a valid monitoring type was requested,  generate:
	--	sp_monitor 'help', '<monitoring type>'
	--
	-- . If an invalid monitoring type was requested,  generate:
	--	sp_monitor 'help'
	--
	-- . If 'help' was the command, generate:
	--	sp_monitor 'help'
	--
	select @monprocname = "sp_monitor 'help'"
			    + case 
			       when (@valid_entity = 1) and (@l_entity != 'help')
			       	then ", '" + @l_entity + "'"
				else NULL
			      end
	if ((@valid_entity = 0) or (@valid_montype = 0))
	begin
		select @entity_arg = case 
					when @valid_entity = 0
					then @entity
					when @valid_montype = 0
					then @dbname
				     end
		raiserror 18889, @entity_arg
	end
	raiserror 19260, @monprocname
	return(1)
end

-- Check if some of the common utility sprocs are available, and bail if
-- they are not. The sub-procs assume that these verification sprocs exist,
-- so check first and bail if they don't.
--
select @monprocname = "sybsystemprocs.dbo.sp_monitor_verify_setup"
if (not exists (select 1 from sybsystemprocs.dbo.sysobjects
		 where sysstat & 7 = 4
		   and id = object_id(@monprocname)) )
begin
	raiserror 18826, @monprocname
	goto missing_proc
end

select @monprocname = "sybsystemprocs.dbo.sp_monitor_verify_cfgval"
if (not exists (select 1 from sybsystemprocs.dbo.sysobjects
		 where sysstat & 7 = 4
		   and id = object_id(@monprocname)) )
begin
	raiserror 18826, @monprocname
	goto missing_proc
end

-- See if the monitoring-specific sub-proc is available, and setup a 
-- variable to call it.
--
select @monprocname = "sybsystemprocs.dbo.sp_monitor_"

select @monprocname = @monprocname + case @u_entity
					when NULL then 'server'
					else @l_entity
				     end

if (not exists (select 1 from sybsystemprocs.dbo.sysobjects
		 where sysstat & 7 = 4
		   and id = object_id(@monprocname)) )
begin
	raiserror 18826, @monprocname
	goto missing_proc
end

if @u_entity = "HELP"
begin
	-- Note that @dbname is overloaded to provide detailed 
	-- help on the parameter passed along with help.
	-- User can say: sp_monitor help, "all" 
	-- to get detailed help information on all supported monitoring types.
	-- In that caes pass @listall as 2.
	--
	select @listall = case
			    WHEN @u_dbname IS NULL then 1
			    WHEN lower(@u_dbname) = "all" then 2
			    else 0
			   end
	exec @rtnstatus = @monprocname @u_dbname , @listall
	return @rtnstatus
end

-- By default monitor the server
if (@u_entity is NULL) 
begin
	exec @rtnstatus = @monprocname
	return @rtnstatus
end

/*
** From here on, we go into the land of monitoring individual entities via
** MDA tables. This system needs a control table that might not exist from
** various calling sequences. Ensure that it is created first before doing
** any further work.
*/
select @crt_procname = "sybsystemprocs.dbo.sp_monitor_crt_mon_config"
exec @rtnstatus = @crt_procname
if (@rtnstatus != 0)
	return @rtnstatus

if (@u_entity = "ENABLE")
begin
	-- Using lower-case monitoring type names...
	exec @rtnstatus = @monprocname @l_dbname
end

else if (@u_entity = "DISABLE")
begin
	-- Using lower-case monitoring type names...
	exec @rtnstatus = @monprocname @l_dbname
end

else if @u_entity = "PROCEDURE"
begin
	exec @rtnstatus = @monprocname @dbname, @OrderBy_OR_Procname, @option
end

else if @u_entity = "EVENT"
begin
	select @spid = case WHEN (@u_dbname is not NULL)
			    THEN convert(int, @u_dbname)
			    ELSE 0
		       end
	exec @rtnstatus = @monprocname @spid
end

else if @u_entity = "CONNECTION" 
begin
	/*
	** By default order the output for monitoring
	** connections in the decreasing order of elapsed time
	*/
	if (@u_dbname is NULL)
	begin
		select @u_dbname = "ELAPSED TIME"
	end

	exec @rtnstatus = @monprocname @u_dbname, @OrderBy_OR_Procname
end

else if @u_entity = "STATEMENT"
begin
	/* By default order by elapsed time. */
	if (@u_dbname is NULL)
	begin
		select @u_dbname = "ELAPSED TIME"
	end

	exec @rtnstatus = @monprocname @u_dbname 
end

else if @u_entity = "DEADLOCK"
begin
	-- Call this directly from the current db, w/o prefacing the dbname,
	-- so that if the user issues this from 'master', we can correctly
	-- use master..monDeadLock w/o any further parsing fuss.
	--
	select @monprocname = "sp_monitor_deadlock"
	exec @rtnstatus = @monprocname
				  @dbname
				, @OrderBy_OR_Procname
				, @option
end

else if @u_entity = "PROCSTACK"
begin
	-- If no spid is provided, generate current task's procedure stack
	if (@dbname IS NULL)
		select @spid = @@spid

	else if (patindex("%[^0-9]%", @dbname) = 0)
	begin
		select @spid = convert(int, @dbname)
	end
	else
	begin
		select @monprocname = "<spid> = '" + @dbname + "'"
		raiserror 19060, '"sp_monitor procstack"', @monprocname
		return 1
	end

	-- Validate this arg, as an int, and pass it as the contet block
	-- to sub-proc. (These many lines of context will be generated when
	-- calling sp_showtext underneath here._
	--
	if (@OrderBy_OR_Procname IS NOT NULL)
	begin
		if (patindex("%[^0-9]%", @OrderBy_OR_Procname) = 0)
		begin
			select @context = convert(int, @OrderBy_OR_Procname)
		end
		else
		begin
			select @monprocname = "<contextblock> = '"
					    + @OrderBy_OR_Procname + "'"
			raiserror 19060, '"sp_monitor procstack"', @monprocname
			return 1
		end
	end

	-- Produce the procedural/stack trace for this spid.
	exec @rtnstatus = @monprocname @spid, @context, @option
end

else if @u_entity = "ARCHIVE"
begin
	-- Call the archival sproc for given monitoring type and archive.
	select @monprocname = "dbo.sp_monitor_archive"
	exec @rtnstatus = @monprocname @dbname, @entity_arg
end

else if @u_entity = "REPORT"
begin
	-- Call the reporting sproc for given monitoring type and report.
	select @monprocname = "dbo.sp_monitor_report"
	exec @rtnstatus = @monprocname @dbname, @entity_arg
				, @OrderBy_OR_Procname, @option 
end

else if @u_entity = "LIST"
begin
	exec @rtnstatus = @monprocname
end

else if @u_entity = "TRACE"
begin
	exec @rtnstatus = @monprocname @dbname
end

-- Return whatever return code we found from callee.
return(@rtnstatus)

missing_proc:
	raiserror 19122, "MDA", "installmontables", "(mon_role)"
	return(1)
end	-- }
go

go
exec sp_procxmode 'sp_monitor', 'anymode'
go
grant execute on sp_monitor to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_pkeys')
begin
	drop procedure sp_pkeys
end
go
print "Installing sp_pkeys"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** note: there is one raiserror message: 18040
**
** messages for "sp_pkeys"               18039, 18040
**
** 17461, "Object does not exist in this database."
** 18039, "table qualifier must be name of current database."
** 18040, "catalog procedure %1! can not be run in a transaction.", sp_pkeys
**
*/

create procedure sp_pkeys
			   @table_name		varchar(257),
			   @table_owner 	varchar(257) = null,
			   @table_qualifier varchar(257) = null 
as
declare @keycnt smallint
declare @indexid smallint
declare @i int
declare @id int
declare @uid int
select @id = NULL


	set nocount on

	if (@@trancount = 0)
	begin
		set chained off
	end
	else
	begin	
		/* if inside a transaction */
		/* catalog procedure sp_pkeys can not be run in a transaction.*/
		raiserror 18040, "sp_pkeys"
		return (1)
	end

	set transaction isolation level 1

	if @table_qualifier is not null
	begin
		if db_name() != @table_qualifier
		begin	
			/* if qualifier doesn't match current database */
			/* "table qualifier must be name of current database"*/
			raiserror 18039
			return (1)
		end
	end

	if @table_owner is null
	begin
		select @id = id , @uid = uid
		from sysobjects 
		where name = @table_name
			and uid = user_id()
		if (@id is null)
		begin
			select @id = id ,@uid = uid
			from sysobjects 
			where name = @table_name
			and uid = 1
		end
	end
	else
	begin
		select @id = id , @uid = uid
		from sysobjects 
		where name = @table_name and uid = user_id(@table_owner)
	end
	
	if (@id is null)
	begin	
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end

	create table #pkeys(
			 table_qualifier varchar(257),
			 table_owner     varchar(257),
			 table_name      varchar(257),
			 column_name     varchar(257),
			 key_seq	 smallint)


/*
**  now we search for primary key (only declarative) constraints
**  There is only one primary key per table.
*/

	select @keycnt = keycnt, @indexid = indid
	from   sysindexes
	where  id = @id
	and indid > 0 /* make sure it is an index */
	and status2 & 2 = 2 /* make sure it is a declarative constr */
	and status & 2048 = 2048 /* make sure it is a primary key */

/*
**  For non-clustered indexes, keycnt as returned from sysindexes is one
**  greater than the actual key count. So we need to reduce it by one to
**  get the actual number of keys.
*/

	if (@indexid >= 2)
	begin
		select @keycnt = @keycnt - 1
	end

	select @i = 1

	while @i <= @keycnt
	begin
		insert into #pkeys values
		(db_name(), user_name(@uid), @table_name,
			index_col(@table_name, @indexid, @i, @uid), @i)
		select @i = @i + 1
	end
	
	exec sp_autoformat @fulltabname = #pkeys,
		@selectlist = "table_qualifier, table_owner, table_name, column_name, key_seq",
		@orderby = "order by table_qualifier, table_owner, table_name, key_seq"
	drop table #pkeys	
	return (0)
go
exec sp_procxmode 'sp_pkeys', 'anymode'
go
grant execute on sp_pkeys to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_placeobject')
begin
	drop procedure sp_placeobject
end
go
print "Installing sp_placeobject"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */
/*	5.0	14.2	11/12/91	sproc/src/placeobject */

/*
** Messages for "sp_placeobject"        17730
**
** 17460, "Object must be in the current database."
** 17520, "There is no such segment as '%1!'."
** 17730, "Use sp_logdevice to move syslogs table."
** 17731, "You can't move system tables."
** 17732, "You do not own table '%1!'."
** 17733, "There is no table named '%1!'."
** 17734, "There is no index named '%1!' for table '%2!'."
** 17735, "'%1!' is now on segment '%2!'."
** 17736, "You can't place a user table/index to logsegment."
** 18336, "Permission denied. Your curwrite label must be
**	   set at the hurdle of the affected database."
** 17738, "sp_placeobject is not allowed for %1!, as it is
**         a virtually hashed table."
** 17739, "Segment %1! has a virtually hashed table; therefore,
**         you cannot place an object on this segment."
*/
/*
** NOTE:
** All updates to sysindexes are done by forcing the index access via
** 'csysindexes' so that it's clear that only one row is being updated.
** (Multi-row updates to sysindexes are prohibited.)
*/
create procedure sp_placeobject
@segname	varchar(255),	/* segment name */
@objname	varchar(1023)	/* object name */
as

declare	@msg		varchar(1024)	/* message text */
declare @tabname	varchar(767)	/* table name, may be qualified */
declare @indexname	varchar(255)	/* index name, unqualified */
declare	@indexid	smallint	/* index ID */
declare	@segment	smallint	/* segment number */
declare @procval 	int		/* 1 if user has sa_role, 0 otherwise */
declare	@revobjname	varchar(1023)	/* reverse of @objname */
declare @hash_bit	int		/* used for virtually hashed table */



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see if the segment exists.
*/
select @segment = segment
	from syssegments
	where name = @segname
if @segment is null
begin
	/*
	** 17520, "There is no such segment as '%1!'."
	*/
	raiserror 17520, @segname
	return (1)
end

/*
**  Are we dealing with a table or its index?
*/
if (@objname like "%.%") and (object_id(@objname) is null)
begin
	/* @objname is in the form [database.][owner.]table.index */
	select @revobjname = reverse(@objname)
	select
		@tabname = reverse(substring(@revobjname,
			charindex(".", @revobjname) + 1, 767)),
		@indexname = reverse(substring(@revobjname, 1,
			charindex(".", @revobjname) - 1))
end
else
begin
	/* @objname is in the form [database.][owner.]table */
	select @tabname = @objname, @indexname = null
end

/*
**  Make sure the table is local to the current database.
*/
if @tabname like "%.%.%" and
	substring(@tabname, 1, charindex(".", @tabname) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return  (1)
end

/*
**  make sure the table exists.
*/
if (object_id(@tabname) is null)
begin
	/*
	** 17733, "There is no table named '%1!'."
	*/
	raiserror 17733, @tabname
	return (1)
end

/*
**  Can't use placeobject to move syslogs.
*/
if (object_id(@tabname) = 8)
begin
	/*
	** 17730, "Use sp_logdevice to move syslogs table."
	*/
	raiserror 17730
	return (1)
end

/*
**  Can't move system tables.
*/
if (object_id(@tabname) < 100)
begin
	/*
	** 17731, "You can't move system tables."
	*/
	raiserror 17731
	return (1)
end

/*
**  Only the Database Owner (DBO) or Table Owner (TBO) or
**  Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if user_id() != 1
begin
	if not exists (select * from sysobjects
		where id = object_id(@tabname) and uid = user_id())
	begin
		if (proc_role("sa_role") < 1)
		begin
			/*
			** 17732, "You do not own table '%1!'."
			*/
			raiserror 17732, @tabname
			return (1)
		end
	end
end

select @hash_bit = number from master.dbo.spt_values
	where name = "virtually hashed table" and type="O2"
if exists (select * from sysobjects
	where id = object_id(@tabname) and @hash_bit = sysstat2 & @hash_bit)
begin
	/*
	** 17738, "sp_placeobject is not allowed for %1!, as it is
	**         a virtually hashed table."
	*/
	raiserror 17738, @tabname
	return (1)
end

/* If user has sa role audit this as a successful sa 
** command execution.
*/ 
if charindex("sa_role",show_role()) > 0
	select @procval = proc_role("sa_role") 

/*
**  If we are dealing with an index, make sure it exists.
*/
if @indexname is not  null and
	not exists (select * from sysindexes
	where id = object_id(@tabname) and name = @indexname)
begin
	/*
	** 17734, "There is no index named '%1!' for table '%2!'."
	*/
	raiserror 17734, @indexname, @tabname
	return (1)
end


if (@segname = "logsegment")
begin
	/* 17736, "You can't place a user table/index to logsegment." */
	raiserror 17736
	return (1)
end

if exists (select * from syssegments
	where name = @segname and 2 = status & 2)
begin
	/*
	** 17739, "An object cannot be placed on segment %1!. As this segment has a virtually hashed table."
	*/
	raiserror 17739, @segname
	return (1)
end


/*
**  Everything's ok so change the segment for the object.
*/
declare @dbname		varchar(255)
declare @objid		int
declare @ptnid		int
declare @placementptnid int
declare @placementidx	smallint
declare @moreupdates	smallint
 
select @dbname = db_name()
select @objid = object_id(@tabname)

/*
** If the table has a placement index (bit 0x200 = 512) we need
** to consider the below two cases:
**
** 1)	if @indexname is null then we need to update syspartitions
**	for indid 0 as well for the placement index.
**
** 2)	if @indexname is not null then we need to update syspartitions
**	for this index as well for indid 0 if this index is the
**	placement index of the table.
**
** We can't disassociate a placement index from its data pages
** likewise we do for an APL table and its clustered index,
** where in that case we instead have a single row in sysindexes
** with indid 1.
*/
select @placementidx = 0
select @placementidx = indid 
	from sysindexes 
	where id = @objid and indid > 1 and status2 & 512 = 512
 
/* Assume we don't have to do more than one update of sysindexes. */
select @moreupdates = 0

if @indexname is null
begin
	select @indexid = indid
		from sysindexes
		where id = @objid and indid < 2

	if (@placementidx > 1)
		select @moreupdates = 1
end
else
begin
	select @indexid = indid
		from sysindexes
		where id = @objid and name = @indexname

	if (@placementidx > 1 and @indexid = @placementidx)
	begin
		select @moreupdates = 1

		/*
		** Force it to be 0 so that we update below
		** sysindexes row for indid 0.
		*/
		select @placementidx = 0
	end
end


begin tran updatesys

/* Get the partition ids of affected index*/
declare ptnid_crsr cursor
	for select partitionid from syspartitions
		where id = @objid and indid = @indexid
	for read only

update sysindexes
set segment = @segment
from sysindexes
where id = @objid and indid = @indexid
plan "(update (i_scan csysindexes sysindexes))"

if (@@error != 0)
begin
	rollback tran updatesys
	return (1)
end

/*
** We updated a sysindexes row. We also need to update the in-core
** structure representing this sysindexes row as the sysindexes rows
** cache is not a write thru cache.
*/
dbcc refreshides(@dbname, @objid, @indexid, "placeobject")

if (@@error != 0)
begin
	rollback tran updatesys
	return (1)
end

update syspartitions
	set segment = @segment
	from syspartitions
	where id = @objid and  indid = @indexid

if (@@error != 0)
begin
	rollback tran updatesys
	return (1)
end

/*
** We updated syspartitions row. We also need to update the in-core
** structure representing this syspartitions row.
*/
open ptnid_crsr
fetch ptnid_crsr into @ptnid
while(@@sqlstatus = 0) 
begin
	dbcc refreshpdes(@dbname, @objid, @indexid, @ptnid, "placeobject")

	if (@@error != 0)
	begin
		rollback tran updatesys
		return (1)
	end
	fetch ptnid_crsr into @ptnid
end
close ptnid_crsr
deallocate cursor ptnid_crsr

if (@moreupdates = 1)
begin
	declare placementptnid_crsr cursor
	for select partitionid from syspartitions 
		where id = @objid and indid = @placementidx
	for read only

	update sysindexes
	set segment = @segment
	from sysindexes
	where id = @objid and indid = @placementidx
	plan "(update (i_scan csysindexes sysindexes))"

	if (@@error != 0)
	begin
		rollback tran updatesys
		return (1)
	end

	/*
	** We updated a sysindexes row. We also need to update the in-core
	** structure representing this sysindexes row as the sysindexes rows
	** cache is not a write thru cache.
	*/
	dbcc refreshides(@dbname, @objid, @placementidx, "placeobject")

	if (@@error != 0)
	begin
		rollback tran updatesys
		return (1)
	end

	update syspartitions
		set segment = @segment
		from syspartitions
		where id = @objid 
		      and indid = @placementidx

	if (@@error != 0)
	begin
		rollback tran updatesys
		return (1)
	end

	/*
	** We updated syspartitions row. We also need to update the in-core
	** structure representing this syspartitions row.
	*/
	open placementptnid_crsr
	fetch placementptnid_crsr into @placementptnid
	while(@@sqlstatus = 0) 
	begin
		dbcc refreshpdes(@dbname, @objid, @placementidx, 
				 @placementptnid, "placeobject")

		if (@@error != 0)
		begin
			rollback tran updatesys
			return (1)
		end
		fetch placementptnid_crsr into @placementptnid
	end
	close placementptnid_crsr
	deallocate cursor placementptnid_crsr
end

commit tran updatesys

dbcc dbrepair (@dbname, remap, NULL, -1, @segname)
/*
** 17735, "'%1!' is now on segment '%2!'."
*/
exec sp_getmessage 17735, @msg output
print @msg, @objname, @segname

return (0)
go
exec sp_procxmode 'sp_placeobject', 'anymode'
go
grant execute on sp_placeobject to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_primarykey')
begin
	drop procedure sp_primarykey
end
go
print "Installing sp_primarykey"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/password */

/*
** Messages for "sp_primarykey"         17740
**
** 17390, "Table or view name must be in 'current' database." 
** 17492, "The table or view named doesn't exist in the current database." 
** 17740, "Only the owner of the table may define a primary key."
** 17741, "Primary key already exists on table -- drop key first."
** 17742, "The table has no such first column."
** 17743, "The table has no such second column."
** 17744, "The table has no such third column."
** 17745, "The table has no such fourth column."
** 17746, "The table has no such fifth column."
** 17747, "The table has no such sixth column."
** 17748, "The table has no such seventh column."
** 17749, "The table has no such eighth column."
** 17750, "New primary key added."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_primarykey
@tabname  varchar(767),			/* table name that has the key */
@col1     varchar(255),			/* columns that make up the key */
@col2     varchar(255) = NULL,
@col3     varchar(255) = NULL,
@col4     varchar(255) = NULL,
@col5     varchar(255) = NULL,
@col6     varchar(255) = NULL,
@col7     varchar(255) = NULL,
@col8     varchar(255) = NULL
as

declare @uid int			/* owner id of the object */
declare @cnt smallint			/* howmany columns in key */
declare @key1 smallint			/* colids of the columns in the key */
declare @key2 smallint
declare @key3 smallint
declare @key4 smallint
declare @key5 smallint
declare @key6 smallint
declare @key7 smallint
declare @key8 smallint
declare @msg  varchar(1024)
declare @dbname varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  Check to see that the tabname is local.
*/
if @tabname like "%.%.%" and
	substring(@tabname, 1, charindex(".", @tabname) - 1) != db_name()
begin
	/*
	** 17390, "Table or view name must be in 'current' database." 
	*/
	raiserror 17390
	return (1)
end

/*
**  See if we can find the object.  It must be a system table, user table,
**  or view.  The low 3 bits of sysobjects.sysstat indicate what the 
**  object type is -- it's more reliable than using sysobjects.type which
**  could change.
*/
if not exists (select *
	from sysobjects
		where id = object_id(@tabname)
			and (sysstat & 7 = 1		/* system table */
				or sysstat & 7 = 2	/* view */
				or sysstat & 7 = 3))	/* user table */
begin
	/*
	** 17492, "The table or view named doesn't exist in the current database." 
	*/
	raiserror 17492
	return (1)
end 

/*
**  Check to see that object owner is adding the key.
*/
select @uid = uid
	from sysobjects
		where id = object_id(@tabname)
			and (sysstat & 7 = 1            /* system table */
				 or sysstat & 7 = 2      /* view */
				  or sysstat & 7 = 3)     /* user table */
if @uid != user_id()
begin
	/*
	** 17740, "Only the owner of the table may define a primary key."
	*/
	raiserror 17740
	return (1)
end

/*
**  See if the primary key exists already.  Syskeys.type = 1 indicates
**  a primary key.
*/
if exists (select *
		from syskeys
			where id = object_id(@tabname)
				and type = 1)
begin
	/*
	** 17741, "Primary key already exists on table -- drop key first."
	*/
	raiserror 17741
	return (1)
end

/*
**  Now check out each column argument to verify it's existence.
*/
select @cnt = 1, @key1 = colid
	from syscolumns
		where name = @col1 
			and id = object_id(@tabname)
if @key1 is NULL
begin
	/*
	** 17742, "The table has no such first column."
	*/
	raiserror 17742
	return (1)
end

if @col2 is not NULL
begin
	select @cnt = @cnt + 1, @key2 = colid
		from syscolumns
			where name = @col2 
				and id = object_id(@tabname)
	if @key2 is NULL
	begin
		/*
		** 17743, "The table has no such second column."
		*/
		raiserror 17743
		return (1)
	end
end
else goto doinsert

if @col3 is not NULL
begin
	select @cnt = @cnt + 1, @key3 = colid
		from syscolumns
			where name = @col3 
				and id = object_id(@tabname)
	if @key3 is NULL
	begin
		/*
		** 17744, "The table has no such third column."
		*/
		raiserror 17744
		return (1)
	end
end
else goto doinsert

if @col4 is not NULL
begin
	select @cnt = @cnt + 1, @key4 = colid
		from syscolumns
			where name = @col4 
				and id = object_id(@tabname)
	if @key4 is NULL
	begin
		/*
		** 17745, "The table has no such fourth column."
		*/
		raiserror 17745
		return (1)
	end
end
else goto doinsert

if @col5 is not NULL
begin
	select @cnt = @cnt + 1, @key5 = colid
		from syscolumns
			where name = @col5 
				and id = object_id(@tabname)
	if @key5 is NULL
	begin
		/*
		** 17746, "The table has no such fifth column."
		*/
		raiserror 17746
		return (1)
	end
end
else goto doinsert

if @col6 is not NULL
begin
	select @cnt = @cnt + 1, @key6 = colid
		from syscolumns
			where name = @col6 
				and id = object_id(@tabname)
	if @key6 is NULL
	begin
		/*
		** 17747, "The table has no such sixth column."
		*/
		raiserror 17747
		return (1)
	end
end
else goto doinsert

if @col7 is not NULL
begin
	select @cnt = @cnt + 1, @key7 = colid
		from syscolumns
			where name = @col7 
				and id = object_id(@tabname)
	if @key7 is NULL
	begin
		/*
		** 17748, "The table has no such seventh column."
		*/
		raiserror 17748
		return (1)
	end
end
else goto doinsert

if @col8 is not NULL
begin
	select @cnt = @cnt + 1, @key8 = colid
		from syscolumns
			where name = @col8 
				and id = object_id(@tabname)
	if @key8 is NULL
	begin
		/*
		** 17749, "The table has no such eighth column."
		*/
		raiserror 17749
		return (1)
	end
end

/*
**  Type 1 is a primary key, 2 is a foreignkey, and 3 is a commonjoin.
*/
doinsert:

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction	
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

insert into syskeys
	(id, type, depid, keycnt, size, key1, key2, key3, key4, key5,
		key6, key7, key8, spare1)
values (object_id(@tabname), 1, NULL, @cnt, 0, @key1, @key2, @key3, @key4, 
		@key5, @key6, @key7, @key8, 0)

if (@@error != 0)
begin
	rollback transaction rs_logexec
	return(1)
end

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_primarykey", @dbname
			
	rollback transaction rs_logexec
	return(1)
end

commit transaction

/*
** 17750, "New primary key added."
*/
exec sp_getmessage 17750, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_primarykey', 'anymode'
go
grant execute on sp_primarykey to public
go
exec sp_procxmode 'sp_primarykey', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_recompile')
begin
	drop procedure sp_recompile
end
go
print "Installing sp_recompile"
go

/*
** Generated by spgenmsgs.pl on Tue May 31 02:59:14 2005 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/recompile [Total 7]
**
** 17390, "Table or view name must be in current database."
** 17460, "Object must be in the current database."
** 17732, "You do not own table '%1!'."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17760, "%1!' is a system table. Cannot use '%2!' on system tables."
** 17761, "Object '%1!' is not a table."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in updating the schemacnt column in sysobjects."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/recompile [Total 1]
**
** 17762, "Each stored procedure and trigger that uses table '%1!' will be recompiled the next time it is executed."
*/
/*
** End spgenmsgs.pl output.
*/
/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/password */

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_recompile
@objname	varchar(767)
as

declare @type	smallint
declare @uid	int
declare @msg    varchar(1024)
declare @dbname varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

if @objname like '%%.%%.%%' and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/*
	** 17390, "Table or view name must be in 'current' database."
	*/
	raiserror 17390
	return (1)
end

if not exists (select *
			from sysobjects
				where id = object_id(@objname))
begin
	/*
	** 17460, "Object must be in the current database."
	*/
	raiserror 17460
	return (1)
end

select @type = sysstat & 7, @uid = uid
	from sysobjects
		where id = object_id(@objname)
if @type = 1
begin
	/*
	** 17760, "'%1!' is a system table.  Sp_recompile cannot be used on system tables."
	*/
	raiserror 17760, @objname, "sp_recompile"
	return (1)
end
if @type != 3
begin
	/*
	** 17761, "Object '%1!' is not a table."
	*/
	raiserror 17761, @objname
	return (1)
end

if user_id() != 1 and @uid != user_id()
begin
	/*
	** 17732, "You do not own table '%1!'." 
	*/
	raiserror 17732, @objname
	return (1)
end

set nocount on

/* Start the transaction to log the execution of this procedure.
**
** IMPORTANT: The name "rs_logexec is significant and is used by 
**            Replication Server
*/
begin transaction rs_logexec

/*
** Increment the schemacnt associated with cached des.
*/
if (schema_inc(object_id(@objname), 1) != 1)
begin
	/*
	** 17763, "The execution of the stored procedure '%1!'
	**         in database '%2!' was aborted because there
	**         was an error in updating the column
	**         schemacnt in sysobjects."
	*/
	select @dbname = db_name()
	raiserror 17763, "sp_recompile", @dbname

	rollback transaction rs_logexec
	return(1)
end

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!'
	** 	   in database '%2!' was aborted because there
	** 	   was an error in writing the replication log
	**	   record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_recompile", @dbname
		
	rollback transaction rs_logexec
	return(1)
end

commit transaction

/*
** 17762, "Each stored procedure and trigger that uses table '%1!' will
**         be recompiled the next time it is executed."
*/
exec sp_getmessage 17762, @msg output
print @msg, @objname

return (0)
go
exec sp_procxmode 'sp_recompile', 'anymode'
go
grant execute on sp_recompile to public
go
exec sp_procxmode 'sp_recompile', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_remoteoption')
begin
	drop procedure sp_remoteoption
end
go
print "Installing sp_remoteoption"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/remoteoption */

/*
** Messages for "sp_remoteoption"       17770
**
** 17513, "There is no remote user '%1!' mapped to local user '%2!' from
**	the remote server '%3!'."
** 17260, "Can't run %1! from within a transaction."
** 17770, "Settable remote login options."
** 17771, "There is no remote user '%1!' mapped to local user '%2!' on
**	remote server '%3!'."
** 17772, "Usage: sp_remoteoption [remoteserver, loginame, remotename,
**	optname, {true | false}]"
** 17773, "Remote login option doesn't exist or can't be set by user."
** 17774, "Run sp_remoteoption with no parameters to see options."
** 17775, "Remote login option is not unique."
** 17777, "Option '%1!' turned on."
** 17778, "Option '%1!' turned off."
** 17431, "true"
** 17432, "false"
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
** 18780, "Synchronization will not occur because server '%1!' is the companion server."
** 18782 "Unable to find a server with name '%1!' and id '%2!'."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_remoteoption
@remoteserver varchar(255) = NULL,	/* server name to change */
@loginame varchar(255) = NULL,		/* user's remote name */
@remotename varchar(255) = NULL,		/* user's local user name */
@optname varchar(20) = NULL,		/* option name to turn on/off */
@optvalue varchar(10) = NULL		/* true or false */
as

declare @statvalue 	smallint	/* number of option */
declare @optcount 	int		/* number of options like @optname */
declare	@msg		varchar(1024)
declare @suid		int
declare @rname  	varchar(255)
declare @lname  	varchar(255)
declare @true		varchar(10)
declare @false  	varchar(10)
declare @sptlang	int
declare @whichone	int		/* Which language */
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_remoteoption', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sso_role") = 0)
	return (1)

select @sptlang = 0, @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17070 and 17079
		and langid = @@langid)
	    select @sptlang = 0
end

/*
**  If no @server given, just list the possible remote login options.
**  Only certain status bits may be set or cleared.  
**	   settable                	    not settable
**      ------------------------------  --------------------------
**	trusted (1)
*/
if @remoteserver is null
begin
	/*
	** 17770, "Settable remote login options."
	*/
	exec sp_getmessage 17770, @msg output
	print @msg
	if @sptlang = 0
	    exec sp_autoformat @fulltabname = "master.dbo.spt_values",
		@selectlist = "remotelogin_option = name",
		@whereclause = "where type = 'F' and number in (1, 1) and number > 0",
		@orderby = "order by name"
	else
	begin
	    select remotelogin_option = name, description
	    into #remoption1rs	
		from master.dbo.spt_values, master.dbo.sysmessages
			where type = "F"
				and number in (1, 1)
				and number > 0
				and msgnum = error
				and error between 17070 and 17079
				and langid = @sptlang
	    exec sp_autoformat @fulltabname = #remoption1rs,
		@orderby = "order by remotelogin_option"	
	    drop table #remoption1rs
	end
	return (0)
end

/*
**  If @loginame is NULL then we want to set @suid = -1. Otherwise get
**  it real value.
*/
if @loginame is null
	select @suid = -1
else select @suid = suser_id(@loginame)

/*
**  Verify the server name, local, and remote names. 
*/
if not exists (select *
		from master.dbo.sysremotelogins r, master.dbo.sysservers s
			where r.remoteserverid = s.srvid
				and s.srvname = @remoteserver
				and r.remoteusername = @remotename
				and r.suid = @suid)
begin
	/*
	** 17771, "There is no remote user '%1!' mapped to local user '%2!' on
	**	remote server '%3!'."
	*/
	select @rname = isnull(@remotename, "NULL")
	select @lname = isnull(@loginame, "NULL")
	raiserror 17771, @rname, @lname, @remoteserver
	return (1)
end

/*
**  Check remaining parameters.
*/
/* 17431, "true" */
exec sp_getmessage 17431, @true out
/* 17432, "false" */
exec sp_getmessage 17432, @false out
if @optname is NULL or lower(@optvalue) not in 
	("true", "false", @true, @false) or @optvalue is null
begin
	/*
	** 17772, "Usage: sp_remoteoption [remoteserver, loginame, remotename,
	**	optname, {true | false}]"
	*/
	raiserror 17772
	return (1)
end

/*
**  Use @optname and try to find the right option.
**  If there isn't just one, print appropriate diagnostics and return.
*/
select @optcount = count(*)
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%" and type = "F"
			and number in (1, 1)
			and number > 0

/*
** If option not found, and language not english, then check some more
*/
if @optcount = 0 and @sptlang != 0
begin
    select @optcount = count(*)
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%" and type = "F"
			and number in (1, 1)
			and number > 0
			and error between 17070 and 17079
			and msgnum = error
			and langid = @sptlang
    select @whichone = 1
end

/*
**  If no option, show the user what the options are.
*/
if @optcount = 0
begin
	/*
	** 17773, "Remote login option doesn't exist or can't be set by user."
	*/
	raiserror 17773
	/*
	** 17774, "Run sp_remoteoption with no parameters to see options."
	*/
	exec sp_getmessage 17774, @msg output
	print @msg
	return (1)
end

/*
**  If more than one option like @optname, show the duplicates and return.
*/
if @optcount > 1
begin
	/*
	** 17775, "Remote login option is not unique."
	*/
	raiserror 17775

	if @sptlang = 0
	begin
	    select duplicate_option = name
	    into #remoption2rs   	
		from master.dbo.spt_values
			where name like "%" + @optname + "%"
				and type = "F"
				and number in (1, 1)
				and number > 0
	    exec sp_autoformat @fulltabname = #remoption2rs
	    drop table #remoption2rs
	end
	else
	begin
	    select duplicate_option = name, description
	    into #remoption3rs  	
		from master.dbo.spt_values, master.dbo.sysmessages
			where 
				(name like "%" + @optname + "%" 
				or description like "%" + @optname + "%")
				and type = "F"
				and number in (1, 1)
				and number > 0
				and error between 17070 and 17079
				and msgnum = error
				and langid = @sptlang
	    exec sp_autoformat @fulltabname = #remoption3rs
	    drop table #remoption3rs
	end
      return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_remoteoption"
	return (1)
end

/*
**  Get the number which is the bit value to set
*/
if @whichone = 0
    select @statvalue = number
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%" and type = "F"
			and number in (1, 1)
			and number > 0
else
    select @statvalue = number
 	   from master.dbo.spt_values, master.dbo.sysmessages
		where description like "%" + @optname + "%" 
			and type = "F"
			and number in (1, 1)
			and number > 0
			and error between 17070 and 17079
			and msgnum = error
			and langid = @sptlang



/*
**  Now update sysremotelogins.
*/
if lower(@optvalue) in ("true", @true)
begin
	update master.dbo.sysremotelogins
		set status = status | @statvalue
		from master.dbo.sysremotelogins r, master.dbo.sysservers s
			where r.remoteserverid = s.srvid
				and s.srvname = @remoteserver
				and r.remoteusername = @remotename
				and r.suid = @suid

	

	/*
	** 17777, "Option '%1!' turned on."
	*/
	exec sp_getmessage 17777, @msg output
	print @msg, @optname


	return (0)
end

/*
**  We want to turn it off.
*/
else
begin
	update master.dbo.sysremotelogins
	set status = status & ~@statvalue
	from master.dbo.sysremotelogins r, master.dbo.sysservers s
	where r.remoteserverid = s.srvid
		and s.srvname = @remoteserver
		and r.remoteusername = @remotename
		and r.suid = @suid

	

	/*
	** 17778, "Option '%1!' turned off."
	*/
	exec sp_getmessage 17778, @msg output
	print @msg, @optname



	return (0)
end

return (0)


go
exec sp_procxmode 'sp_remoteoption', 'anymode'
go
grant execute on sp_remoteoption to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_rename')
begin
	drop procedure sp_rename
end
go
print "Installing sp_rename"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/password */

/*
** Messages for "sp_rename"             17780
**
** 17260, "Can't run %1! from within a transaction."
** 17460, "Object must be in the current database."
** 17240, "'%1!' is not a valid name."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because therewas an error in updating the schemacnt column in sysobjects."
** 17780, "There is already a column named '%1!' in table '%2!'."
** 17781, "Column name has been changed."
** 17782, "You do not own a table or column (or index) of that name in the current database."
** 17783, "There is already an index named '%1!' for table '%2!'."
** 17784, "Index name has been changed."
** 17785, "Table or view names beginning with '#' are not allowed."
** 17786, "Object name cannot be changed either because it does not exist in this database, or you don't own it, or it is a system name."
** 17787, "Newname already exists in systypes."
** 17788, "Newname already exists in sysobjects."
** 17789, "Object name has been changed."
** 17968, "The built-in function logschema() failed for '%1!'."
** 18058, "Name of user-defined type name changed."
** 18071, "Set curwrite to the level of table/column."
** 18077, "Set curwrite to the level of index."
** 18078, "Set curwrite to the level of the object in systypes."
** 18079, "Set curwrite to the level of the object in sysobjects."
** 18080, "Certified state of object '%1!' has been set to 'Suspect'"
** 18409, "The built-in function '%1!' failed. Please see 
**         the other messages printed along with this message."
** 18410, "The replication status of '%1!' is corrupt. Please contact 
**         Sybase Technical Support."
** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
** 19412  "Cannot rename a service that is deployed."
** 19819  "Warning: Changing an object or column name may break existing stored procedures, cached statements or other compiled objects."
**
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
**
** NOTE:
** All updates to sysindexes are done by forcing the index access via
** 'csysindexes' so that it's clear that only one row is being updated.
** (Multi-row updates to sysindexes are prohibited.)
*/

create procedure sp_rename
@objname varchar(512),			/* old (current) object name */
@newname varchar(256),			/* new name we want to call it */
@indorcol varchar(10) = null		/* Index or column to rename */
as

declare @objid int			/* object id of the thing to rename */
declare @index_objid int		/* object id from sysindexes */
declare @msg varchar(1024)
declare @temp_dbid	int
declare @temp_objid	int
declare @curdb_name	varchar(255)	/* name of current db */
declare @rep_constant	smallint	/* bit indicating a repl. object */
declare @cur_sysstat	smallint	/* current sysstat value of object */
declare @rep_obj	int		/* is the object replicated? */
declare @rep_db_stat	int		/* rep status of database */
declare @rep_db		int		/* is the db replicated */
declare @table_or_proc	int		/* object is a table or procedure */
declare @obj_type	char(2)		/* type of the object */
declare @user_tran	int		/* inside a user tran? */
declare @after_image	int		/* log the after image of the schema */
declare @mod_versionts	int		/* modify version timestamp after
					** logging the schema
					*/
declare @dbname varchar(255)
declare @maxobjlen	int		/* get the length of sysobject.name from syscolumns */
declare @maxuserlen	int		/* get the length of sysusers.name from syscolumns */
declare @maxtotlen	int		/* get the Total length of sysobjects.name + sysusers.name*/
declare @lt_rep_get_failed
			int
declare @lt_rep_all	int
declare @lt_rep_l1	int

/*
** Initialise objid and index_objid
*/
select @objid = NULL
select @index_objid = NULL
/* 
** check the length of sysobject.name and sysuser.name 
*/
select @maxobjlen = length from syscolumns
	where id = object_id("sysobjects") and
	name = 'name'
select @maxuserlen = length from syscolumns
	where id = object_id("sysusers") and
	name = 'name'
select @maxtotlen = (@maxobjlen + @maxuserlen) + 1


/* check the lengths of the input params */
if char_length(@objname) > @maxtotlen 
begin
        /*
        ** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
        */
        raiserror 17325, @objname, @maxtotlen 
        return (1)
end
if char_length(@newname) > @maxobjlen
begin
        /*
        ** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
        */
        raiserror 17325, @newname, @maxobjlen
        return (1)
end
if ((@indorcol is not null) and (@indorcol not in ('index', 'column')))
begin
	/*
	** 18938, "Invalid third argument '%1!' entered. Valid values are 
	** {'index'|'column'}"
	*/
	raiserror 18938, @indorcol
	return (1)
end

/*
** Replication constants.
*/
select @lt_rep_get_failed = -2, @lt_rep_all = 2048, @lt_rep_l1 = 4096 
/*
** Running sp_rename inside a transaction would endanger the
** recoverability of the transaction/database. Disallow it.
*/

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_rename"
	return (1)
end

set chained off
set transaction isolation level 1

if @objname like "%.%.%"
begin
	/*
	** 17460, "Object must be in the current database."
	*/
	raiserror 17460
	return (1)
end

/*
**  Check to see that the @newname is valid.
*/
if valid_name(@newname,@maxobjlen) = 0
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @newname
	return (1)
end

/*
**  Check to see if we are renaming a table/column (or table/index)
**  or a table or usertype.
**  If @objname is of the form table.column then it's a column.
**  In the column case, we need to extract and verify the table and
**  column names and make sure the user owns the table that is getting
**  the rule bound.
*/
if @objname like "%.%"
begin
	declare @tabname varchar(255)		/* name of table */
	declare @colname varchar(255)		/* name of column */
	declare @colid smallint			/* colid of the column */

	/*
	**  Get the table name out.
	*/
	select @tabname = substring(@objname, 1, charindex(".", @objname) - 1)
	select @colname = substring(@objname, charindex(".", @objname) + 1, @maxtotlen)

	/*
	**  If no third parameter was specified, or, if third parameter
	**  was specified as 'index', see if there is an index
	**  of this name in a table owned by the user, and keep it in a 
	**  local variable.
	*/
	if (@indorcol is null or @indorcol = 'index')
	begin
		select @index_objid = sysindexes.id, @colid = sysindexes.indid
			from sysobjects, sysindexes
		where sysindexes.id = sysobjects.id
			and sysobjects.name = @tabname
			and sysindexes.name = @colname
			and sysindexes.indid != 0
			and sysobjects.sysstat & 7 = 3	/* user table */
			and sysobjects.uid = user_id()

	end

	/*
	**  Now check to see that the column exists in a table owned
	**  by the user. Don't do this if the user explicitly specified
	**  that this is an index.
	*/

	if (@indorcol is null or @indorcol != 'index')
	begin
		select @objid = syscolumns.id, @colid = syscolumns.colid
			from sysobjects, syscolumns
		where syscolumns.id = sysobjects.id
			and sysobjects.name = @tabname
			and syscolumns.name = @colname
			and (sysobjects.sysstat & 7 = 2		/* user table */
			or sysobjects.sysstat & 7 = 3)		/* view */
			and sysobjects.uid = user_id()
	end

	/*
	**  Did we find it?  If not, it might be an index name so we'll
	**  check in the next case. If the user explicitly specified 
	**  that this is an index name, check in the next case as well.
	*/
	if @objid is not  null
	begin
		/*
		**  If there is an index as well as a column of the same
		**  name, raise an error to warn the user of this ambiguity.
		*/
		if @index_objid is not null
		begin
			/*
			** 18939, "There is an index as well as a column of
			** the name '%1!'. Please specify as the third 
			** argument whether you would like to rename 'index' 
			** or 'column'"
			*/
			raiserror 18939, @colname
			return (1)
		end

		/* 
		** Cannot modify the name of a function-based index key. 
		** The name is a system name created internally.
		*/
		if exists (select 1 
				from syscolumns 
					where id = @objid and
					      colid = @colid and
					      status3 & 1 = 1)
		begin
			/*
			** 17786, "Object name cannot be changed either 
			** because it does not exist in this database, 
			** or you don't own it, or it is a system name."
			*/
			raiserror 17786
			return (1)
		end

		/*
		**  Check to make sure that there is no already a column
		**  that has the new name.
		*/
		if exists (select *
				from syscolumns
					where id = @objid
						and name = @newname)
		begin
			/*
			** 17780, "There is already a column named '%1!' in table '%2!'."
			*/
			raiserror 17780, @newname, @tabname
			return (1)
		end

		/* determine the object's replication status */

		/* Replication enabled flag is 8000H (which is -32768D) */
		select @rep_constant = -32768

		select
			@cur_sysstat = sysstat
		from
			sysobjects holdlock
		where
			id = @objid

		if (@cur_sysstat & @rep_constant) = @rep_constant
		begin
			select @rep_obj = 1
		end
		else
		begin
			select @rep_obj = 0
		end

		/* determine the database's replication status */
		select @rep_db_stat = getdbrepstat()
		if (@rep_db_stat = @lt_rep_get_failed)
		begin
        		/*
        		** 18409, "The built-in function getdbrepstat() 
			** failed. Please see the other messages printed 
			** along with this message."
        		*/
			raiserror 18409, "getdbrepstat"
        		return (1)
		end
		else
		begin
			if ((@rep_db_stat & @lt_rep_all = @lt_rep_all) or
			    (@rep_db_stat & @lt_rep_l1 = @lt_rep_l1))
				select @rep_db = 1
			else
				select @rep_db = 0
		end

		/*
		** IMPORTANT: The name rs_logexec is significant
		** and is used by Replication Server. 
		*/
		begin transaction rs_logexec

		/* if the object is replicated, log the schema before 
		** changing the column name
		*/
		if ((@rep_obj = 1) or (@rep_db = 1))
		begin
			select @user_tran = 0
			select @after_image = 0
			select @mod_versionts = 1
			if (logschema(@objid, @user_tran, @after_image, 
					@mod_versionts) != 1)
			begin
				/*
				** 17968 "The built-in function logschema() 
				** failed for '%1!'."
				*/
				raiserror 17968, @tabname

				rollback transaction rs_logexec
				return(1)
			end
		end 

		/*
		** Update schema count for this table or view.
		*/
		if (schema_inc(object_id(@tabname), 2) != 1)
		begin
			/*
			** 17763, "The execution of the stored procedure '%1!'
			**         in database '%2!' was aborted because there
			**         was an error in updating the column
			**         schemacnt in sysobjects."
			*/
			select @dbname = db_name()
			raiserror 17763, "sp_rename", @dbname
			rollback transaction rs_logexec
			return(1)
		end

		/*
		**  Go ahead and change the column name.
		*/
		update syscolumns
			set name = @newname
				from syscolumns
			where id = @objid
				and colid = @colid
		/*
		** If we are renaming the SYB_IDENTITY_COL
		** then turn off the COL_AUTO_IDENTITY bit (0x2).
		** Note that we can never rename a column to
		** SYB_IDENTIY_COL (since valid_name() will fail)
		** so don't worry about the converse.
		*/
		if (@colname = "SYB_IDENTITY_COL")
		begin
			update syscolumns
				set status = (~2 & status)
					from syscolumns
				where id = @objid
					and colid = @colid
		end

		/*
		** Write the log record to replicate this invocation 
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure '%1!'
			** 	   in database '%2!' was aborted because there
			** 	   was an error in writing the replication log
			**	   record."
			*/
			select @dbname = db_name()
			raiserror 17756, "sp_rename", @dbname
				
			rollback transaction rs_logexec
			return(1)
		end

		/* commit the transaction */
		commit transaction

		/*
		** 17781, "Column name has been changed."
		*/
		exec sp_getmessage 17781, @msg output
		print @msg
		/*
		** 19819  "Warning: Changing an object or column name may 
		** break existing stored procedures, cached statements or 
		** other compiled objects."
		*/
		exec sp_getmessage 19819, @msg output
		print @msg
		return (0)
	end

	/*
	**  Might be an index name.
	*/
	else
	begin
		/*
		**  We have already obtained the objid from sysindexes.
		*/
		select @objid = @index_objid

		/*
		**  If @objid is still NULL then that means it isn't an
		**  index name.  We checked above to see if it was a column
		**  name so now it's time to give up.
		*/
		if @objid is null
		begin
			/*
			** 17782, "You do not own a table or column (or index) of that name in the current database."
			*/
			raiserror 17782
			return (1)
		end

		/*
		**  Check to make sure that there is no already an index
		**  that has the new name.
		*/
		if exists (select *
				from sysindexes
					where id = @objid
						and name = @newname
						and indid > 0)
		begin
			/*
			** 17783, "There is already an index named '%1!' for table '%2!'."
			*/
			raiserror 17783, @newname, @tabname
			return (1)
		end

		/*
		** IMPORTANT: The name rs_logexec is significant
		** and is used by Replication Server. 
		*/
		begin transaction rs_logexec

		/*
		**  Go ahead and change the index name.
		*/
		update sysindexes
		set name = @newname
		from sysindexes
		where id = @objid and indid = @colid
		plan "(update (i_scan csysindexes sysindexes))"

		/*
		** We updated a sysindexes row. We also need to update the
		** in-core structure representing this sysindexes row as the
		** sysindexes rows cache is not a write thru cache. 
		*/ 
		select @temp_dbid = db_id()

		dbcc refreshides(@temp_dbid, @objid, @colid, "indname")
		
		/* 
		** If there was a error in rollback the update to sysindexes.
		** dbcc refreshides would have printed the error message.
		*/
		if @@error != 0
		begin
			rollback transaction rs_logexec
			return (1)
		end

		/*
		** Write the log record to replicate this invocation 
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure '%1!'
			** 	   in database '%2!' was aborted because there
			** 	   was an error in writing the replication log
			**	   record."
			*/
			select @dbname = db_name()
			raiserror 17756, "sp_rename", @dbname
				
			rollback transaction rs_logexec
			return(1)
		end

		commit transaction 
		/*
		** 17784, "Index name has been changed."
		*/
		exec sp_getmessage 17784, @msg output
		print @msg
		return (0)
	end
end

/*
**  Check to see if the object exists and is owned by the user.
**  It will either be in the sysobjects table or the systypes table.
**  Check sysobjects first.
**  System objects have ids < 100 and we don't allow their names to change.
*/
if exists (select id
	from sysobjects
		where id = object_id(@objname)
			and uid = user_id()
			and id > 99)
/*
**  Don't allow the newname to begin with #.
*/
begin
	if substring(@newname, 1, 1) = "#"
	begin
		/*
		** 17785, "Table or view names beginning with '#' are not allowed."
		*/
		raiserror 17785
		return (1)
	end
end

/*
**  It's not in sysobjects so check systypes.
*/
else
begin
	select @objid = usertype
		from systypes
			where name = @objname
				and uid = user_id()
				and usertype > 99

	/*
	**  It's nowhere to be found so quit.
	*/
	if @objid is NULL
	begin
		/*
		** 17786, "Object name cannot be changed either because it does not exist in this database, or you don't own it, or it is a system name."
		*/
		raiserror 17786
		return (1)
	end

	/* Check that newname doesn't already exist. */
	if exists (select *
			from systypes
				where name = @newname)
	begin
		/*
		** 17787, "Newname already exists in systypes."
		*/
		raiserror 17787
		return (1)
	end

	/*
	** IMPORTANT: This transaction name is significant and is used by
	**            Replication Server
	*/
	begin transaction rs_logexec
	
		/*
		** Change the name of a datatype
		*/
		update systypes
			set name = @newname
			where usertype = @objid

		/*
		** Write the log record to replicate this invocation 
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure '%1!'
			** 	   in database '%2!' was aborted because there
			** 	   was an error in writing the replication log
			**	   record."
			*/
			select @dbname = db_name()
			raiserror 17756, "sp_setreptable", @dbname
				
			rollback transaction rs_logexec
			return(1)
		end
	commit transaction

	/*
	** 18058, "Name of user-defined type name changed."
	*/
	exec sp_getmessage 18058, @msg output
	print @msg
	return (0)
end

/*
**  It might be a table so update the index entry for the table IF it has
**  no clustered index.  No clustered index means that there is an entry
**  for the table under the @objid with indid = 0.
*/

/* Check that newname doesn't already exist. */
if exists (select *
		from sysobjects
			where name = @newname
			and uid = user_id())
begin
	/*
	** 17788, "Newname already exists in sysobjects."
	*/
	raiserror 17788
	return (1)
end

/*
** IMPORTANT: This transaction name is significant and is used by
**            Replication Server
*/
begin transaction rs_logexec

	/* if the object is a table or a procedure, we may have to log its
	** schema before/after changing its name
	*/
	if exists (
		    select id 
		    from sysobjects where
			(type = "U" or type = "P" or type = "WS") and 
			name = @objname
		  )
	begin
		select @table_or_proc = 1
	end
	else
	begin
		select @table_or_proc = 0
	end

	/* 
	** Is the object a service?
        */

        if exists (
			select id 
 			from sysobjects where 
				type = "WS" and
                                name = @objname
                  )
        begin
		/*
		** Lock the specific row in the sysattributes table to 
		** avoid race conditions with sp_webservices deploy and
		** undeploy.
		*/

		select @temp_objid=object from sysattributes holdlock where 
			class = 18 and
			attribute = 6 and
			object = object_id(@objname)

		/*
		** If the service is deployed do not allow the rename 
		** to go through. 
		*/

		if exists (
				select object_info3 from sysattributes where
					object = object_id(@objname) and
					class = 18 and
					attribute = 6 and
					object_info3 & 128 = 128
			   )
		begin
			/*
			** 19412, "Cannot rename a service that is deployed. "
			*/

			raiserror 19412 
		    	rollback transaction rs_logexec
			return(1)
		end
        end

	/* determine the object's replication status if it is a table or
	** a procedure and log its schema if necessary
	*/
	if (@table_or_proc = 1)
	begin

		/* Replication enabled flag is 8000H (which is -32768D) */
		select @rep_constant = -32768

		select
			@cur_sysstat = sysstat
		from
			sysobjects holdlock
		where
			id = object_id(@objname) 

		if (@cur_sysstat & @rep_constant) = @rep_constant
		begin
			select @rep_obj = 1
		end
		else
		begin
			select @rep_obj = 0
		end

		/* check if db is replicated */
		select @rep_db_stat = getdbrepstat()
		if (@rep_db_stat = @lt_rep_get_failed)
		begin
        		/*
        		** 18409, "The built-in function getdbrepstat() 
			** failed. Please see the other messages printed 
			** along with this message."
        		*/
			raiserror 18409
			rollback transaction rs_logexec
        		return (1)
		end
		else
		begin
			if ((@rep_db_stat & @lt_rep_all = @lt_rep_all) or
			    (@rep_db_stat & @lt_rep_l1 = @lt_rep_l1))
				select @rep_db = 1
			else
				select @rep_db = 0
		end

		/*
		** if db is replicated, and object is user table, then the
		** user table is replicated even if it is not explicitly
		** marked for replication
		*/
		if ((@rep_obj = 0) and (@rep_db = 1))
		begin
			if exists (
				select id from
					sysobjects where
					(type = "U") and
					(id = object_id(@objname))
				  )
			begin
				select @rep_obj = 1
			end
		end

		if (@rep_obj = 1)
		begin
			select @user_tran = 0
			select @after_image = 0
			select @mod_versionts = 1
			if (logschema(object_id(@objname), @user_tran, 
					@after_image, @mod_versionts) != 1)
			begin
				/*
				** 17968 "The built-in function logschema() 
				** failed for '%1!'."
				*/
				raiserror 17968, @objname

				rollback transaction rs_logexec
				return(1)
			end
		end
	end

	/*
	** Update schema count for this table or view.
	*/
	select @obj_type = type 
	from sysobjects where id = object_id(@objname)

	if (@obj_type = 'U' or @obj_type = 'V') 
	begin
		if (schema_inc(object_id(@objname), 2) != 1)
        	begin
			/*
			** 17763, "The execution of the stored procedure '%1!'
			**         in database '%2!' was aborted because there
			**         was an error in updating the column
			**         schemacnt in sysobjects."
			*/
			select @dbname = db_name()
			raiserror 17763, "sp_rename", @dbname
			rollback transaction rs_logexec
			return(1)
		end
	end

	update sysobjects
		set name = @newname
			where id = object_id(@objname)

	/*
	** If the object is a proxy table, update sysattributes
	*/
        update sysattributes
                set object_cinfo = @newname
                        where object_cinfo = @objname and class = 9

	 /*
	 **  This might not do anything -- only if we are dealing with a
	 **  table that has no clustered index.
	 **  Also change the name of the text entry, if any.
	 */
	update sysindexes
	set name = @newname
	where id = object_id(@objname) and indid = 0
	plan "(update (i_scan csysindexes sysindexes))"

	/*
	** We updated a sysindexes row. We also need to update the
	** in-core structure representing this sysindexes row as the
	** sysindexes rows cache is not a write thru cache. 
	*/ 
	select @temp_dbid = db_id()
	select @temp_objid = object_id(@objname)

	dbcc refreshides(@temp_dbid, @temp_objid, 0, "indname")

	/* dbcc refreshides would print a message in case of error */
	if @@error != 0
	begin
		rollback transaction rs_logexec
		return (1)
	end

	update sysindexes
	set name = "t" + @newname
	where id = object_id(@objname) and indid = 255
	plan "(update (i_scan csysindexes sysindexes))"

	/*
	** We updated a sysindexes row. We also need to update the
	** in-core structure representing this sysindexes row as the
	** sysindexes rows cache is not a write thru cache. 
	*/ 
	dbcc refreshides(@temp_dbid, @temp_objid, 255, "indname")

	/* dbcc refreshides would print a message in case of error */
	if @@error != 0
	begin
		rollback transaction rs_logexec
		return (1)
	end

	/*
	**	We also must update the object name in the descriptor
	**	otherwise, in the cache, the object would be under the
	**	old name.
	*/
	dbcc chgobjname(@objname, @newname)

	if @@error != 0
	begin
		rollback transaction rs_logexec
		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_rename", @dbname
				
		rollback transaction rs_logexec
		return (1)
	end

commit transaction

/*
** 17789, "Object name has been changed."
*/
exec sp_getmessage 17789, @msg output
print @msg

/*
** 19819  "Warning: Changing an object or column name may break existing stored procedures, cached statements or other compiled objects."
*/
exec sp_getmessage 19819, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_rename', 'anymode'
go
grant execute on sp_rename to public
go
exec sp_procxmode 'sp_rename', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_renamedb')
begin
	drop procedure sp_renamedb
end
go
print "Installing sp_renamedb"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/renamedb */

/*
** Messages for "sp_renamedb"           17790
**
** 17260, "Can't run %1! from within a transaction." 
** 17590, "The specified database does not exist."
** 17240, "'%1!' is not a valid name."
** 17791, "A database with the new name already exists."
** 17792, "The databases master, model, tempdb, sybsecurity, sybsystemprocs and mounted_sybsystemprocs cannot be renamed."
** 17793, "System Administrator (SA) must set database '%1!' to single-user mode with sp_dboption before using '%2!'."
** 17794, "Database is renamed and in single-user mode."
** 17795, "System Administrator (SA) must reset it to multi-user mode with sp_dboption."
** 17902, "You cannot run stored procedure '%1!' from a low durability database."
** 18850, "HA Error: Database '%1!' is a system proxy database. You must execute sp_renamedb on the primary server first."
** 18851, "HA Error: You must be in the master database in order to run '%1!' against a system proxy database."
** 18843, "Please check the System Administration Guide to determine how to %1! the corresponding proxy or real database on the companion server '%2!'."
*/



/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function db_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_renamedb
@dbname sysname(30),			/* old (current) db name */
@newname sysname(30)			/* new name we want to call it */
as

declare @msg varchar(1024)
declare @bitdesc varchar(30)		/* bit description for the db */
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @maxobjlen int
declare @rollback int

select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_renamedb', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_renamedb"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

/*
**  Make sure the database exists.
*/
if not exists (select *
		from master.dbo.sysdatabases
			where name = @dbname)
begin
	/*
	** 17590, "The specified database does not exist."
	*/
	raiserror 17590
	return (1)
end

/*
**  Make sure that the @newname db doesn't already exist.
*/
if exists (select *
		from master.dbo.sysdatabases
			where name = @newname)
begin
	/*
	** 17791, "A database with the new name already exists."
	*/
	raiserror 17791
	return (1)
end

/*
**  Check to see that the @newname is valid.
*/
select @maxobjlen = length from master.dbo.syscolumns 
	where id = object_id("master.dbo.sysdatabases")
	and name = 'name'

if valid_name(@newname,@maxobjlen) = 0
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @newname
	return (1)
end

/*
**  Don't allow the names of master, tempdb, and model to be changed.
*/
if @dbname in ("master", "model", "tempdb", "sybsecurity", "sybsystemprocs", "mounted_sybsystemprocs")
begin
	/*
	** 17792, "The databases master, model, tempdb, sybsecurity, 
	** sybsystemprocs and mounted_sybsystemprocs cannot be renamed."
	*/
	raiserror 17792
	return (1)
end


/* 
** Check single user bit (4096) 
** Database must be in single user mode to necessitate the rid update in the
** database's DBTABLE
*/ 
select @bitdesc = null 
select @bitdesc = v.name
        from master.dbo.spt_values v, master.dbo.sysdatabases d 
                where d.dbid = db_id(@dbname) 
                        and v.type = "D" 
                        and d.status & v.number = 4096 
if @bitdesc is null 
begin 
	/*
	** 17793, "System Administrator (SA) must set database '%1!' to single-user mode with sp_dboption before using '%2!'."
	*/
	raiserror 17793, @dbname, "sp_renamedb"
        return(1)  
end  



/* 
** This stored procedure can not be executed from a low durablity database
** as the changes made by follwoing 'dbcc chgdbname' can not be undone
** as the execution will not come back to stored procedure when error 
** 3952 happens. So we check if we are in a low durability database before
** starting execution of the stored procedure.
*/
if db_attr(db_name(), "durability") != 'full'
begin
	raiserror 17902, "sp_renamedb"
	return (1)
end

/*
**  Update the dbinfo in the sysindexes row for syslogs of the database
**  whose name is being changed. Also the dbtable structure for the db
**  in question is updated with the new name.
**
**  NOTE: the following dbcc command relies on the above commands executing.
**	  Using this command outside of this procedure can cause a host of
**  	  perfidious problems.
*/
dbcc chgdbname (@dbname, @newname)

if @@error = 0
begin
	select @rollback = 1
	begin tran rename_db
	update master.dbo.syslogins
		set dbname = @newname 
			where dbname = @dbname
	if @@error = 0
	begin
		update master.dbo.sysdatabases
			set name = @newname
				where name = @dbname
		if @@error = 0
		begin
			commit tran rename_db
			set @rollback = @@error
		end
	end
	
	if @rollback != 0
	begin
		rollback tran rename_db
		dbcc chgdbname (@newname, @dbname)
		return(1)
	end
end
else
	return (1)

/*
** 17794, "Database is renamed and in single-user mode."
*/
exec sp_getmessage 17794, @msg output
print @msg

/*
** 17795, "System Administrator (SA) must reset it to multi-user mode with sp_dboption."
*/
exec sp_getmessage 17795, @msg output
print @msg



return (0)
go
exec sp_procxmode 'sp_renamedb', 'anymode'
go
grant execute on sp_renamedb to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_serveroption')
begin
	drop procedure sp_serveroption
end
go
print "Installing sp_serveroption"
go

/* Sccsid = "%M% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */

/*
** Messages for "sp_serveroption"       17800
**
** 17260, "Can't run %1! from within a transaction." 
** 17800, "No such server -- run sp_helpserver to list servers."
** 17801, "Usage: sp_serveroption [server, {{security mechanism, mechname} | {server cost, value} | 
**	{optname, {true | false}}}]"
** 17802, "Server option doesn't exist or can't be set by user."
** 17803, "Run sp_serveroption with no parameters to see options."
** 17804, "Server option is not unique."
** 17806, "Option can be set for remote servers only -- not the local server."
** 17807, "Settable server options."
** 17809, "Confidentiality, integrity, and mutual authentication are \
**	   valid with rpc security model B only."
** 17431, "true"
** 17432, "false"
** 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
** 18686, "Server option 'server logins' cannot be set when @@servername is null"
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18780, "Server '%1!' is the companion server, therefore, synchronization is d
isallowed."
** 18782, "Unable to find a server with name '%1!' and id '%2!'."
** 18890, "Only the 'external engine auto start' option can be enabled for the 
** ejb class of servers."
** 19255, "The option '%s' can be set for '%s' server class only." 
** 19661, "Server '%1!' is not a cluster instance, can not set server option."
** 19662, "Server name '%1!' doesn't match with its netname '%2!', can not set server option."
** 19663, "Server '%1!' is a cluster instance, can not unset server option."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_serveroption
@server varchar(255) = NULL,		/* server name to change */
@optname varchar(30) = NULL,		/* option name to turn on/off */
@optvalue varchar(20) = NULL		/* true or false */
as

declare @srvid int			/* id of the server */
declare @inst_id int			/* cluster instance id */ 
declare @netname varchar(255)		/* server net name */
declare @srvstatus int			/* value of sysservers.srvstatus */
declare @srvstatus2 unsigned int        /* value of sysservers.srvstatus2 */
declare @srvclass smallint		/* class of the server */
declare @model_a_value smallint		/* value of security model A */
declare @model_b_value smallint		/* value of security model B */
declare @model_b1_value smallint	/* value of use msg confidentiality */
declare @model_b2_value smallint	/* value of use msg integrity */
declare @model_b3_value smallint	/* value of mutual authentication */
declare @statvalue smallint		/* number of option for srvstatus */
declare @statvalue2 unsigned int	/* number of option for srvstatus2 */
declare @optcount int			/* number of options like @optname */
declare @msg varchar(1024) 
declare @true varchar(30) 
declare @false varchar(30) 
declare @status int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int
declare @rowlimit int
declare	@outstr	varchar(255),	/* for SDC dbcc set_scope */
	@scope	varchar(16)	/* for SDC dbcc set_scope */

select @HA_CERTIFIED = 0


select @status = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_serveroption', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/* 
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_serveroption"
	return (1)
end

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
**  If no @server given, just list the possible server options.
**  Only certain status bits may be set or cleared.  
**  The default is to allow timeouts (bit 0 is clear) and to
**  perform no network password encryption (bit 1 is clear).
**	   settable                	    not settable
**      ------------------------------  --------------------------
**    0    timeouts
**    2    net password encryption
**    4    readonly
**    8    rpc security model A
**    16   rpc security model B
**    32   cis hafailover
**    64   use message confidentiality
**    128  use message integrity
**    256  mutual authentication
**    512  server logins
**    1024 external engine auto start
**    4096 negotiated logins
**	   security mechanism
**	   server cost
**
**  srvstatus2:
**
**	   settable                	    not settable
**      ------------------------------  --------------------------
**    1    relocated joins
**    2    enable login redirection	
**    4	   cluster instance
**    8    incompatible sort order
**
**
**  Notice that options "security mechanism" and "server cost"
**  are not represented by a bit of srvstatus and therefore
**  are no corresponding entries in spt_values for them.
**  Select the options from spt_values unioned with these options
**  into a temp table for use in this procedure.
*/
select @rowlimit = @@setrowcount	
set rowcount 0

select name into #server_options
		from master.dbo.spt_values where 
                        (type = "A" and number not in (-1, 1)) or type = "A2"
	union
	select "server cost"
	union
	select "security mechanism"

set rowcount @rowlimit

if @server is null
begin
	/* 17807, "Settable server options." */
	exec sp_getmessage 17807, @msg out
	print @msg
	select "" = name from #server_options order by 1
	return (0)
end

/*
**  Verify the server name and get the @srvid
*/
select @srvid = srvid
	from master.dbo.sysservers
		where srvname = @server

/*
**  If @server not found, say so. 
*/
if @srvid is NULL
begin
	/*
	** 17800, "No such server -- run sp_helpserver to list servers."
	*/
	raiserror 17800
	return (1)
end

/*
** Make sure only the 'external engine auto start option' can be used if the
** class of servers belong to the ASEJB class
*/
if exists (select 1 from master.dbo.sysservers where 
		srvname = @server and srvclass = 10)
begin
	if @optname not like "%external engine auto%"
	begin
		/*
		** 18890, "Only the 'external engine auto start' option can 
		** be enabled for the ejb class of servers."
		*/
		raiserror 18890
		return (1)
	end
end
else
begin
	/*
	** The server is not an EJB Server. 
	** The 'external engine auto start' option can only be set for EJB Servers. For all
	** other classes of servers, this is considered to be an invalid option.
	*/
	if @optname like "%external engine auto%"
	begin
		/*
		** 19255, "The option '%s' can be set for '%s' server class only."
		*/
		raiserror 19255, "external engine auto start", "EJB"
		return (1)
	end
end

		

/*
**  Check remaining parameters.
**  Note that "security mechanism" and "server cost" take a value instead of true or false
*/
/* 17431, "true" */
exec sp_getmessage 17431, @true out
/* 17432, "false" */
exec sp_getmessage 17432, @false out
if @optname is NULL or
	( @optname not like "%security me%" and @optname not like "%server c%"
	and lower(@optvalue) not in
	("true", "false", @true, @false) ) or
        ( @optname not like "%security me%" and @optvalue is null )
begin
	/*
	** 17801, "Usage: sp_serveroption [server, {{security mechanism, mechname} | 
	**         {server cost, value} | {optname, {true | false}}}]"
	*/
	raiserror 17801
	return (1)
end

/*
**  Use @optname and try to find the right option.
**  If there isn't just one, print appropriate diagnostics and return.
*/
select @optcount = count(*)
 	   from #server_options
		where name like "%" + @optname + "%"

/*
**  If no option, show the user what the options are.
*/
if @optcount = 0
begin
	/*
	** 17802, "Server option doesn't exist or can't be set by user."
	*/
	raiserror 17802
	/*
	** 17803, "Run sp_serveroption with no parameters to see options."
	*/
	exec sp_getmessage 17803, @msg output
	print @msg
	return (1)
end

/*
**  If more than one option like @optname, show the duplicates and return.
*/
if @optcount > 1
begin
	/*
	** 17804, "Server option is not unique."
	*/
	raiserror 17804

	select duplicate_option = name
		from #server_options
			where name like "%" + @optname + "%"

	return (1)
end

/*
**  Currently there are two options that can be set -- no timeouts and
**  net password encryption -- and both only apply to remote servers.  
**  If the current server is local then reject it.
*/
if @srvid = 0
begin
	/*
	** 17806, "Option can be set for remote servers only -- not the local server."
	*/
	raiserror 17806
	return (1)
end



if @optname like "%security me%"
begin
	if (proc_role("sso_role") < 1)
		return(1)
 
	update master.dbo.sysservers
		set srvsecmech = @optvalue
		where srvid = @srvid

	

	return (0)
end

/*
** Update the server cost
*/
if @optname like "%server c%"
begin
	/*
	** Changing the server cost requires SA role
	*/
	if (proc_role("sa_role") < 1)
		goto clean_all

	update master.dbo.sysservers
		set srvcost = convert(smallint, @optvalue)
		where srvid = @srvid

	

	/*
	** Update the srvdes
	** For SDC, update cluster-wide in-memory SRVDES with data from
	** just-updated SYSSERVERS table. Before dbcc cis, the dbcc
	** command scope needs to be set to cluster.
	*/
	if (@@clustermode = "shared disk cluster")
	begin
		select @scope = NULL
		select @outstr = "dbcc set_scope_in_cluster('scope')"
		if (charindex("instance", @outstr) != 0)
		begin
			/* save the scope to be restored later */
			select @scope = "instance"
			dbcc set_scope_in_cluster('cluster')
		end
	end

	dbcc cis ("srvdes", @srvid)

	/* restore dbcc command scope */
	if (@@clustermode = "shared disk cluster")
	begin
		if (@scope = "instance")
		begin
			dbcc set_scope_in_cluster('instance')
		end
	end

	return (0)
end

/*
**  Get the number which is the bit value to set in srvstatus2
*/
select @statvalue2 = number
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%" and type = "A2"
			and number > 0

/*
** Update serveroption in srvstatus2 field
**
** 	statvalue2	serveroption
**	---------	------------
**	   1		<reserved for "relocated joins" in 15.0.2>
**	   2		enable login redirection
**	   4		cluster instance
**
*/
if (@statvalue2 in (2, 4))
begin
	if (proc_role("sa_role") < 1)
		goto clean_all

        select @srvstatus2 = isnull(srvstatus2, 0) from master.dbo.sysservers
	        where srvid = @srvid 

        if lower(@optvalue) in ("true", @true)
        begin
		if (@statvalue2 = 4)
		begin
			select @inst_id = instance_id(@server)
			if @inst_id is NULL
			begin
				/*
				** 19661, "Server '%1!' is not a cluster instance, 
				** can not set server option."
				*/
				exec sp_getmessage 19661, @msg output
				print @msg, @server
				goto clean_all
			end
			select @netname=srvnetname from master.dbo.sysservers
				where srvid = @srvid
			if (@server != @netname)
			begin
				/*
				** 19662, "Server name '%1!' doesn't match with its netname '%2!', 
				** can not set server option."
				*/
				exec sp_getmessage 19662, @msg output
				print @msg, @server, @netname
				goto clean_all
			end
		end
		update master.dbo.sysservers
			set srvstatus2 = @srvstatus2 | @statvalue2
				where srvid = @srvid

        end
        else
        begin
		if (@statvalue2 = 4)
		begin
			select @inst_id = instance_id(@server)
			if @inst_id is not NULL
			begin
				/*
				** 19663, "Server '%1!' is a cluster instance, 
				** can not unset server option."
				*/
				exec sp_getmessage 19663, @msg output
				print @msg, @server
				goto clean_all
			end
		end
                update master.dbo.sysservers
			set srvstatus2 = @srvstatus2 & ~@statvalue2
				where srvid = @srvid

        end

	/*
	** Update the srvdes
	** For SDC, update cluster-wide in-memory SRVDES with data from
	** just-updated SYSSERVERS table. Before dbcc cis, the dbcc
	** command scope needs to be set to cluster.
	*/
	if (@@clustermode = "shared disk cluster")
	begin
		select @scope = NULL
		select @outstr = "dbcc set_scope_in_cluster('scope')"
		if (charindex("instance", @outstr) != 0)
		begin
			/* save the scope to be restored later */
			select @scope = "instance"
			dbcc set_scope_in_cluster('cluster')
		end
	end

	dbcc cis ("srvdes", @srvid)

	/* restore dbcc command scope */
	if (@@clustermode = "shared disk cluster")
	begin
		if (@scope = "instance")
		begin
			dbcc set_scope_in_cluster('instance')
		end
	end

        return (0)
end

/*
** Update srvstatus2 field values
**    1    relocated joins 
**    8    incompatible sort order
*/
if (@optname like "%rel%" or @optname like "%inc%")
begin
	/*
	**  Get the number which is the bit value to set
	*/
	select @statvalue2 = number
		   from master.dbo.spt_values
			where name like "%" + @optname + "%" and type = "A2"
				and number > 0
	/*
	** Changing 'relocated joins' or 'incompatible sort order' requires SA role
	*/
	if (proc_role("sa_role") < 1)
		goto clean_all

        select @srvstatus2 = isnull(srvstatus2, 0) from master.dbo.sysservers
	        where srvid = @srvid 

        if lower(@optvalue) in ("true", @true)
        begin
		update master.dbo.sysservers
			set srvstatus2 = @srvstatus2 | @statvalue2
				where srvid = @srvid

        end
        else
        begin
                update master.dbo.sysservers
			set srvstatus2 = @srvstatus2 & ~@statvalue2
				where srvid = @srvid

        end

	/*
	** Update the srvdes
	*/
	dbcc cis ("srvdes", @srvid)

        return (0)
end


/*
**  Get the number which is the bit value to set
*/
select @statvalue = number
 	   from master.dbo.spt_values
		where name like "%" + @optname + "%" and type = "A"
			and number > 0

/*
** OMNI: If we're setting server logins, dissallow
** when @@servername is null
*/
if @statvalue = 512 and @@servername is NULL
begin
	/*
	** 18686, "Server option 'server logins' cannot be set 
	**	when @@servername is null"
	*/
	exec sp_getmessage 18686, @msg output
	print @msg
	goto clean_all
end
 
/* 
** Check for SSO options:
**
** value       : 2    net password encryption
** value       : 8    rpc security model A
** value       : 16   rpc security model B
** value       : 64   use message confidentiality
** value       : 128  use message integrity
** value       : 256  mutual authentication
** value       : 512  server logins
** value       : 4096 negotiated logins
*/
if (@statvalue in (2, 8, 16, 64, 128, 256, 512, 4096))
begin
        if (proc_role("sso_role") < 1)
                goto clean_all
end


/*
** Check for HA options 
**
** value       : 32   cis hafailover
*/
else if( @statvalue in (32))
begin
        if (proc_role("ha_role") < 1)
                goto clean_all
end

/*
** For any other option check for SA role
** 
** Currently the following are left
**
** value       : 0    timeouts
** value       : 4    readonly
** value       : 1024 external engine auto start
*/
else 
begin
	if (proc_role("sa_role") < 1)
		goto clean_all
end


select @model_a_value = number from master.dbo.spt_values
	where type = "A" and name = "rpc security model A"
select @model_b_value = number from master.dbo.spt_values
	where type = "A" and name = "rpc security model B"
select @model_b1_value = number from master.dbo.spt_values
	where type = "A" and name = "use message confidentiality"
select @model_b2_value = number from master.dbo.spt_values
	where type = "A" and name = "use message integrity"
select @model_b3_value = number from master.dbo.spt_values
	where type = "A" and name = "mutual authentication"

select @srvstatus = srvstatus from master.dbo.sysservers
	where srvid = @srvid 

if ( (@statvalue = 64 or @statvalue = 128 or @statvalue = 256) )
begin
	if ( (@srvstatus & @model_b_value) = 0 )
	begin
		/*
		** <msgnum> confidentiality, integrity, and mutual
		** authentication are valid with rpc security model B only.
		*/
		raiserror 17809
		goto clean_all
	end
end

/*
**  Now update sysservers.
**  The timeouts option is handled a little strangely since the default
**  is timeouts.  Therefore timeouts = true means to clear the bit
**  and timeouts = false means to set the bit.
*/



if lower(@optvalue) in ("true", @true)
begin
	if (@statvalue = 1)
	begin
		update master.dbo.sysservers
			set srvstatus = srvstatus & ~@statvalue
				where srvid = @srvid

	end
	else
	begin
		if ( @statvalue = 8 or @statvalue = 16 or @statvalue = 32 )
		begin
			/*
			** confidentiality, integrity, and mutual authentication
			** are reset whenever "rpc security model X" is reset.
			** Also because models A, B, and C are mtutally
			** exclusive, when when one of them is turned on,
			** other two will be turned off.
			*/
			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b1_value
					where srvid = @srvid


			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b2_value
					where srvid = @srvid


			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b3_value
					where srvid = @srvid


			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_a_value
					where srvid = @srvid


			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b_value
					where srvid = @srvid

		end
		update master.dbo.sysservers
			set srvstatus = srvstatus | @statvalue
				where srvid = @srvid

	end
end

/*
**  We want to turn it off.
*/
else
begin
	if @statvalue = 1
	begin
		update master.dbo.sysservers
			set srvstatus = srvstatus | @statvalue
				where srvid = @srvid

	end
	else
	begin
		if ( @statvalue = 8 or @statvalue = 16 or @statvalue = 32 )
		begin
			/* model A is the default */
			update master.dbo.sysservers
				set srvstatus = srvstatus | @model_a_value
				where srvid = @srvid

                end

		update master.dbo.sysservers
			set srvstatus = srvstatus & ~@statvalue
				where srvid = @srvid


		if (@statvalue = 16)	
		/* 
		** if model B bit is turned off then turn off 
		** b1, b2, and b3 too.
		*/
		begin
			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b1_value
					where srvid = @srvid


			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b2_value
					where srvid = @srvid


			update master.dbo.sysservers
				set srvstatus = srvstatus & ~@model_b3_value
					where srvid = @srvid

		end
	end
end




/*
** OMNI: If net password encryption, readonly, hafailover, server login or
** negotiated logins option is specified, update the srvdes
*/
if @statvalue in (2,4,32,512,4096)
begin
	/*
	** For SDC, update cluster-wide in-memory SRVDES with data from
	** just-updated SYSSERVERS table. Before dbcc cis, the dbcc
	** command scope needs to be set to cluster.
	*/
	if (@@clustermode = "shared disk cluster")
	begin
		select @scope = NULL
		select @outstr = "dbcc set_scope_in_cluster('scope')"
		if (charindex("instance", @outstr) != 0)
		begin
			/* save the scope to be restored later */
			select @scope = "instance"
			dbcc set_scope_in_cluster('cluster')
		end
	end

	dbcc cis ("srvdes", @srvid)

	/* restore dbcc command scope */
	if (@@clustermode = "shared disk cluster")
	begin
		if (@scope = "instance")
		begin
			dbcc set_scope_in_cluster('instance')
		end
	end
end

return (0)

clean_all:



return (1)
go
exec sp_procxmode 'sp_serveroption', 'anymode'
go
grant execute on sp_serveroption to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_serverinfo')
begin
	drop procedure sp_serverinfo
end
go
print "Installing sp_serverinfo"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_serverinfo"         17796
**
** 17796, "Legal request codes are as follows:"
*/

create procedure sp_serverinfo
@request	varchar(30) = NULL,
@arg1		varchar(255) = NULL,	/* optional arg1 */
@arg2		varchar(30) = NULL,	/* optional arg2 */
@arg3		varchar(30) = NULL,	/* optional arg3 */
@arg4		varchar(30) = NULL,	/* optional arg4 */
@arg5		varchar(30) = NULL,	/* optional arg5 */
@arg6		varchar(30) = NULL,	/* optional arg6 */
@arg7		varchar(30) = NULL,	/* optional arg7 */
@arg8		varchar(30) = NULL,	/* optional arg8 */
@arg9		varchar(30) = NULL	/* optional arg9 */
as

declare @csid		int		/* character set id */
declare @soid		int		/* sort order id */
declare @msg            varchar(1024)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

if (@request is null  or  @request = "help")
begin
	/*
	** 17796, "Legal request codes are as follows:"
	*/
	exec sp_getmessage 17796, @msg output
	print @msg
	print "    server_csname"
	print "    server_soname"
	print "    csdefinition"
	print "    sodefinition"
	print "	   client_csexpansion"
	return (9)
end

if (@request = "server_csname")
    begin
	/*
	** User wants the name of the server's default character set.
	** No additional arguments required.
	*/
	select @csid = value
	from master.dbo.syscurconfigs
	where config = 131

	select name
	from master.dbo.syscharsets
	where id = @csid and type between 1000 and 1999

	return (0)
    end
else if (@request = "server_soname")
    begin
	/*
	** User wants the name of the server's default sort order.
	** No additional arguments required.
	*/
	select @soid = value
	from master.dbo.syscurconfigs
	where config = 123

	select @csid = value
	from master.dbo.syscurconfigs
	where config = 131

	select name
	from master.dbo.syscharsets
	where id = @soid and csid = @csid and type between 2000 and 2999

	return (0)
    end
else if (@request = "csdefinition")
    begin
	/*
	** User wants the type, id, and definition (IMAGE field) of the
	** character set specified in "@arg1".
	*/
	select @csid = id
	from master.dbo.syscharsets
	where name = @arg1

	set textsize 32768

	select type, id, definition
	from master.dbo.syscharsets
	where id = @csid and type between 1000 and 1999

	return (0)
    end
else if (@request = "sodefinition")
    begin
	/*
	** User wants the name of the server's character set.
	** No additional arguments required.
	*/
	/*
	** User wants the definition (IMAGE field) of the sort order which
	** is the logical equivalent to the server's default sort order,
	** except based on the character set specified in "@arg1".
	*/
	select @soid = value
	from master.dbo.syscurconfigs
	where config = 123

	select @csid = id
	from master.dbo.syscharsets
	where name = @arg1 and type between 1000 and 1999

	select definition
	from master.dbo.syscharsets
	where id = @soid and csid = @csid and type between 2000 and 2999

	return (0)
    end
else if (@request = "client_csexpansion")
    begin
	/*
	** User wants the expansion factor from server to client.
	** No additional arguments required.
	*/

	select @@client_csexpansion

	return (0)
    end
else
    begin
	/*
	** Unknown request code.
	*/
	return (1)
    end
go
exec sp_procxmode 'sp_serverinfo', 'anymode'
go
grant execute on sp_serverinfo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_server_info')
begin
	drop procedure sp_server_info
end
go
print "Installing sp_server_info"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_server_info"
**
** 18059, "Attribute id %1! is not supported."
*/

create procedure sp_server_info
@attribute_id int = NULL		/* optional attribute id */
as


set nocount on

/* If an attribute id was specified then just return the info for that
** attribute.
*/
if @attribute_id is not null
begin
	/* Verify that the attribute is valid. */
	if not exists ( select attribute_id 
		from sybsystemprocs.dbo.spt_server_info
			where attribute_id = @attribute_id )
	begin
		/*
		** 18059, "Attribute id %1! is not supported."
		*/
		raiserror 18059, @attribute_id
		return (1)
	end

	select * 
	from sybsystemprocs.dbo.spt_server_info
	where attribute_id = @attribute_id
end

/* If no attribute was specified then return info for all supported
** attributes.
*/
else
begin
	select * 
	from sybsystemprocs.dbo.spt_server_info
end

return (0)
go
exec sp_procxmode 'sp_server_info', 'anymode'
go
grant execute on sp_server_info to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inform')
begin
	drop procedure sp_inform
end
go
print "Installing sp_inform"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** A Microsoft catalog stored procedure is named sp_server_info, too
** close to the Sybase internal stored proc "sp_serverinfo".  Since
** Sybase's sp_serverinfo has not been documented to customers, this new
** stored procedure simply calls sp_serverinfo.  This new procedure
** should replace sp_serverinfo eventually in Sybase products and could
** be exposed to customers at any time.
*/

create procedure sp_inform
@request	varchar(30) = NULL,
@arg1		varchar(30) = NULL,	/* optional arg1 */
@arg2		varchar(30) = NULL,	/* optional arg2 */
@arg3		varchar(30) = NULL,	/* optional arg3 */
@arg4		varchar(30) = NULL,	/* optional arg4 */
@arg5		varchar(30) = NULL,	/* optional arg5 */
@arg6		varchar(30) = NULL,	/* optional arg6 */
@arg7		varchar(30) = NULL,	/* optional arg7 */
@arg8		varchar(30) = NULL,	/* optional arg8 */
@arg9		varchar(30) = NULL	/* optional arg9 */
as

declare @re_request	varchar(30)
declare @re_arg1	varchar(30)
declare @re_arg2	varchar(30)
declare @re_arg3	varchar(30)
declare @re_arg4	varchar(30)
declare @re_arg5	varchar(30)
declare @re_arg6	varchar(30)
declare @re_arg7	varchar(30)
declare @re_arg8	varchar(30)
declare @re_arg9	varchar(30)
declare @retval		int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

select @re_request = @request
select @re_arg1 = @arg1
select @re_arg2 = @arg2
select @re_arg3 = @arg3
select @re_arg4 = @arg4
select @re_arg5 = @arg5
select @re_arg6 = @arg6
select @re_arg7 = @arg7
select @re_arg8 = @arg8
select @re_arg9 = @arg9
select @retval = 1

execute @retval = sp_serverinfo @request = @re_request, 
	@arg1 = @re_arg1, @arg2 = @re_arg2, @arg3 = @re_arg3, 
	@arg4 = @re_arg4, @arg5 = @re_arg5, @arg6 = @re_arg6, 
	@arg7 = @re_arg7, @arg8 = @re_arg8, @arg9 = @re_arg9

return @retval
go
exec sp_procxmode 'sp_inform', 'anymode'
go
grant execute on sp_inform to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setreplicate')
begin
	drop procedure sp_setreplicate
end
go
print "Installing sp_setreplicate"
go

/*
** Generated by spgenmsgs.pl on Wed Feb  8 14:55:58 2006 
*/
/*
** raiserror Messages for setreplicate [Total 11]
**
** 17460, "Object must be in the current database."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17961, "Usage: sp_setreplicate object_name, {true | false}"
** 17962, "The replication status for '%1!' is already set to %2!. Replication status for '%3!' does not change."
** 17963, "An object with the same name, but owned by a different user is already being replicated.  The object '%1!' cannot be replicated."
** 17966, "Due to system failure, the replication status for '%1!' has not been changed."
** 17969, "No user table or procedure named '%1!' exists in the current database."
** 18409, "The built-in function '%1!' failed. Please see the other messages printed along with this message."
** 18410, "The replication status of '%1!' is corrupt. Please contact Sybase Technical Support."
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) or a user with REPLICATION authorization may execute this stored procedure."
** 18688, "Stored procedures with object parameters cannot be marked for replication yet at this time. Instead, use sp_setreptable to mark the invidual tables for replication. The replication status for '%1!' is not changed."
*/
/*
** sp_getmessage Messages for setreplicate [Total 5]
**
** 17431, "true"
** 17432, "false"
** 17964, "The replication status for '%1!' is set to %2!."
** 17965, "The replication status for '%1!' is currently %2!."
** 17968, "The built-in function logschema() failed for '%1!'. See the other messages printed along with this message for more information."
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_setreplicate
@replicate_name	varchar(767) = NULL,	/* obj we want to mark as replicate */
@setflag 	varchar(5) = NULL	/* set or unset the replicate status. */
as

declare @current_status	int /* current sysstat value for the object. */
declare @new_status	int /* new sysstat value for the object. */
declare @new_status2	int /* new sysstat2 value for the object. */
declare @rep_constant 	smallint /* bit which indicates a replicated object. */
declare @dbccbit	int	 /* The "on"/"off" bit for the DBCC command */
declare @db		varchar(255) 	/* db of object. */
declare @owner		varchar(255) 	/* owner of object. */
declare @object		varchar(255)	/* object's name. */
declare @true		varchar(30)
declare @false		varchar(30)
declare @msg 		varchar(1024)
declare @tmpstr		varchar(10)
declare @sptlang	int
declare @procval	int
declare @rep_on_schema	int	/* log schema when turning replication on? */ 
declare @rep_off_schema	int	/* log schema when turning replication off? */ 
declare @objid		int
declare @user_tran	int	/* are we inside a user tran? */
declare @after_image	int	/* log the after image of the schema */
declare @mod_versionts	int	/* modify version timestamp after logging
				** the schema
				*/
declare @dbname varchar(255)
declare @tmpid		int	/* Temporary variable for check to make
				** sure that the object is a user table
				** or a procedure	
				*/
declare @curstat            int
declare @reptostandbyon     int  /* 1:  there are standby server */
declare @db_rep_level_all   int  /* All level replication */
declare @db_rep_level_none  int  /* no replication */
declare @db_rep_level_l1    int  /* L1 level replication */
declare @xtype_token	    int	 /* Type for object paramters. */
declare @owner_bit	    int
declare @index_bit	    int  
declare @colrepalwys	    smallint /* Always replicate */
declare @colrepifch         smallint /* Replicate if changed */
declare @tipsa_in_index     smallint /* Use index on text columns */
declare @texttype           smallint /* Text datatype */
declare @imagetype          smallint /* Image datatype */
declare @unitexttype        smallint /* UNITEXT type. */
declare @xtype_type         smallint /* Java column */
declare @offrow             smallint
declare @lt_rep_get_failed  int
declare @lt_rep_all	    int
declare @lt_rep_l1	    int


if @@trancount = 0
begin
	set chained off
end

if (@@trancount > 0)
	select @user_tran = 1
else
	select @user_tran = 0 

set transaction isolation level 1

/*
** Replication enabled flag is 8000H (which is -32768D)
*/
select @rep_constant = -32768

/* set @rep_on_schema and rep_off_schema to false initially */
select  @rep_on_schema = 0,
	@rep_off_schema = 0,
        @db_rep_level_all = -1, /* -1: code for all level replication */
	@db_rep_level_l1 = 1,   /* 1:  code for L1 level replication */
	@index_bit = 8388608,	/* 0x800000 in sysstat2 */
	@owner_bit = 4096,	/* 0x1000 in sysstat2 */
	@colrepalwys  = 1,
	@colrepifch = 2,
	@tipsa_in_index = 2048,
	@imagetype = 34,
	@texttype = 35,
	@xtype_type = 36,
	@unitexttype = 174,
	@offrow = 1,
	@lt_rep_get_failed = -2,/* LT_GET_REP_FAILED */
	@lt_rep_all = 2048,	/* LT_REP_ALL */
	@lt_rep_l1 = 4096	/* LT_REP_L1 */


/*
** Datatype value for object parameters is 36.
*/
select @xtype_token = 36

/*
** Initialize 'true' and 'false' strings
*/
/* 17431, "true" */
exec sp_getmessage 17431, @true out
/* 17432, "false" */
exec sp_getmessage 17432, @false out

/*
** Set 'sptlang' for proper printing of object information.  Used mainly
** for the 'select' statement which is executed when we are invoked with
** no parameters.  Copied from similar code in 'sp_help'
*/
select @sptlang = @@langid
if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	    select @sptlang = 0
end

/*
** If we are invoked with no parameters, then just print out all objects
** which are marked for replication.  The 'select' statement is heavily
** based upon the one found in 'sp_help'.
*/
if (@replicate_name is NULL and @setflag is NULL)
begin
	select
		Name = o.name,
		Type = convert(char(16), m.description + x.name)
	into #show_replicate_obj
	from
		sysobjects o,
		master.dbo.spt_values v,
		master.dbo.spt_values x,
		master.dbo.sysmessages m
	where 
		o.sysstat & 2055 = v.number
		and v.type = "O"
		and v.msgnum = m.error
		and isnull(m.langid, 0) = @sptlang
		and m.error between 17100 and 17109
		and x.type = "R"
		and o.userstat & -32768 = x.number
		and (o.sysstat & @rep_constant) = @rep_constant

	exec sp_autoformat #show_replicate_obj
	
	drop table #show_replicate_obj
	
	return (0)
end

/*
** Crack the name into its corresponding pieces.
*/
execute sp_namecrack 	@replicate_name, 
			@db = @db output, 
			@owner = @owner output,
			@object = @object output

/*
** Make sure that the object is in the current database.
*/
if (@db is not NULL and @db != db_name())
begin
	/*
	** 17460, "Object must be in the current database."
	*/
		raiserror 17460
	return (1)
end

/*
**  Make sure that the object actually exists.
*/
select @objid = object_id(@replicate_name)

/* Check if the object is either a procedure or user table */
select @tmpid = id from sysobjects
	where id = @objid and type in ("P","U")

/* Error if the object does not exist or if it is not a user table or
** procedure. 
*/
if (@objid is NULL) or (@objid != @tmpid)
begin
	/*
	** 17969, "No user table or procedure named '%1!' exists in the
	** 	   current database."
	*/
	raiserror 17969, @object
	return (1)
end

/*
** Currently, marking for replication user tables in the 'master' database
** is not allowed.
**
** Therefore, if the current database is the 'master' database and the
** object is a user table, reset the '@setflag' to NULL so that the system
** procedure will report the current status of the user table.  A proper
** error message should be implemented at a later date.
*/
if ((db_name() = "master") and
    exists(select * from sysobjects where name = @object and type = "U"))
begin
	select @setflag = NULL
end

/*
** If the 'setflag' parameter is NULL, then we are only interested in the
** current replication status of the specified object.
*/
if (@setflag is NULL)
begin
	select
		@current_status = sysstat
	from 
		sysobjects holdlock
	where 
		id = @objid 

	if (@current_status & @rep_constant) = @rep_constant
	begin
		select @tmpstr = @true
	end
	else
	begin
		select @tmpstr = @false
	end

	/*
	** 17965 "The replication status for '%1!' is currently %2!."
	*/
	exec sp_getmessage 17965, @msg output
	print @msg, @replicate_name, @tmpstr

	return (0)
end

/*
** You must be SA, dbo or have REPLICATION role to execute this
** sproc.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("replication_role", show_role()) = 0)
	begin
		/*
		** 18418, "Only the System Administrator (SA), the
		**	   Database Owner (dbo) or a user with REPLICATION
		**	   authorization may execute this stored
		**	   procedure."
		*/
		raiserror 18418
		return (1)
	end
	else
	begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
	end
end

/*
** Check for a valid setname parameter
*/
if (lower(@setflag) not in ("true", "false", @true, @false))
begin
	/*
	** 17961 "Usage: sp_setreplicate object_name, {true | false}"
	*/
	raiserror 17961
	return (1)
end

select @curstat = getdbrepstat(),
	@dbname = db_name()
 
/*
** Perform sanity checks on the returned value
** getdbrepstat() return current status of replication server. Check returned
** message, system supports only L1 and All level replication.   
*/
if (@curstat = @lt_rep_get_failed)
begin
        /*
        ** 18409, "The built-in function getdbrepstat() failed. Please
        ** see the other messages printed along with this message."
        */
        raiserror 18409, "getdbrepstat"
        return (1)
end
 
if ((@curstat & @lt_rep_all = @lt_rep_all) or
	(@curstat & @lt_rep_l1 = @lt_rep_l1))
begin
        select @reptostandbyon = 1
end
else
begin
        select @reptostandbyon = 0
end

/*
** Get the object's current status. Hold a read lock on sysobjects so that 
**	the status cannot be changed until we're done.
*/
select @current_status = sysstat , @new_status2 = sysstat2
	from sysobjects holdlock
		where id = @objid 

/*
** Perform the requested operation on the object.
*/
if lower(@setflag) in ("false", @false)
begin
	/*
	** Is the replicate status bit even set?
	*/
	if (@current_status & @rep_constant) = 0
	begin
		/*
		** 17962 "The replication status for '%1!' is already
		**	  set to %2!.  Replication status for '%3!'
		**	  does not change."
		*/
		raiserror 17962, @replicate_name, @setflag, @replicate_name
		return(1)
	end

	select @new_status = @current_status & ~@rep_constant
	select @new_status2 = @new_status2 & ~ (@owner_bit | @index_bit)
	select @dbccbit = 0
	select @rep_off_schema = 1
end
else
begin
	/*
	** We are turning on replication
	**
	** Is the replicate status bit already set?
	*/
	if (@current_status & @rep_constant) != 0
	begin
		/*
		** 17962 "The replication status for '%1!' is already
		**	  set to %2!.  Replication status for '%3!'
		**	  does not change."
		*/
		raiserror 17962, @replicate_name, @setflag, @replicate_name
		return(1)
	end

	/*
	** Make sure that no like object with the same name, but a
	** different owner, exists.  We need to do this because
	** the SQL Server does not send owner information along
	** with the object to the Replication Server.  This
	** restriction may be lifted in future versions.
	*/
	if exists (select * from sysobjects
			where name = @object
			and (
				(type = "U ") /* user table */
			or
				(type = "P ") /* stored procedure */
			)
			and sysstat & @rep_constant != 0)
	begin
		/*
		** 17963 "An object with the same name, but owned by a
		**	  different user is already being replicated.
		**	  The object '%1!' cannot be replicated."
		*/
		raiserror 17963, @replicate_name
		return(1)
	end

	/*
	** Disallow procedures that have object parameters, becuase.
	** replication of procedures with object parameters is not
	** supported yet.
	*/
	if exists (select A.name
		     from sysobjects A, syscolumns B
		    where A.name = @object
		      and A.type = "P"
		      and A.id   = B.id
		      and B.type = @xtype_token)
	begin
		/*
		** 18688, "Stored procedures with object parameters cannot be
		**         marked for replication yet at this time. Instead,
		**         use sp_setreptable to mark the invidual tables for
		**         replication. The replication status for '%1!' is
		**         not changed."
		*/
		raiserror 18688, @object
		return(1)
	end

	select @new_status = @current_status | @rep_constant
	select @dbccbit = 1
	select @rep_on_schema = 1
end

/*
** Update the object's sysstat column
**
** IMPORTANT: This transaction name is significant and is used by
**            Replication Server
*/
begin transaction rs_logexec

	/* log the schema first if we are turning off replication
         ** or standby server is running
         */
	if ((@rep_off_schema = 1) or (@reptostandbyon = 1))
	begin
		select @after_image = 0
		select @mod_versionts = 1
		if (logschema(@objid, @user_tran, @after_image, 
				@mod_versionts) != 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'."
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name   

			rollback transaction
			return(1)	
		end

		/* 
		** Update syscolumns status to remove any off-row replication
		** bit
		*/
		update syscolumns
		set status = status & ~(@colrepalwys | @colrepifch)
		where
		    id = @objid
		    and (type in (@imagetype, @texttype,  @unitexttype)
			 or (type = @xtype_type
			     and (xstatus & @offrow) = @offrow) )
	end

	update sysobjects set sysstat = @new_status,
			      sysstat2 = @new_status2 
	where id = @objid

	/* 
	** Log the schema now if we are turning on replication and we are
	** inside a user tran
	*/
	if ((@rep_on_schema = 1) and (@user_tran = 1))
	begin
		select @after_image = 1
		select @mod_versionts = 0
		if (logschema(@objid, @user_tran, @after_image, 
				@mod_versionts) != 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'."
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name   

			rollback transaction
			return(1)	
		end
	end

	/*
	** Update the object's status in cache.
	*/
	dbcc setreplicate(@replicate_name, @dbccbit)

	if @@error != 0
	begin
		/*
		** 17966 "Due to system failure, the replication status
		**	  for '%1!' has not been changed."
		*/
		raiserror 17966, @replicate_name, @setflag

		rollback transaction

		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		raiserror 17756, "sp_setreplicate", @dbname
			
		rollback transaction rs_logexec
		return(1)
	end

commit transaction

/*
** 17964 "The replication status for '%1!' is set to %2!."
*/
exec sp_getmessage 17964, @msg output
print @msg, @replicate_name, @setflag
return(0)
go
exec sp_procxmode 'sp_setreplicate', 'anymode'
go
grant execute on sp_setreplicate to public
go
exec sp_procxmode 'sp_setreplicate', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceused')
begin
	drop procedure sp_spaceused
end
go
print "Installing sp_spaceused"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/spaceused */
 
/*
** Messages for "sp_spaceused"          17830
**
** 17460, "Object must be in the current database." 
** 17461, "Object does not exist in this database."
** 17830, "Object is stored in 'sysprocedures' and
** 	   has no space allocated directly."
** 17831, "Views don't have space allocated."
** 17832, "Not avail."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_spaceused
@objname varchar(317) = null,		/* the object we want size on */
@list_indices int = 0			/* don't sum all indices, list each */
as

declare @type	smallint		/* the object type */
declare @msg	varchar(1024)		/* message output */
declare @dbname varchar(255)             /* database name */
declare @tabname varchar(255)            /* table name */
declare @length	int
declare @isarchivedb int		/* Is this an archive database? */
declare @empty_dpgs  int		/*
					** #empty data pages in hash region
					** of Virtually hashed table
					*/


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Determine if this is an archive database. */
if exists (select * from master.dbo.sysdatabases
                            where dbid = db_id()
                            and (status3 & 4194304) = 4194304)
        select @isarchivedb = 1
else
	select @isarchivedb = 0

/*
**  Check to see that the objname is local.
*/
if @objname is not null
begin
	/*
        ** Get the dbname and ensure that the object is in the
        ** current database. Also get the table name - this is later
        ** needed to see if information is being requested for syslogs.
        */
        execute sp_namecrack @objname,
                             @db = @dbname output,
                             @object = @tabname output
        if @dbname is not NULL
	begin
		/*
		** 17460, "Object must be in the current database." 
		*/
		if (@dbname != db_name())
		begin
			raiserror 17460
			return (1)
		end
	end

	/*
	**  Does the object exist?
	*/
	if not exists (select *
                        from sysobjects
                                where id = object_id(@objname))
	begin
		/*
		** 17461, "Object does not exist in this database."
		*/
		raiserror 17461
		return (1)
	end

	/* Get the object type */
        select @type = sysstat & 15 
                from sysobjects
                        where id = object_id(@objname)
	/*
	**  See if it's a space object.
	**  types are:
	**	0 - trigger
	**	1 - system table
	**	2 - view
	**	3 - user table
	**	4 - sproc
	**	6 - default
	**	7 - rule
	*/
	if not exists (select *
			from sysindexes
				where id = object_id(@objname)
					and indid < 2)
	begin
		if @type not in (1,2,3)
		begin
			/*
			** 17830, "Object is stored in 'sysprocedures' and
			** 	   has no space allocated directly."
			*/
			raiserror 17830
			return (1)
		end

		if @type = 2
		begin
			/*
			** 17831, "Views don't have space allocated."
			*/
			raiserror 17831
			return (1)
		end
	end

end

/*
**  If @objname is null, then we want summary data.
*/
set nocount on
if @objname is null
begin
	declare @slog_res_pgs numeric(20, 9),  	/* number of reserved pgs. in syslogs */
		@slog_dpgs numeric(20, 9) 	/* number of data pages in syslogs */
	
	if (@isarchivedb = 0)
	begin
		/* This is a normal database. */
		select distinct database_name = db_name(), database_size =
			ltrim(str(sum(size) / (1048576 / d.low), 10, 1)) + " MB"
		into #spaceused1result
		from master.dbo.sysusages, master.dbo.spt_values d
			where dbid = db_id()
				and d.number = 1
				and d.type = "E"
			having dbid = db_id()
				and d.number = 1
				and d.type = "E"

		exec sp_autoformat #spaceused1result
		drop table #spaceused1result
	end
	else
	begin
		/* This is an archive database. */
		declare @scratchdb sysname
		declare @dbsize int
		declare @sizestr varchar(128)

		/*
		** The original diskmap is stored in the sysaltusages catalog
		** in the scratch database with a location = 4.
		** Read the scratch database name from sysattributes first.
		*/
		select @scratchdb = convert(sysname, char_value)
		from master.dbo.sysattributes
		where 	class=28
			and object_type="D"
			and object=db_id()
			and attribute=0

		select @sizestr = 'select @dbsize=sum(size) from ' +
				@scratchdb + '.dbo.sysaltusages'+
				' where dbid=' + convert(char,db_id()) +
				' and location = 4'
		exec (@sizestr)
		
		select distinct 
			database_name = db_name(), 
			original_size =
				ltrim(str(@dbsize / (1048576 / d.low), 10, 1)) 
					+ " MB",
			modified_pages_size = 
				ltrim(str(sum(size) / (1048576 / d.low), 10, 1)) 
					+ " MB",
			unused = 
				ltrim(str(sum(unreservedpgs) / (1048576 / d.low), 10, 1)) 
					+ " MB"
		into #spaceused2result
		from master.dbo.sysusages, master.dbo.spt_values d
			where dbid = db_id()
				and d.number = 1
				and d.type = "E"
			having dbid = db_id()
				and d.number = 1
				and d.type = "E"

		exec sp_autoformat #spaceused2result
		drop table #spaceused2result
	end

	/*
	** Obtain the page count for syslogs table. 
	** 
	** The syslogs system table has only data (no index does exist).
	** Built-in functions reserved_pages and data_pages will always 
	** return the same value for syslogs.
	** This is due to the fact that syslogs pages are allocated an extent
	** worth at a time and all log pages in this extent are set as in use.
	** This is why we aren't able to determine the amount of unused 
	** syslogs pages by simply doing reserved_pages - data_pages.
	**
	** Also note that syslogs table doesn't have OAM pages.  However,
	** builtin functions reserved_pages() and data_pages() handle syslogs
	** as a special case.
	*/
	select @slog_res_pgs = convert(numeric(20, 9), reserved_pages(db_id(), 8))
	select @slog_dpgs = @slog_res_pgs

	/*
	** Obtain the page count for all the objects in the current
	** database; except for 'syslogs' (id = 8). Store the results
	** in a temp. table (#pgcounts).
	**
	** Note that we first retrieve the needed information from
	** sysindexes and we only then apply the OAM builtin system
	** functions on that data.  The reason being we want to relax
	** keeping the sh_int table lock on sysindexes for the duration
	** of the command.
	*/
	select distinct
		s.name,
		s.id,
		s.indid,
		res_pgs = 0,
		low = d.low,
		dpgs = convert(numeric(20, 9), 0),
		ipgs = convert(numeric(20, 9), 0),
		unused = convert(numeric(20, 9), 0)
	into #pgcounts 
	from sysindexes s, master.dbo.spt_values d
		where s.id != 8
			and d.number = 1 
			and d.type = "E" 
		having d.number = 1
			and d.type = "E"
	/*
	** If the database has one or more Virtually hashed tables, then
	** we have to count the empty pages in the hash region of those
	** tables. Find out all the Virtually hashed tables, count the
	** empty pages and modify the #data pages and #unused pages to be
	** reported accordingly.
	*/
	select distinct attrib = convert(char(30),a.char_value),
		id = s.id,
		emptypg_cnt = 0
	into #vhash_tbls
	from sysattributes t, master.dbo.sysattributes c,
		master.dbo.sysattributes a, sysindexes s
		where t.object_type = "T"
			and t.object = s.id
			and c.class = 0 and c.attribute = 0
			and a.class = 0 and a.attribute = 1
			and t.class = c.object
			and t.class = a.object
			and t.attribute = a.object_info1

	delete from #vhash_tbls where attrib <> 'hash key factors'

	update #vhash_tbls set
		emptypg_cnt = emptypgcnt
	from systabstats, #vhash_tbls
		where systabstats.id = #vhash_tbls.id

	select @empty_dpgs = sum(emptypg_cnt)
		from #vhash_tbls

	if(@empty_dpgs is NULL)
	begin
		select @empty_dpgs = 0
	end

	/* Calculate the reserved pages, data pages, index pages and
	** unused pages. Note that we take care of the special case
	** of indid = 1, 0 in later steps. For indid = 1 case we need
	** to get the data pages and index pages in separate steps.
	*/
	update #pgcounts set
		res_pgs = reserved_pages(db_id(), id, indid),
                ipgs = convert(numeric(20, 9), data_pages(db_id(), id, indid)),
		unused = convert(numeric(20, 9),
			  (reserved_pages(db_id(), id, indid) 
			  - data_pages(db_id(), id, indid)))
	where indid  > 1

	/* get the data pages for indid = 0 */
	update #pgcounts set
		res_pgs = reserved_pages(db_id(), id, indid),
		dpgs = convert(numeric(20, 9), data_pages(db_id(), id, indid)),
		unused = convert(numeric(20, 9),
			   (reserved_pages(db_id(), id, indid)
			   - data_pages(db_id(), id, indid)))
	where indid = 0
		
	
	/* For the clustered index case calculate the data and reserved pages
	** by passing in indid of 0 to the builtins. Note, for indid = 1
	** the data pages are accounted for in ipgs. 
	*/
	update #pgcounts set
		ipgs = ipgs 
		  + convert(numeric(20, 9), data_pages(db_id(), id, indid)),
		dpgs = dpgs
		  + convert(numeric(20, 9), data_pages(db_id(), id, 0)),
                res_pgs = res_pgs 
			+ reserved_pages(db_id(), id, 0)
			+ reserved_pages(db_id(), id, indid)
        where indid = 1

	/* Calculate the unused count for the special case of indid  = 1 */
	update #pgcounts set
		unused = convert(numeric(20, 9), (res_pgs - dpgs - ipgs))
	where indid = 1

	/*
	** Compute the summary results by adding page counts from
	** individual data objects. Add to the count the count of 
	** pages for 'syslogs'.  Convert the total pages to space
	** used in Kilo bytes.
	*/
	select distinct reserved = convert(char(15), convert(varchar(11),
		convert(numeric(11, 0), (sum(res_pgs) + @slog_res_pgs) *
			(low / 1024))) + " " + "KB"),
		data = convert(char(15), convert(varchar(11),
			convert(numeric(11, 0), (sum(dpgs) + @slog_dpgs -
			@empty_dpgs) * (low / 1024))) + " " + "KB"),
		index_size = convert(char(15), convert(varchar(11),
			convert(numeric(11, 0),  sum(ipgs) * (low / 1024)))
			+ " " + "KB"),
		unused = convert(char(15), convert(varchar(11),
			convert(numeric(11, 0), (sum(unused) + @empty_dpgs) * 
			(low / 1024))) + " " + "KB")
	into #fmtpgcnts
	from #pgcounts

	exec sp_autoformat #fmtpgcnts
	drop table #fmtpgcnts
end

/*
**  We want a particular object.
*/
else
begin
	if (@tabname = "syslogs") /* syslogs */
	begin
		declare @free_pages	int, /* log free space in pages */
			@clr_pages	int, /* log space reserved for CLRs */
			@total_pages	int, /* total allocatable log space */
			@used_pages	int, /* allocated log space */
			@ismixedlog	int  /* mixed log & data database ? */

		select @ismixedlog = status2 & 32768
			from master.dbo.sysdatabases where dbid = db_id()

		select @clr_pages = lct_admin("reserved_for_rollbacks", 
						db_id())
		select @free_pages = lct_admin("logsegment_freepages", db_id())
				     - @clr_pages

		select @total_pages = sum(u.size)
		from master.dbo.sysusages u
		where u.segmap & 4 = 4
		and u.dbid = db_id()

		if(@ismixedlog = 32768)
		begin
			/* 
			** For a mixed log and data database, we cannot
			** deduce the log used space from the total space
			** as it is mixed with data. So we take the expensive
			** way by scanning syslogs.
			*/
			select @used_pages = lct_admin("num_logpages", db_id())

			/* Account allocation pages as used pages */
			select @used_pages = @used_pages + (@total_pages / 256)
		end
		else
		begin
			/* Dedicated log database */
			select @used_pages = @total_pages - @free_pages 
					   - @clr_pages
		end

		select	name = convert(char(15), @tabname),
			total_pages = convert(char(15), @total_pages),
			free_pages = convert(char(15), @free_pages),
			used_pages = convert(char(15), @used_pages),
			reserved_pages = convert(char(15), @clr_pages)
	end
	else
	begin
		/*
		** Obtain the page count for the target object in the current
		** database and store them in the temp table #pagecounts.
		**
		** Note that we first retrieve the needed information from
		** sysindexes and we only then apply the OAM builtin system
		** functions on that data.  The reason being we want to relax
		** keeping the sh_int table lock on sysindexes for the duration
		** of the command.
		*/
		select  name = o.name,
			tabid = i.id,
			iname = i.name, 
			indid = i.indid,
			low = d.low,
			rowtotal = convert(numeric(18,0), 0),
			reserved = convert(numeric(20, 9), 0),
			data = convert(numeric(20, 9), 0),
			index_size = convert(numeric(20, 9), 0),
			unused = convert(numeric(20, 9), 0)
		into #pagecounts
		from sysobjects o, sysindexes i, master.dbo.spt_values d
				where i.id = object_id(@objname)
					and o.id = i.id
					and d.number = 1
					and d.type = "E"
		
		/* perform the row counts */
		update #pagecounts
			set rowtotal = row_count(db_id(), tabid)
		where indid <= 1

		/* calculate the counts for indid > 1
		** case of indid = 1, 0 are special cases done later
		*/
		update #pagecounts set
			reserved = convert(numeric(20, 9),
			    reserved_pages(db_id(), tabid, indid)),
			index_size =  convert(numeric(20, 9),
			    data_pages(db_id(), tabid, indid)),
			unused = convert(numeric(20, 9),
				 ((reserved_pages(db_id(), tabid, indid) -
				  (data_pages(db_id(), tabid, indid)))))
		where indid > 1


		/* calculate for case where indid = 0 */
		update #pagecounts set
                        reserved = convert(numeric(20, 9),
                            reserved_pages(db_id(), tabid, indid)),
                        data = convert(numeric(20, 9),
                            data_pages(db_id(), tabid, indid)),
                        unused = convert(numeric(20, 9),
                                 ((reserved_pages(db_id(), tabid, indid) -
                                  (data_pages(db_id(), tabid, indid)))))
                where indid = 0


		/* handle the case where indid = 1, since we need
		** to take care of the data and index pages. 
		*/
		update #pagecounts set
			reserved = convert(numeric(20, 9),
			             reserved_pages(db_id(), tabid, 0)) 
			          +  convert(numeric(20, 9),
			             reserved_pages(db_id(), tabid, indid)),
			index_size = convert(numeric(20, 9),
				     data_pages(db_id(), tabid, indid)),
		        data = convert(numeric(20, 9),
				       data_pages(db_id(), tabid, 0))
		where indid = 1

		/* calculate the unused count for indid = 1 case.*/
		update #pagecounts set
			unused = convert(numeric(20, 9), 
				     reserved - data - index_size)
		where indid = 1


	    if (@list_indices = 1)
	    begin
        	select  index_name = iname,
			size = convert(char(10), convert(varchar(11),
	    	       	       convert(numeric(11, 0),
				       index_size / 1024 *
		        			low)) + " " + "KB"),
	    		reserved = convert(char(10), 
				   convert(varchar(11),
	    	       	   	   convert(numeric(11, 0),
					   reserved / 1024 * 
		       			   low)) + " " + "KB"),
	    		unused = convert(char(10), convert(varchar(11),
	    		 	 convert(numeric(11, 0), unused / 1024 *
					 low)) + " " + "KB")
		into #formatpgcounts
		from #pagecounts
		where indid > 0

		exec sp_autoformat #formatpgcounts
		drop table #formatpgcounts
	    end

	    /*
	    ** Check whether the table is Virtually hashed. For Virtually
	    ** Hashed tables, we maintain the number of empty pages in
    	    ** systabstats. Compute the #data pages and #unused pages
	    ** based on that value.
	    */
	    if(exists(select convert(char(30),a.char_value)
		from sysattributes t, master.dbo.sysattributes c,
			master.dbo.sysattributes a
		where t.object_type = "T"
			and t.object = object_id(@objname)
			and c.class = 0 and c.attribute = 0
			and a.class = 0 and a.attribute = 1
			and t.class = c.object
			and t.class = a.object
			and t.attribute = a.object_info1
			and a.char_value = 'hash key factors'))
	    begin
		select @empty_dpgs = emptypgcnt
			from systabstats where id = object_id(@objname)
	    end
	    else
	    begin
		select @empty_dpgs = 0
	    end

	    select distinct name,
	    	rowtotal = convert(char(15), sum(rowtotal)),
		reserved = convert(char(15), convert(varchar(11),
		           convert(numeric(11, 0), sum(reserved) *
			   (low / 1024))) + " " + "KB"),
		data = convert(char(15), convert(varchar(11),
		       convert(numeric(11, 0), (sum(data) - @empty_dpgs) * (low / 1024))) 
		       + " " + "KB"),
		index_size = convert(char(15), convert(varchar(11),
			     convert(numeric(11, 0), sum(index_size) *
			     (low / 1024))) + " " + "KB"),
		unused = convert(char(15), convert(varchar(11),
		    	 convert(numeric(11, 0), (sum(unused) + @empty_dpgs) *
			 (low / 1024))) + " " + "KB")
		into #fmtpgcounts
	        from #pagecounts

		exec sp_autoformat #fmtpgcounts
		drop table #fmtpgcounts
	end
end
return (0)
go
exec sp_procxmode 'sp_spaceused', 'anymode'
go
grant execute on sp_spaceused to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sproc_columns')
begin
	drop procedure sp_sproc_columns
end
go
print "Installing sp_sproc_columns"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_sproc_columns"
**
** 18039, "Table qualifier must be name of current database"
*/

create procedure sp_sproc_columns
@procedure_name		varchar(261) = '%', 	/* name of stored procedure  */
@procedure_owner 	varchar(257) = null,	/* owner of stored procedure */
@procedure_qualifier	varchar(257) = null,	/* name of current database  */
@column_name		varchar(257) = null	/* col name or param name    */
as

declare @msg 		  varchar(250)
declare @group_num		int
declare @semi_position		int
declare @full_procedure_name	char(520)
declare @procedure_id		int
declare @char_bin_types   varchar(30) 
declare @sptlang  		int	

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
        if not exists (
                select * from master.dbo.sysmessages where error
                between 17100 and 17109
                and langid = @@langid)
            select @sptlang = 0
end


/* If column name not supplied, match all */
if @column_name is null 
	select @column_name = '%'

/* The qualifier must be the name of current database or null */
if @procedure_qualifier is not null
begin
	if db_name() != @procedure_qualifier
	begin
	if @procedure_qualifier = ''
		begin
			/* in this case, we need to return an empty result 
			** set because the user has requested a database with
			** an empty name
			*/
			select @procedure_name = ''
			select @procedure_owner = ''
		end
		else
		begin
			/*
			** 18039, Table qualifier must be name of current database
			*/
			exec sp_getmessage 18039, @msg output
			print @msg
			return
		end
	end
end


/* first we need to extract the procedure group number, if one exists */
select @semi_position = charindex(';',@procedure_name)
if (@semi_position > 0)
begin	/* If group number separator (;) found */
	select @group_num = convert(int,substring(@procedure_name, 
						  @semi_position + 1, 2))
	select @procedure_name = substring(@procedure_name, 1, 
					   @semi_position -1)
end
else
begin	/* No group separator, so default to group number of 1 */
	select @group_num = 1
end

/* character and binary datatypes */
select @char_bin_types =
	char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

if @procedure_owner is null
begin	/* If unqualified procedure name */
	select @full_procedure_name = @procedure_name
end
else
begin	/* Qualified procedure name */
	select @full_procedure_name = @procedure_owner + '.' + @procedure_name
end

/*
** If the @column_name parameter is "RETURN_VALUE" and this is a sqlj
** function, then we should be looking for column name "Return Type"
*/
if @column_name = "RETURN_VALUE"
	and exists (select 1 from sysobjects
		    where id = object_id(@full_procedure_name)
		    and type = 'F')
begin	
	select @column_name = "Return Type"
end

/*	Get Object ID */
select @procedure_id = object_id(@full_procedure_name)

if ((charindex('%',@full_procedure_name) = 0) and
	(charindex('_',@full_procedure_name) = 0)  and
	@procedure_id != 0)
begin
/*
** this block is for the case where there is no pattern
** matching required for the table name
*/
	select	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		procedure_qualifier = db_name(),
		procedure_owner = user_name(o.uid),
		procedure_name = o.name +';'+ ltrim(str(c.number,5)),
                column_name =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                column_type =
                        case
                            when c.name = 'Return Type'
                                        then convert(smallint, 5)
                            else convert(smallint, 0)
                        end,

/*
** With the current data in the spt_datatype_info table, the convert() below
** is never being used.
** These conversions were ported from the original Microsoft INSTCAT.SQL
** file which contained catalog stored procedures for 4.9 and earlier SQL
** Servers.
*/
		data_type = d.data_type
			    +convert(smallint, 
				     isnull(d.aux,
					    ascii(substring("666AAA@@@CB??GG",
						            2*(d.ss_dtype%35+1)
							    +2-8/c.length,
							    1)) - 60)),
		type_name = rtrim(substring(d.type_name,
					1+isnull(d.aux,
					     ascii(substring("III<<<MMMI<<A<A",
							2*(d.ss_dtype%35+1)
							+2-8/c.length,
						        1)) - 60), 
					    13)),
		"precision" = isnull(convert(int, c.prec),
			isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						          2*(d.ss_dtype%35+1)
							  +2-8/c.length,1))
							  -60)),
		length = isnull(d.length, convert(int,c.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						    	     2*(d.ss_dtype%35
							     +1)+2-8/c.length,
						             1))-64)),
		scale = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale)) +
			convert(smallint, 
				isnull(d.aux, ascii(substring("<<<<<<<<<<<<<<?",
					        2*(d.ss_dtype%35+1)
						+2-8/c.length,
					        1))-60)),
		radix = d.numeric_radix,
		nullable =	/* set nullability from status flag */
			convert(smallint, convert(bit, c.status&8)),
		remarks = null,		/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
		column_def = NULL,
		sql_data_type = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
			isnull(d.aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(d.ss_dtype%35+1)+2-8/c.length,1))
			-60))),
		sql_datetime_sub = NULL,
		char_octet_length = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint,
		    substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
		/* calculate the precision */
		isnull(convert(int, c.prec),
		    isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		    +isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		ordinal_position = c.colid,
		is_nullable = rtrim(substring('NO YES',
			(convert(smallint, convert(bit, c.status&8))*3)+1, 3)),
                mode = case c.status2
                        when NULL then "unknown"
                        else (select convert(nvarchar(20), mi.description)
                              from   master.dbo.spt_values vi
                                   , master.dbo.sysmessages mi
                              where vi.number = c.status2
                                   and vi.msgnum = mi.error
                                   and isnull(mi.langid, 0) = @sptlang
                                   and mi.error between 17583 and 17586)
                        end
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.id = @procedure_id
		and c.id = o.id
		and c.type = d.ss_dtype
		and c.name like @column_name
		and d.ss_dtype in (111, 109, 38, 110, 43)  /* Just *N types */
		and c.number = @group_num
	union
	select
		procedure_qualifier = db_name(),
		procedure_owner = user_name(o.uid),
		procedure_name = o.name +';'+ ltrim(str(@group_num,5)),
		column_name = 'RETURN_VALUE',
		column_type = convert(smallint, 5), /* return parameter */
		data_type = d.data_type+convert(smallint,
					  isnull(d.aux,
					     ascii(substring("666AAA@@@CB??GG",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
						          -60)),
		type_name = d.type_name,
		"precision" = isnull(d.data_precision, convert(int,d.length))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
							  -60)),
		length = isnull(d.length, convert(int,t.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						    	     2*(d.ss_dtype%35
							     +1)+2-8/t.length,
						             1))-64)),
		scale = d.numeric_scale +convert(smallint,
					   isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
						        2*(d.ss_dtype%35+1)
							+2-8/d.length,
						        1))-60)),
		radix = d.numeric_radix,
		nullable = convert(smallint, 0),
		remarks = null,		/* Remarks are NULL */
		ss_data_type = d.ss_dtype,
		colid = convert(smallint, 0), /* first row returned */
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/d.length,1))
                        -60))),
                sql_datetime_sub = NULL,
                char_octet_length = NULL,
                ordinal_position = convert(tinyint, 0),
                is_nullable = "NO",
                mode = (select convert(nvarchar(20), mi.description)
                        from master.dbo.sysmessages mi
                        where isnull(mi.langid, 0) = @sptlang
                        and mi.error = 17586)

	from
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.id = @procedure_id
		and d.ss_dtype = 56  /* int for return code */
		and t.type = 56
		and o.type = 'P'
		and (@column_name = '%' or @column_name = 'RETURN_VALUE')
	union
	select		   /* All other types including user data types */
		procedure_qualifier = db_name(),
		procedure_owner = user_name(o.uid),
		procedure_name = o.name +';'+ ltrim(str(c.number,5)),
		column_name = 	
			case	
		 	    when c.name = 'Return Type' then 'RETURN_VALUE'
			    else c.name
			end,
		column_type = 
			case 
			    when c.name = 'Return Type' 
					then convert(smallint, 5)
			    else convert(smallint, 0)	
			end,		

		/*   Map systypes.type to ODBC type	       		*/
		/*   SS-Type "				 1	      "	*/
		/*	     "33 3 3 4 44 5 5 2 5 55666"	        */
		/*	     "45 7 9	5 78 0 2 2 6 89012"             */
		data_type = d.data_type+convert(smallint,
			isnull(d.aux, ascii(substring("666AAA@@@CB??GG",
			2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)),
		type_name = 
			case 
			    when t.name = 'extended type' 
				then isnull(get_xtypename(c.xtype, c.xdbid), 
									t.name)
			    when t.usertype in (44, 45, 46)
				then "unsigned " + substring(t.name, 
						charindex("u", t.name) + 1, 
						charindex("t", t.name))
			    else 
				t.name
			end,
		"precision" = isnull(convert(int, c.prec),
			isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						       2*(d.ss_dtype%35+1)
						       +2-8/c.length,1))
						       -60)),
		length = isnull(d.length, convert(int,c.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						             2*(d.ss_dtype%35
							     +1)+2-8/c.length,
						             1))-64)),
		scale = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale))
			+ convert(smallint,
					  isnull(d.aux,
					    ascii(substring("<<<<<<<<<<<<<<?",
							    2*(d.ss_dtype%35+1)
							    +2-8/c.length,
							    1))-60)),
		radix = d.numeric_radix,

		/* set nullability from status flag */
		nullable = convert(smallint, convert(bit, c.status&8)),
		remarks = null,		/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60))),
                sql_datetime_sub = NULL,
		char_octet_length = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint,
		    substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
		/* calculate the precision */
		isnull(convert(int, c.prec),
		    isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		    +isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                        (convert(smallint, convert(bit, c.status&8))*3)+1, 3)),
                mode = case c.status2
                        when NULL then "unknown"
                        else (select convert(nvarchar(20), mi.description)
                              from   master.dbo.spt_values vi
                                   , master.dbo.sysmessages mi
                              where vi.number = c.status2
                                   and vi.msgnum = mi.error
                                   and isnull(mi.langid, 0) = @sptlang
                                   and mi.error between 17583 and 17586)
                        end
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.id = @procedure_id
		and c.id = o.id
		and c.type *= d.ss_dtype
		and c.usertype *= t.usertype
		and c.name like @column_name
		and c.number = @group_num
		and d.ss_dtype not in (111, 109, 38, 110, 43) /* No *N types */
	order by colid
end
else
begin
	/* 
	** this block is for the case where there IS pattern
	** matching done on the table name
	*/
	if @procedure_owner is null
		select @procedure_owner = '%'

	select	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		procedure_qualifier = db_name(),
		procedure_owner = user_name(o.uid),
		procedure_name = o.name +';'+ ltrim(str(c.number,5)),
                column_name =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                column_type =
                        case
                            when c.name = 'Return Type'
                                        then convert(smallint, 5)
                            else convert(smallint, 0)
                        end,
		data_type = d.data_type+convert(smallint,
					  isnull(d.aux,
					     ascii(substring("666AAA@@@CB??GG",
						          2*(d.ss_dtype%35+1)
							  +2-8/c.length,1))
						          -60)),
		type_name = rtrim(substring(d.type_name,
				    1+isnull(d.aux,
					     ascii(substring("III<<<MMMI<<A<A",
					                  2*(d.ss_dtype%35+1)
							  +2-8/c.length,
						          1))-60), 13)),
		"precision" = isnull(convert(int, c.prec), 
				isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						           2*(d.ss_dtype%35+1)
							   +2-8/c.length,1))
						           -60)),
		length = isnull(d.length, convert(int,c.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
							   2*(d.ss_dtype%35+1)
							   +2-8/c.length,
							   1))-64)),
		scale = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale))
			+ convert(smallint,
					    isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
							   2*(d.ss_dtype%35+1)
							   +2-8/c.length,
							   1))-60)),
		radix = d.numeric_radix,
		/* set nullability from status flag */
		nullable = convert(smallint, convert(bit, c.status&8)),
		remarks = null,		/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60))),
                sql_datetime_sub = NULL,
		char_octet_length = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint,
		    substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
		/* calculate the precision */
		isnull(convert(int, c.prec),
		    isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		    +isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                        (convert(smallint, convert(bit, c.status&8))*3)+1, 3)),
                mode = case c.status2
                        when NULL then "unknown"
                        else (select convert(nvarchar(20), mi.description)
                              from   master.dbo.spt_values vi
                                   , master.dbo.sysmessages mi
                              where vi.number = c.status2
                                   and vi.msgnum = mi.error
                                   and isnull(mi.langid, 0) = @sptlang
                                   and mi.error between 17583 and 17586)
                        end

	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_owner
		and o.id = c.id
		and c.type = d.ss_dtype
		and c.name like @column_name
		
		/* Just procs & sqlj procs and funcs */
		and o.type in ('P', 'F')
		and d.ss_dtype in (111, 109, 38, 110, 43)	/* Just *N types */
	union
	select distinct
		procedure_qualifier = db_name(),
		procedure_owner = user_name(o.uid),
		procedure_name = o.name +';'+ ltrim(str(p.number,5)),
		column_name = 'RETURN_VALUE',
		column_type = convert(smallint, 5), /* return parameter */
		data_type = d.data_type+convert(smallint,
					  isnull(d.aux,
					     ascii(substring("666AAA@@@CB??GG",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
						          -60)),
		type_name = d.type_name,
		"precision" = isnull(d.data_precision, convert(int,d.length))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
							  -60)),
		length = isnull(d.length, convert(int,t.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						    	     2*(d.ss_dtype%35
							     +1)+2-8/t.length,
						             1))-64)),
		scale = d.numeric_scale +convert(smallint,
					   isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
						        2*(d.ss_dtype%35+1)
							+2-8/d.length,
						        1))-60)),
		radix = d.numeric_radix,
		nullable = convert(smallint, 0),
		remarks = null,		/* Remarks are NULL */
		ss_data_type = d.ss_dtype,
		colid = convert(smallint, 0), /* first row returned */
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/d.length,1))
                        -60))),
                sql_datetime_sub = NULL,
                char_octet_length = NULL,
                ordinal_position = convert(tinyint, 0),
                is_nullable = "NO",
                mode = (select convert(nvarchar(20), mi.description)
                        from master.dbo.sysmessages mi
                        where isnull(mi.langid, 0) = @sptlang
                        and mi.error = 17586)

	from
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sysprocedures p
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_owner
		and d.ss_dtype = 56  /* int for return code */
		and t.type = 56
		and o.type = 'P'			/* Just Procedures */
		and p.id = o.id
		and 'RETURN_VALUE' like @column_name
	union
	select		   /* All other types including user data types */
		procedure_qualifier = db_name(),
		procedure_owner = user_name(o.uid),
		procedure_name = o.name +';'+ ltrim(str(c.number,5)),
                column_name =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                column_type =
                        case
                            when c.name = 'Return Type'
                                        then convert(smallint, 5)
                            else convert(smallint, 0)
                        end,
		/*   Map systypes.type to ODBC type    			*/
		/*   SS-Type  "				 1	      " */
		/*	      "33 3 3 4 44 5 5 2 5 55666"		*/
		/*	      "45 7 9 5 78 0 2 2 6 89012"    		*/
		data_type = d.data_type+convert(smallint,
			isnull(d.aux, ascii(substring("666AAA@@@CB??GG",
			2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)),
		type_name =
                        case 
                            when t.name = 'extended type' 
                                then isnull(get_xtypename(c.xtype, c.xdbid),
									t.name)
                            when t.usertype in (44, 45, 46)        
                                then "unsigned " + substring(t.name, 
                                                charindex("u", t.name) + 1, 
                                                charindex("t", t.name))
                            else 
                                t.name
                        end,


		"precision" = isnull(convert(int, c.prec),
			isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, 
				     convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
					                   2*(d.ss_dtype%35+1)
							   +2-8/c.length,1))
					           -60)),
		length = isnull(d.length, convert(int,c.length))
			 +convert(int,
				  isnull(d.aux,
					 ascii(substring("AAA<BB<DDDHJSPP",
					                 2*(d.ss_dtype%35+1)
							 +2-8/c.length,
					                 1))-64)),
		scale = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale))
			+ convert(smallint,
				 isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					                2*(d.ss_dtype%35+1)
							+2-8/c.length,
					                1))-60)),
		radix = d.numeric_radix,
		/* set nullability from status flag */
		nullable = convert(smallint, convert(bit, c.status&8)),
		remarks = null,		/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60))),
                sql_datetime_sub = NULL,
		char_octet_length = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint,
		    substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
		/* calculate the precision */
		isnull(convert(int, c.prec),
		    isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		    +isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                        (convert(smallint, convert(bit, c.status&8))*3)+1, 3)),
                mode = case c.status2
                        when NULL then "unknown"
                        else (select convert(nvarchar(20), mi.description)
                              from   master.dbo.spt_values vi
                                   , master.dbo.sysmessages mi
                              where vi.number = c.status2
                                   and vi.msgnum = mi.error
                                   and isnull(mi.langid, 0) = @sptlang
                                   and mi.error between 17583 and 17586)
                        end

	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_owner
		and o.id = c.id
		and c.type *= d.ss_dtype
		and c.usertype *= t.usertype

                /* Just procs & sqlj procs and funcs */
		and o.type in ('P', 'F')
		and c.name like @column_name
		and d.ss_dtype not in (111, 109, 38, 110, 43) /* No *N types */
	order by procedure_owner, procedure_name, colid
end


go
exec sp_procxmode 'sp_sproc_columns', 'anymode'
go
grant execute on sp_sproc_columns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_statistics')
begin
	drop procedure sp_statistics
end
go
print "Installing sp_statistics"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_statistics"          18039
**
** 18039, "Table qualifier must be name of current database."
** 18040, "Catalog procedure '%1!' can not be run in a transaction.
**
*/

/*
** Sp_statistics returns statistics for the given table, passed as first 
** argument. A row is returned for the table and then for each index found
** in sysindexes, starting with lowest value index id in sysindexes and 
** proceeding through the highest value index.  
**
** Returned rows consist of the columns:
** table qualifier (database name), table owner, table name from sysobjects, 
** non_unique (0/1), index qualifier (same as table name), 
** index name from sysindexes, type (SQL_INDEX_CLUSTERED/SQL_INDEX_OTHER), 
** sequence in index, column name, collation, table cardinality (row count), 
** and number of pages used by table (doampg).
** table cardinality (row count), and number of pages used by 
** table (datoampage).
*/

create procedure sp_statistics (
	@table_name		varchar(257),
	@table_owner		varchar(257) = null,
	@table_qualifier	varchar(257) = null,
	@index_name		varchar(257) = '%',
	@is_unique 		char(1) = 'N')
as
declare @indid			int
declare @lastindid		int
declare @full_table_name	char(520)
declare @int_limit		int

/*
** Verify table qualifier is name of current database.
*/
if @table_qualifier is not null
begin
	if db_name() != @table_qualifier
	begin	/* If qualifier doesn't match current database */
		/*
		** 18039, "Table qualifier must be name of current database."
		*/
		raiserror 18039
		return (1)
	end
end

if @@trancount > 0
begin
	/*
	** 18040, "Catalog procedure '%1!' can not be run in a transaction.
	*/
	raiserror 18040, "sp_statistics"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

create table #TmpIndex(
	table_qualifier	varchar(257),
	table_owner	varchar(257),
	table_name	varchar(257),
	index_qualifier varchar(257) null,
	index_name	varchar(257) null,
	non_unique	smallint null,
	type		smallint,
	seq_in_index	smallint null,
	column_name	varchar(257) null,
	collation	char(1) null,
	index_id	int null,
	cardinality	int null,
	pages		int null,
	status		smallint,
	status2		smallint)

/*
** Fully qualify table name.
*/
if @table_owner is null
begin	/* If unqualified table name */
	select @full_table_name = @table_name
end
else
begin	/* Qualified table name */
	select @full_table_name = @table_owner + '.' + @table_name
end

select @int_limit=2147483647

/*
** Start at lowest index id, while loop through indexes. 
** Create a row in #TmpIndex for every column in sysindexes, each is
** followed by an row in #TmpIndex with table statistics for the preceding
** index.
*/
select @indid = min(indid)
	from sysindexes
	where id = object_id(@full_table_name)
		and indid > 0
		and indid < 255

while @indid is not NULL
begin
	insert #TmpIndex	/* Add all columns that are in index */
	select
		db_name(),		/* table_qualifier */
		user_name(o.uid),	/* table_owner	   */
		o.name,			/* table_name	   */
		o.name, 		/* index_qualifier */
		x.name,			/* index_name	   */
		0,			/* non_unique	   */
		1,			/* SQL_INDEX_CLUSTERED */
		colid,			/* seq_in_index	   */
		INDEX_COL(@full_table_name,x.indid,colid),
					/* column_name	   */
		index_colorder(@full_table_name,
			x.indid,colid),	/* collation	   */
		@indid,			/* index_id 	   */
		case			/* cardinality	   */ 
			when row_count(db_id(), x.id) < @int_limit
			then row_count(db_id(), x.id) 
			else @int_limit
			end,	
		case			/* pages	   */
			when data_pages(db_id(), x.id, 
					case
						when x.indid = 1
						then 0
						else x.indid
					end) < @int_limit
			then data_pages(db_id(), x.id, 
					case
						when x.indid = 1
						then 0
						else x.indid
					end)
			else @int_limit
			end,
		x.status,		/* status	   */
		x.status2		/* status2	   */		
	from sysindexes x, syscolumns c, sysobjects o
	where x.id = object_id(@full_table_name)
		and x.id = o.id
		and x.id = c.id
		and c.colid < keycnt+(x.status&16)/16
		and x.indid = @indid

	/*
	** Save last index and increase index id to next higher value.
	*/
	select @lastindid = @indid
	select @indid = NULL

	select @indid = min(indid)
	from sysindexes
	where id = object_id(@full_table_name)
		and indid > @lastindid
		and indid < 255
end

update #TmpIndex
	set non_unique = 1
	where status&2 != 2 /* If non-unique index */

update #TmpIndex
	set
		type = 3,		/* SQL_INDEX_OTHER */
		cardinality = NULL,
		pages = NULL
	where index_id > 1		/* If non-clustered index */

update #TmpIndex
	set type = 1			/* SQL_INDEX_CLUSTERED */
	where 
	status2&512 = 512	/* if placement index */
/* 
** Now add row with table statistics 
*/
insert #TmpIndex
	select
		db_name(),			/* table_qualifier */
		user_name(o.uid),		/* table_owner	   */
		o.name, 			/* table_name	   */
		null,				/* index_qualifier */
		null,				/* index_name	   */
		null,				/* non_unique	   */
		0,				/* SQL_table_STAT  */
		null,				/* seq_in_index	*/
		null,				/* column_name	   */
		null,				/* collation	   */
		0,				/* index_id 	   */
		case				/* cardinality	   */ 
			when row_count(db_id(), x.id) < @int_limit
			then row_count(db_id(), x.id) 
			else @int_limit
			end,	
		case				/* pages	   */ 
			when data_pages(db_id(), x.id, 
					case
						when x.indid = 1
						then 0
						else x.indid
					end) < @int_limit
			then data_pages(db_id(), x.id, 
					case
						when x.indid = 1
						then 0
						else x.indid
					end)
			else @int_limit
			end,
		0,				/* status	   */
		0				/* status2	   */
	from sysindexes x, sysobjects o
	where o.id = object_id(@full_table_name)
		and x.id = o.id
		and (x.indid = 0 or x.indid = 1)	
	/*  
	** If there are no indexes
	** then table stats are in a row with indid = 0
	*/

if @is_unique != 'Y'	
begin
	/* If all indexes desired */
	select
		table_qualifier,
		table_owner,
		table_name,
		non_unique,
		index_qualifier,
		index_name,
		type,
		seq_in_index,
		column_name,
		collation,
		cardinality,
		pages
	from #TmpIndex
	where index_name like @index_name 	/* If matching name */
		or index_name is null		/* If SQL_table_STAT row */
	order by non_unique, type, index_name, seq_in_index

end
else	
begin
	/* else only unique indexes desired */
	select
		table_qualifier,
		table_owner,
		table_name,
		non_unique,
		index_qualifier,
		index_name,
		type,
		seq_in_index,
		column_name,
		collation,
		cardinality,
		pages
	from #TmpIndex
	where (non_unique = 0 			/* If unique */
		or non_unique is NULL)		/* If SQL_table_STAT row */
		and (index_name like @index_name	/* If matching name */
		or index_name is NULL)		/* If SQL_table_STAT row */
	order by non_unique, type, index_name, seq_in_index

end
drop table #TmpIndex

return (0)
go
exec sp_procxmode 'sp_statistics', 'anymode'
go
grant execute on sp_statistics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sendmsg')
begin
	drop procedure sp_sendmsg
end
go
print "Installing sp_sendmsg"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

create procedure sp_sendmsg 
@ip_address varchar(255),		/* IP address to send the message */
@port_number  int,			/* Port number */
@message varchar(4096)			/* Message to be sent */
as

declare @returncode int

if @@trancount = 0
begin
	set chained off
	set transaction isolation level 1
end


/* Do the work */
select @returncode = syb_sendmsg(@ip_address, @port_number, @message)

if ((@returncode = 0) or (@returncode is null))
begin
	return(0)
end
else
begin
	return(1)
end

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_stored_procedures')
begin
	drop procedure sp_stored_procedures
end
go
print "Installing sp_stored_procedures"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_stored_procedures"	18041
**
** 18041, "Stored Procedure qualifier must be name of current database."
**
*/
create procedure sp_stored_procedures
@sp_name	varchar(261) = null,	/* stored procedure name */
@sp_owner	varchar(257) = null,	/* stored procedure owner */
@sp_qualifier	varchar(257) = null	/* stored procedure qualifier; 
					** For the SQL Server, the only valid
					** values are NULL or the current 
					** database name
					*/
as

declare @issa int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* If qualifier is specified */
if @sp_qualifier is not null
begin
	/* If qualifier doesn't match current database */
	if db_name() != @sp_qualifier
	begin
		/* If qualifier is not specified */
		if @sp_qualifier = ''
		begin
			/* in this case, we need to return an empty 
			** result set because the user has requested a 
			** database with an empty name 
			*/
			select @sp_name = ''
			select @sp_owner = ''
		end

		/* qualifier is specified and does not match current database */
		else
		begin	
			/* 
			** 18041, "Stored Procedure qualifer must be name of
			** current database"
			*/
			raiserror 18041
			return (1)
		end
	end
end

/* If procedure name not supplied, match all */
if @sp_name is null
begin  
	select @sp_name = '%'
end
else 
begin
	/* If owner name is not supplied, but procedure name is */ 
	if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
	begin
		/* If procedure exists and is owned by the current user */
		if exists (select * 
			   from sysobjects
			   where uid = user_id()
				and name = @sp_name
				and type = 'P') /* Object type of Procedure */
		begin
			/* Set owner name to current user */
			select @sp_owner = user_name()
		end
	end
end

/* If procedure owner not supplied, match all */
if @sp_owner is null	
	select @sp_owner = '%'

if (suser_id() = 1 or charindex('sa_role', show_role()) > 0)
	select @issa = 1
else
	select @issa = 0

/* 
** Retrieve the stored procedures and associated info on them
*/
select procedure_qualifier = db_name(),
	procedure_owner = user_name(o.uid),
	procedure_name = o.name +';'+ ltrim(str(p.number,5)),
	num_input_params = -1,		/* Constant since value unknown */
	num_output_params = -1, 	/* Constant since value unknown */
	num_result_sets = -1,		/* Constant since value unknown */
	remarks = null			/* Remarks are NULL */
from sysobjects o,sysprocedures p,sysusers u
where o.name like @sp_name
	and p.sequence = 0
	and user_name(o.uid) like @sp_owner
	and o.type = 'P'		/* Object type of Procedure */
	and p.id = o.id
	and u.uid = user_id()		/* constrain sysusers uid for use in 
					** subquery 
					*/

	and (@issa = 1 		/* User is the System Administrator */
	     or  o.uid = user_id()	/* User created the object */
					/* here's the magic..select the highest 
					** precedence of permissions in the 
					** order (user,group,public)  
					*/

	     /*
	     ** The value of protecttype is
	     **
	     **		0  for grant with grant
	     **		1  for grant and,
	     **		2  for revoke
	     **
	     ** As protecttype is of type tinyint, protecttype/2 is
	     ** integer division and will yield 0 for both types of
	     ** grants and will yield 1 for revoke, i.e., when
	     ** the value of protecttype is 2.  The XOR (^) operation
	     ** will reverse the bits and thus (protecttype/2)^1 will
	     ** yield a value of 1 for grants and will yield a
	     ** value of zero for revoke.
	     **
	     ** For groups, uid = gid. We shall use this to our advantage.
             ** 	
	     ** If there are several entries in the sysprotects table
	     ** with the same Object ID, then the following expression
	     ** will prefer an individual uid entry over a group entry
	     **
	     ** For example, let us say there are two users u1 and u2
	     ** with uids 4 and 5 respectiveley and both u1 and u2
	     ** belong to a group g12 whose uid is 16390.  procedure p1
	     ** is owned by user u0 and user u0 performs the following
	     ** actions:
	     **
	     **		grant exec on p1 to g12
	     **		revoke grant on p1 from u1
	     **
	     ** There will be two entries in sysprotects for the object
	     ** p1, one for the group g12 where protecttype = grant (1)
	     ** and one for u1 where protecttype = revoke (2).
	     **
	     ** For the group g12, the following expression will
	     ** evaluate to:
	     **
	     **		((abs(16390-16390)*2) + ((1/2)^1))
	     **		= ((0) + (0)^1) = 0 + 1 = 1
	     **
	     ** For the user entry u1, it will evaluate to:
	     **
	     **		((abs(4-16390)*2) + ((2/2)^1))
	     **		= ((abs(-16386)*2 + (1)^1)
	     **		= 16386*2 + 0 = 32772 
	     **
	     ** As the expression evaluates to a bigger number for the
	     ** user entry u1, select max() will chose 32772 which,
	     ** ANDed with 1 gives 0, i.e., sp_stored_procedures will
	     ** not display this particular procedure to the user.
	     **
	     ** When the user u2 invokes sp_stored_procedures, there is
	     ** only one entry for u2, which is the entry for the group
	     ** g12, and so this entry will be selected thus allowing
	     ** the procedure in question to be displayed.
	     **
             ** NOTE: With the extension of the uid's into negative space, 
             ** and uid limits going beyond 64K, the original expression 
	     ** has been modified from
	     ** ((select max(((sign(uid)*abs(uid-16383))*2)
	     **		+ ((protecttype/2)^1))
	     ** to
	     ** ((select max((abs(uid-u.gid)*2)
	     **		+ ((protecttype/2)^1))
	     ** 
	     ** Notice that multiplying by 2 makes the number an
	     ** even number (meaning the last digit is 0) so what
	     ** matters at the end is (protecttype/2)^1.
	     **
	     */

	     or ((select max( (abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
		   from sysprotects p, sysusers u2
		   where p.id = o.id
		   and u2.uid = user_id()
		   /*
		   ** get rows for public, current users, user's groups
		   */
		   and (p.uid = 0  		/* get rows for public */
		        or p.uid = user_id()	/* current user */
		        or p.uid = u2.gid) 	/* users group */
			     
		   /*
		   ** check for SELECT, EXECUTE privilege.
		   */
	           and (p.action in (193,224))	/* check for SELECT,EXECUTE 
						** privilege 
						*/
		   )&1 			/* more magic...normalize GRANT */
	    	  ) = 1	 		/* final magic...compare Grants	*/
	     /*
	     ** If one of any user defined roles or contained roles for the
	     ** user has permission, the user has the permission
	     */
	     or exists(select 1
		from	sysprotects p1,
			master.dbo.syssrvroles srvro,
			sysroles ro
		where	p1.id = o.id
			and p1.uid = ro.lrid
			and ro.id = srvro.srid
			and has_role(srvro.name, 1) > 0
			and p1.action = 224))
		order by procedure_qualifier, procedure_owner,
			procedure_name
go
exec sp_procxmode 'sp_stored_procedures', 'anymode'
go
grant execute on sp_stored_procedures to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_unbindefault')
begin
	drop procedure sp_unbindefault
end
go
print "Installing sp_unbindefault"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */
 
/*
** Messages for "sp_unbindefault"       17840
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 17840, "Column or usertype must be in 'current' database."
** 17841, "Default unbound from table column."
** 17842, "The specified column has no default."
** 17843, "You do not own a table with a column of that name."
** 17844, "You do not own a user datatype of that name."
** 17845, "The specified user datatype has no default."
** 17846, "Default unbound from datatype."
** 17847, "Columns of the user datatype specified had their defaults unbound."
** 17848, "You cannot unbind a declared default. Use ALTER TABLE command."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
*/

create procedure sp_unbindefault
@objname varchar(511),			/* table/column or datatype name */
@futureonly varchar(15) = NULL		/* flag to indicate extent of binding */
as

declare @defid int			/* id of the default to unbind */
declare @futurevalue varchar(15)	/* the value of @futureonly that causes
					** the binding to be limited */
declare @msg varchar(1024)
declare @returncode int                 /* return from ad_hoc_audit builtin */
declare	@eventnum int		/* event number for bind default auditing */
declare	@mod_ok int		/* successful bind default auditing  */
declare	@mod_fail int		/* failure bind default auditing  */


select	@eventnum = 67		/* unbind default event number */	
select	@mod_ok = 1		
select	@mod_fail = 2		
declare @dbname varchar(255)
declare @tmp int
declare @rows_selected int



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set transaction isolation level 1

select @futurevalue = "futureonly"	/* initialize @futurevalue */

/*
**  When a default or rule is bound to a user-defined datatype, it is also
**  bound, by default, to any columns of the user datatype that are currently
**  using the existing default or rule as their default or rule.  This default
**  action may be overridden by setting @futureonly = @futurevalue when the
**  procedure is invoked.  In this case existing columns with the user
**  datatype won't have their existing default or rule changed.
*/

/*
**  Check to see that the object names are local to the current database.
*/
if @objname like "%.%.%"
begin
	/*
	** 17840, "Column or usertype must be in 'current' database."
	*/
	raiserror 17840
	return (1)
end

/*
**  If @objname is of the form tab.col then we are unbinding a column.
**  Otherwise its a datatype.  In the column case, we need to extract
**  and verify the table and column names and make sure the user owns
**  the table that is getting the default unbound.
*/
if @objname like "%.%"
begin
	declare @tabname varchar(255)		/* name of table */
	declare @colname varchar(255)		/* name of column */

	/*
	**  Get the table name out.
	*/
	select @tabname = substring(@objname, 1, charindex(".", @objname) - 1)
	select @colname = substring(@objname, charindex(".", @objname) + 1, 511)

	/*
	**  Find it.
	*/
	select @defid = syscolumns.cdefault
		from syscolumns, sysobjects
		where syscolumns.id = object_id(@tabname)
			and syscolumns.name = @colname
			and sysobjects.id = object_id(@tabname)
			and uid = user_id()
			and sysobjects.sysstat & 7 = 3	/* user table */

	if @defid is NULL
	begin
		/*
		**  17843, "You do not own a table with a column of that name."
		*/

		/* Audit the failure to unbind a default */
        	select @returncode =
        	ad_hoc_audit (@eventnum, @mod_fail, NULL, db_name(), 
			@tabname, user_name(), 0, object_id(@tabname)

			)
		raiserror 17843
		return (1)
	end



	/* Audit the succssful permission to unbind a default */
	select @returncode =
	ad_hoc_audit ( @eventnum, @mod_ok, NULL, db_name(), 
		@tabname, user_name(), 0, object_id(@tabname)

		)
	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
		raiserror 18293, @eventnum
		return (1)
	end
	/*
	**  Is there something bound to it?
	*/
	if @defid = 0
	begin
		/*
		** 17842, "The specified column has no default."
		*/
		raiserror 17842
		return (1)
	end
	/*
	** Check to see that the default is not of declared type
	*/

	if exists (select * from sysprocedures
			where id = @defid
			and sequence = 0
			and status & 4096 = 4096)
	begin
		/*
		** 17848, "You cannot unbind a declared default. Use ALTER TABLE command."
		*/
		raiserror 17848
		return (1)
	end
	
	/*
	**  Unbind it.
	*/

	/* 
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	update syscolumns
		set cdefault = 0
			from syscolumns, sysobjects
		where syscolumns.id = object_id(@tabname)
			and syscolumns.name = @colname
			and sysobjects.id = object_id(@tabname)
			and uid = user_id()
			and sysobjects.sysstat & 7 = 3

	/*
	**  Since binding a default is a schema change,
	**  update schema count
	**  for the object in the sysobjects table.
	*/

	if (schema_inc(object_id(@tabname), 0) != 1)
	begin
		/*
		** 17763, "The execution of the stored procedure '%1!'
		**         in database '%2!' was aborted because there
		**         was an error in updating the column
		**         schemacnt in sysobjects."
		*/
		select @dbname = db_name()
		raiserror 17763, "sp_unbindefault", @dbname
		rollback transaction rs_logexec
		return(1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_unbindefault", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17841, "Default unbound from table column."
	*/
	exec sp_getmessage 17841, @msg output
	print @msg
	return (0)
end
else
begin
	/*
	**  We're unbinding to a user type.  In this case, the @objname
	**  is really the name of the user datatype.
	**  When we unbind to a user type, any existing columns get changed
	**  to the new binding unless their current binding is not equal
	**  to the current binding for the usertype or if they set the
	**  @futureonly parameter to @futurevalue.
	*/
	declare @olddefault int			/* current default for type */

	/*
	**  Get the current default for the datatype.
	*/
	select @olddefault = tdefault
		from systypes
	where name = @objname
		and uid = user_id()
		and usertype > 100

	if @olddefault is null
	begin
		/*
		** 17844, "You do not own a user datatype of that name."
		*/

		/* Audit the failure to unbind a default */
        	select @returncode =
        	ad_hoc_audit ( @eventnum, @mod_fail, NULL, db_name(), 
			@objname, user_name(), 0, object_id(@objname)

			)
		raiserror 17844
		return (1)
	end


	/* Audit the succssful permission to unbind a default */
	select @returncode =
	ad_hoc_audit ( @eventnum, @mod_ok, NULL, db_name(), 
		@objname, user_name(), 0, object_id(@objname)

		)
	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
		raiserror 18293, @eventnum
		return (1)
	end
	if @olddefault = 0
	begin
		/*
		** 17845, "The specified user datatype has no default."
		*/
		raiserror 17845
		return (1)
	end

	/* 
	** This transaction also writes a log record for
	** replicating the invocation of this procedure.
	** If logexec() fails, the transaction is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is
	** used by Replication Server.
	*/
	begin transaction rs_logexec

	update systypes
		set tdefault = 0
			from systypes
		where name = @objname
			and uid = user_id()
			and usertype > 100

	/*
	** 17846, "Default unbound from datatype."
	*/
	exec sp_getmessage 17846, @msg output
        print @msg

	/*
	**  Now see if there are any columns with the usertype that
	**  need the new binding.
	*/

	select @rows_selected = 0
	if isnull(@futureonly, "") != @futurevalue
	begin
		select @rows_selected = count(distinct syscolumns.id)
				from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and syscolumns.cdefault = @olddefault

		if (@rows_selected > 0)
		begin
			/*
			**  Update the table schema to indicate that something
			**  has changed in the table's schema.
			*/
			select @tmp = sum(schema_inc(s.id, 0))
				from sysobjects s
				where exists
				(select 1
					from syscolumns, systypes
					where s.id = syscolumns.id
					and syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and syscolumns.cdefault = @olddefault)

			if (@rows_selected != @tmp)
			begin
				/*
				** 17763, "The execution of the stored procedure '%1!'
				**         in database '%2!' was aborted because there
				**         was an error in updating the column
				**         schemacnt in sysobjects."
				*/
				select @dbname = db_name()
				raiserror 17763, "sp_unbindefault", @dbname
				rollback transaction rs_logexec
				return(1)
			end

			/*
			**  Update syscolumns with new binding.
			*/
			update syscolumns
				set cdefault = systypes.tdefault
				from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
				and systypes.name = @objname
				and systypes.usertype > 100
				and systypes.uid = user_id()
				and syscolumns.cdefault = @olddefault
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure
		**         '%1!' in database '%2!' was aborted
		**	    because there was an error in writing
		**	    the replication log record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_unbindefault", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17847, "Columns of the user datatype specified had
	** their defaults unbound."
	*/
	exec sp_getmessage 17847, @msg output
	print @msg

end

return (0)
go
exec sp_procxmode 'sp_unbindefault', 'anymode'
go
grant execute on sp_unbindefault to public
go
exec sp_procxmode 'sp_unbindefault', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_unbindrule')
begin
	drop procedure sp_unbindrule
end
go
print "Installing sp_unbindrule"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */
 
/*
** Messages for "sp_unbindrule"         17850
**
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 17840, "Column or usertype must be in 'current' database."
** 17843, "You do not own a table with a column of that name."
** 17844, "You do not own a user datatype of that name." 
** 17850, "Rule unbound from table column."
** 17851, "The specified column has no rule."
** 17852, "The specified user datatype has no rule."
** 17853, "Rule unbound from datatype."
** 17854, "Columns of the user datatype specified had their rules unbound."
** 17855, "You cannot unbind a declared constraint. Use ALTER TABLE command."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
*/

create procedure sp_unbindrule
@objname varchar(511),			/* table/column or datatype name */
@futureonly varchar(15) = NULL,		/* flag to indicate extent of binding */
@whichrule varchar(15) = NULL
as

declare @tot_constr int			/* total number of constraints */
declare @colid smallint			/* column id */
declare @futurevalue varchar(15)	/* the value of @futureonly that causes
					** the binding to be limited */
declare @msg varchar(1024)
declare @returncode int                 /* return from ad_hoc_audit builtin */
declare	@eventnum int		/* event number for bind default auditing */
declare	@mod_ok int		/* successful bind default auditing  */
declare	@mod_fail int		/* failure bind default auditing  */
declare @dbname varchar(255)
declare @tmp int
declare @rows_selected int
declare @access_rule	int	/* 0        - not an access rule.
				** 16777216 - is an access rule. This is
				** the bit in sysobjects.sysstat2 
				** that marks an
				** access_rule.
				*/
select	@eventnum = 68		/* eventnumber for unbind rule */
select	@mod_ok = 1		
select	@mod_fail = 2		
select  @access_rule = 16777216

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set transaction isolation level 1

select @futurevalue = "futureonly"	/* initialize @futurevalue */

/*
**  When a default or rule is bound to a user-defined datatype, it is also
**  bound, by default, to any columns of the user datatype that are currently
**  using the existing default or rule as their default or rule.  This default
**  action may be overridden by setting @futureonly = @futurevalue when the
**  procedure is invoked.  In this case existing columns with the user
**  datatype won't have their existing default or rule changed.
*/

/*
**  Check to see that the object names are local to the current database.
*/
if @objname like "%.%.%"
begin
	/*
	** 17840, "Column or usertype must be in 'current' database."
	*/
	raiserror 17840
	return (1)
end

/*
**  Check that the @futureonly argument, if supplied, is correct.
*/
if (@futureonly is not null)
begin
        if (@futureonly != @futurevalue)
        begin
                /*
                ** 17856, "Usage: sp_unbindrule objectname [,NULL| 'futureonly']
		**			[,"all"| "accessrule"]"
                */
                raiserror 17856
                return (1)
        end
end

/*
**	Check that the @whichrule argument, if supplied, is correct.
*/
if (@whichrule is not null)
begin
        if ((@whichrule != "all") and (@whichrule != "accessrule"))
        begin
                /*
                ** 17856, "Usage: sp_unbindrule objectname [,NULL| 'futureonly']
		**			[,"all"| "accessrule"]"
                */
                raiserror 17856
                return (1)
        end
end


/*
**  If @objname is of the form tab.col then we are unbinding a column.
**  Otherwise its a datatype.  In the column case, we need to extract
**  and verify the table and column names and make sure the user owns
**  the table that is getting the default unbound.
*/
if @objname like "%.%"
begin
	declare @tabname varchar(255)		/* name of table */
	declare @colname varchar(255)		/* name of column */

	/*
	**  Get the table name out.
	*/
	select @tabname = substring(@objname, 1, charindex(".", @objname) - 1)
	select @colname = substring(@objname, charindex(".", @objname) + 1, 511)

	/*
	**  Find it.
	*/
	if not exists (select syscolumns.colid
		from syscolumns, sysobjects
		where syscolumns.id = object_id(@tabname)
			and syscolumns.name = @colname
			and sysobjects.id = object_id(@tabname)
			and uid = user_id()
			and sysobjects.sysstat & 7 = 3)      /* user table */

	begin
		/*
		** 17843, "You do not own a table with a column of that name."
		*/
		/* Audit the failure to unbind a rule */
        	select @returncode =
        	ad_hoc_audit (@eventnum, @mod_fail, NULL, db_name(), 
			@tabname, user_name(), 0, object_id(@tabname)
			)
		raiserror 17843
		return (1)
	end
	/* Audit the successful permission to unbind a rule */
	select @returncode =
	ad_hoc_audit (@eventnum, @mod_ok, NULL, db_name(), 
		@tabname, user_name(), 0, object_id(@tabname)
			)

	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
		raiserror 18293, @eventnum
		return (1)
	end
	/*
	**  Is there something bound to it?
	*/
	if (@whichrule is NULL and 
	   exists (select syscolumns.colid
                from syscolumns, sysobjects
                where syscolumns.id = object_id(@tabname)
                        and syscolumns.name = @colname
                        and sysobjects.id = object_id(@tabname)
                        and uid = user_id()
                        and sysobjects.sysstat & 7 = 3      /* user table */ 
			and syscolumns.domain = 0))
	begin
		/*
		** 17851, "The specified column has no rule."
		*/
		raiserror 17851
		return (1)
	end
	if (@whichrule = "accessrule" and 
	   exists (select syscolumns.colid
                from syscolumns, sysobjects
                where syscolumns.id = object_id(@tabname)
                        and syscolumns.name = @colname
                        and sysobjects.id = object_id(@tabname)
                        and uid = user_id()
                        and sysobjects.sysstat & 7 = 3      /* user table */ 
			and 
			(syscolumns.accessrule = 0 
			 or 
			 syscolumns.accessrule is NULL)))
	begin
		/*
		** FGAC_RESOLVE: qualify the msg with what rule 
		** 17851, "The specified column has no rule."
		*/
		raiserror 17851
		return (1)
	end
	if (@whichrule = "all" and 
	   exists (select syscolumns.colid
                from syscolumns, sysobjects
                where syscolumns.id = object_id(@tabname)
                        and syscolumns.name = @colname
                        and sysobjects.id = object_id(@tabname)
                        and uid = user_id()
                        and sysobjects.sysstat & 7 = 3      /* user table */ 
			and 
			(syscolumns.domain = 0 
			 and
			 isnull(syscolumns.accessrule, 0) = 0 
			) 
		))
	begin
		/*
		** FGAC_RESOLVE: qualify the msg with what rule 
		** 17851, "The specified column has no rule."
		*/
		raiserror 17851
		return (1)
	end
	

	/*
	** Check to see that the rule is not of declared type
	*/

	if ( (@whichrule is NULL) and
		exists (select * from sysprocedures
			where id = (select syscolumns.domain
				    from syscolumns, sysobjects
				    where syscolumns.id = object_id(@tabname)
					and syscolumns.name = @colname
					and sysobjects.id = object_id(@tabname)
					and uid = user_id() 
					and sysobjects.sysstat & 7 = 3)
						/* user table */ 
			and sequence = 0
			and status & 4096 = 4096))
	begin
		/*
		** 17855, "You cannot unbind a declared constraint. Use ALTER TABLE command."
		*/
		raiserror 17855
		return (1)
	end

        /*
        ** Check to see that the rule is not of declared type
        */

        if ( (@whichrule = "all") and
                exists (select * from sysprocedures
                        where id = (select syscolumns.domain
                                    from syscolumns, sysobjects
                                    where syscolumns.id = object_id(@tabname)
                                        and syscolumns.name = @colname
					and isnull(syscolumns.accessrule, 0) = 0
                                        and sysobjects.id = object_id(@tabname)
                                        and uid = user_id()
                                        and sysobjects.sysstat & 7 = 3)
                                                /* user table */
                        and sequence = 0
                        and status & 4096 = 4096))
        begin
                /*
                ** 17855, "You cannot unbind a declared constraint. 
		** Use ALTER TABLE command."
                */
                raiserror 17855
                return (1)
        end

	
	/*
	** If the status of the column reflects having more than one rule,
	** check if there indeed is more than one rules. If there is more
	** reset the domain field w/ a new rule.
	*/

	select @colid = syscolumns.colid
                from syscolumns, sysobjects
                where syscolumns.id = object_id(@tabname)
                        and syscolumns.name = @colname
                        and sysobjects.id = object_id(@tabname)
                        and uid = user_id()
                        and sysobjects.sysstat & 7 = 3

	select @tot_constr = count(*)
	from sysconstraints
	where tableid = object_id(@tabname)
		and colid = @colid

	/*
	**  Unbind it.
	*/
	if (@tot_constr > 1 and (@whichrule = "all" or @whichrule is NULL))
	begin
		update syscolumns
			set domain = (select max(constrid)
					from sysconstraints
					where tableid = object_id(@tabname)
						and colid = @colid)
				from syscolumns, sysobjects
			where syscolumns.id = object_id(@tabname)
				and syscolumns.name = @colname
				and sysobjects.id = object_id(@tabname)
				and uid = user_id()
				and sysobjects.sysstat & 7 = 3
	end
	else if (@tot_constr > 0 and (@whichrule = "all" or @whichrule is NULL))
	begin
		update syscolumns
			set domain = (select max(constrid)
					from sysconstraints
					where tableid = object_id(@tabname)
						and colid = @colid),
				status = syscolumns.status & 239
				from syscolumns, sysobjects
			where syscolumns.id = object_id(@tabname)
				and syscolumns.name = @colname
				and sysobjects.id = object_id(@tabname)
				and uid = user_id()
				and sysobjects.sysstat & 7 = 3
	end
	else if (@whichrule = "all" or @whichrule is NULL)
	begin
		update syscolumns
			set domain = 0
				from syscolumns, sysobjects
			where syscolumns.id = object_id(@tabname)
				and syscolumns.name = @colname
				and sysobjects.id = object_id(@tabname)
				and uid = user_id()
				and sysobjects.sysstat & 7 = 3
	end

	if (@whichrule = "all" or @whichrule = "accessrule")
	begin
		update syscolumns
			set accessrule = 0
				from syscolumns, sysobjects
			where syscolumns.id = object_id(@tabname)
				and syscolumns.name = @colname
				and sysobjects.id = object_id(@tabname)
				and uid = user_id()
				and sysobjects.sysstat & 7 = 3
	end	

        /*
        ** If we just unbound an access rule from this column, zero out 
        ** the accessrule column. Also, check all of the remaining
        ** columns of this table to see if any have an access rule
        ** on them - if not, remove the access-rule bit from
        ** sysobjects for this table.
        */
        if (@access_rule > 0 and
                         (@whichrule = "all" or @whichrule = "accessrule"))
        begin
                update syscolumns
                        set accessrule = 0
                                from syscolumns, sysobjects
                        where syscolumns.id = object_id(@tabname)
                                and syscolumns.name = @colname
                                and sysobjects.id = object_id(@tabname)
                                and uid = user_id()
                                and sysobjects.sysstat & 7 = 3

                /*
                ** If there are other columns with an access rule,
                ** reset @access_rule to 0, so that when we AND in
                ** ~@access_rule to the sysobjects row for this table,
                ** in the next update query, the 0x01000000 bit will
                ** not get reset.
                */
                if exists ( select * from syscolumns
                            where id = object_id(@tabname)
                                and isnull(accessrule, 0)  > 0)

                begin
                        select @access_rule = 0
                end
	end
	/*
	**  Since binding a rule is a schema change,
	**  update schema count
	**  for the object in the sysobjects table.
	*/

	/* 
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	begin transaction rs_logexec

	if (schema_inc(object_id(@tabname), 0) != 1)
	begin
		/*
		** 17763, "The execution of the stored procedure '%1!'
		**         in database '%2!' was aborted because there
		**         was an error in updating the column
		**         schemacnt in sysobjects."
		*/
		select @dbname = db_name()
		raiserror 17763, "sp_unbindrule", @dbname
		rollback transaction rs_logexec
		return(1)
	end

	update sysobjects
		set sysstat2 = sysstat2 & ~@access_rule
		from sysobjects
		where id = object_id(@tabname)
		and uid = user_id()

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_unbindrule", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17850, "Rule unbound from table column."
	*/
	exec sp_getmessage 17850, @msg output
        print @msg  
	return (0)
end
else
begin
	/*
	**  We're unbinding to a user type.  In this case, the @objname
	**  is really the name of the user datatype.
	**  When we unbind to a user type, any existing columns get changed
	**  to the new binding unless their current binding is not equal
	**  to the current binding for the usertype or if they set the
	**  @futureonly parameter to @futurevalue.
	*/
	declare @oldrule int			/* current rule for type */
	declare @oldaccessrule int /* current access rule for type */
	/*
	**  Get the current rule for the datatype.
	*/
	select @oldrule = domain, @oldaccessrule = accessrule
		from systypes
	where name = @objname
		and uid = user_id()
		and usertype > 100

	if @oldrule is null
	begin
		/*
		** 17844, "You do not own a user datatype of that name." 
		*/
		/* Audit the failure to unbind a rule */
        	select @returncode =
        	ad_hoc_audit (@eventnum, @mod_fail, NULL, db_name(), 
			@objname, user_name(), 0, object_id(@objname)
			)
		raiserror 17844
		return (1)
	end

	/* Audit the successful permission to unbind a rule */
	select @returncode =
	ad_hoc_audit (@eventnum, @mod_ok, NULL, db_name(), 
		@objname, user_name(), 0, object_id(@objname)
			)
	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
		raiserror 18293, @eventnum
		return (1)
	end

	if(@whichrule = "accessrule")
	begin
		if ( (@oldaccessrule is NULL) or (@oldaccessrule = 0))
		begin
			/*
			** 17852, "The specified user datatype has no rule."
			*/
			raiserror 17852
			return (1)
		end
	end
	else if (@whichrule = "all")
	begin
		if( ((@oldaccessrule is NULL) or (@oldaccessrule = 0))
				and (@oldrule = 0) )
                begin
                        /*
                        ** 17852, "The specified user datatype has no rule."
                        */
                        raiserror 17852
                        return (1)
                end
        end
	else
	begin
		if( @oldrule = 0)
		begin
                        /*
                        ** 17852, "The specified user datatype has no rule."
                        */
                        raiserror 17852
                        return (1)
		end
	end


	/* 
	** This transaction also writes a log record for
	** replicating the invocation of this procedure. If
	** logexec() fails, the transaction is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and
	** is used by Replication Server.
	*/
	begin transaction rs_logexec

	if (@whichrule = "all")
	begin
		update systypes
		       set domain = 0,
		           accessrule = 0
			   from systypes
		where name = @objname
			and uid = user_id()
			and usertype > 100
	end
	else if (@whichrule = "accessrule")
	begin
		update systypes
		       set accessrule = 0
			   from systypes
		where name = @objname
		      and uid = user_id()
		      and usertype > 100
	end
	else 
	begin	      	  
		update systypes
		       set domain = 0
			   from systypes
		where name = @objname
		      and uid = user_id()
		      and usertype > 100
	end
	
	/*
	** 17853, "Rule unbound from datatype."
	*/
	exec sp_getmessage 17853, @msg output
        print @msg  

	/*
	**  Now see if there are any columns with the usertype that
	**  need the new binding.
	*/
	select @rows_selected = 0
	if isnull(@futureonly, "") != @futurevalue
	begin
		select @rows_selected = count(distinct syscolumns.id)
                                from syscolumns, systypes
                                where syscolumns.usertype = systypes.usertype
                                        and systypes.name = @objname
                                        and systypes.usertype > 100
                                        and systypes.uid = user_id()
                                        and 
					(syscolumns.domain = @oldrule
					 or
					 syscolumns.accessrule = @oldaccessrule
					)

		if (@rows_selected > 0)
		begin
			/*
			**  Update the table schema to indicate that something
			**  has changed in the table's schema.
			*/

			select @tmp = sum(schema_inc(s.id, 0))
					from sysobjects s
					where exists
					(select 1
						from syscolumns, systypes
						where s.id = syscolumns.id
						and syscolumns.usertype = systypes.usertype
						and systypes.name = @objname
						and systypes.usertype > 100
						and systypes.uid = user_id()
						and 
						(syscolumns.domain = @oldrule
						 or
						 syscolumns.accessrule = @oldaccessrule
						))

			if (@rows_selected != @tmp)
			begin
				/*
				** 17763, "The execution of the stored procedure '%1!'
				**         in database '%2!' was aborted because there
				**         was an error in updating the column
				**         schemacnt in sysobjects."
				*/
				select @dbname = db_name()
				raiserror 17763, "sp_unbindrule", @dbname
				rollback transaction rs_logexec
				return(1)
			end

			/*
			**  Update syscolumns with new binding.
			*/
			if (@whichrule = "all")
			begin
				update syscolumns
			       	set domain = systypes.domain,
				   	accessrule = systypes.accessrule
					from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and syscolumns.domain = @oldrule
			end
			else if (@whichrule = "accessrule")
			begin
				update syscolumns
			       	set accessrule = systypes.accessrule
			       	from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and syscolumns.domain = @oldrule
			end
			else
			begin
				update syscolumns
			       	set domain = systypes.domain
					from syscolumns, systypes
				where syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and syscolumns.domain = @oldrule
			end

			if (@access_rule > 0 and 
		    	(@whichrule = "accessrule" or @whichrule = "all"))
			begin
				/*
				** Now that we have removed the "access-rule"
				** status bit from the syscolumns entry, check
				** if any other columns of the tables that have
				** this bit set still have access-rules: if not,
				** reset the access-rule bit in the sysobjects
				** row for these tables.
				*/
				update sysobjects
			    	set sysstat2 = sysstat2 & ~@access_rule
			    	from sysobjects, syscolumns, systypes
			    	where sysobjects.id = syscolumns.id
					and syscolumns.usertype = systypes.usertype
					and systypes.name = @objname
					and systypes.usertype > 100
					and systypes.uid = user_id()
					and not exists ( select * from syscolumns
				    	where syscolumns.id = sysobjects.id
				    	and isnull(syscolumns.accessrule,0) > 0)
			end
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure
		**         '%1!' in database '%2!' was aborted
		**	    because there was an error in writing
		**	    the replication log record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_unbindrule", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/*
	** 17854, "Columns of the user datatype specified 
	** had their rules unbound."
	*/
	exec sp_getmessage 17854, @msg output
       	print @msg  
end

return (0)


go
exec sp_procxmode 'sp_unbindrule', 'anymode'
go
grant execute on sp_unbindrule to public
go
exec sp_procxmode 'sp_unbindrule', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_who')
begin
	drop procedure sp_who
end
go
print "Installing sp_who"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/serveroption */

/*
** Messages for "sp_who"		17nnn
** 
** 17231, "No login with the specified name exists." 
*/

create procedure sp_who @loginame varchar(255) = NULL as

declare @low int
declare @high int
declare @spidlow int
declare @spidhigh int
declare @len1 int, @len2 int, @len3 int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @low = @@minsuid, @high = @@maxsuid, 
       @spidlow = @@minspid, @spidhigh = @@maxspid

if @loginame is not NULL
begin
	select @low = suser_id(@loginame), @high = suser_id(@loginame)
	if @low is NULL
	begin
		if @loginame like "[0-9]%"
		begin
			select @spidlow = convert(int, @loginame),
			     @spidhigh = convert(int, @loginame),
			     @low = @@minsuid, @high = @@maxsuid
		end
		else
		begin
			/*
			** 17231, "No login with the specified name exists." 
			*/
			raiserror 17231
			return (1)
		end
	end
end

	select fid,spid,status,loginame=suser_name(suid),
	   origname=isnull(suser_name(origsuid), suser_name(suid)), hostname,
	   blk_spid=blocked, dbname=db_name(dbid), 
	   tempdbname=db_name(tempdb_id(spid)), cmd, block_xloid
	into #who1result
	from master..sysprocesses
	where suid >= @low and suid <= @high
	and spid >= @spidlow and spid <= @spidhigh

	exec sp_autoformat @fulltabname = #who1result,
	@selectlist = "fid, spid, status, loginame, origname, hostname, blk_spid, dbname, tempdbname, cmd, block_xloid",
	@orderby = "order by fid, spid, dbname"

	drop table #who1result	


return (0)

go
exec sp_procxmode 'sp_who', 'anymode'
go
grant execute on sp_who to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_client_addr')
begin
	drop procedure sp_client_addr
end
go
print "Installing sp_client_addr"
go


/*
** sp_client_addr               
**
**  Stored procedure to pull client ip addresses from sysprocesses table
**  Requires ASE 12.5 or later
**
**  messages raised:
**   18934, "spid not found" 
*/

create procedure sp_client_addr @spid int = NULL as

declare @count int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

if @spid is not NULL
begin
	select @count=count(*) from master..sysprocesses where spid=@spid
	if (@count=0)
	begin		
		/*
		** 18934, "spid not found" 
		*/
		raiserror 18934
		return (1)
	end

	select spid,hostname,ipaddr from master..sysprocesses where spid=@spid
end

else
begin
	select spid,hostname,ipaddr from master..sysprocesses where ipaddr is not NULL
end

return (0)

go
exec sp_procxmode 'sp_client_addr', 'anymode'
go
grant execute on sp_client_addr to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_transactions')
begin
	drop procedure sp_transactions
end
go
print "Installing sp_transactions"
go

/*
** This stored procedure displays information about active
** transactions. sp_transactions can be invoked in one of the following
** modes:  
**
** o sp_transactions 			  -- Display about all txns 
**
** o sp_transactions "xid", <xid-val>	  -- Display info about a
**					     particular xid.  
** o sp_transactions "state", 
**		     "heuristic_commit|heuristic_abort|prepared|indoubt"
**		     [,"xactname"]
**					  -- Display a transaction info 
**					     about all transactins in the 
**					     specified state. If the optional
**					     xactname parameter is specified,
**					     we will select only the xactname
**					     column. 
**
**
** o sp_transactions "gtrid", <gtrid-val> -- Display info for a particular 
**					     gtrid which is one of the
**					     components of xid.
**
** o sp_transactions "xa_recover" 	  -- Used only for xa support.
**					     Do not document this option.
**				
*/

/*
** Messages for "sp_transactions"		18nnn
** 
** 18703  "Please execute the procedure '%1!' from master database".
** 18563, "A transaction name should be specified."
** 18564, "Invalid option. Possible values are: xid and state."
** 18565, "Invalid value for state. Legal values are: heuristic_commit 
**	   heuristic_abort  prepared indoubt."
*/

create procedure sp_transactions 
@query_type	varchar(30) = NULL,
@parm1		varchar(255) = NULL,
@parm2		varchar(255) = NULL
as

declare @transtate int
declare @transtat2 int
declare @xid_only  int
declare @msg varchar(250)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @xid_only = 0

if @query_type is NULL
begin
		select xactkey,
			type = convert(char(11),v3.name),
			coordinator = convert(char(10), v4.name),
			starttime=convert(char(20), starttime),
			state = convert(char(17),v1.name),
			connection = convert(char(9), v2.name),
			dbid=masterdbid, spid, loid,
			failover = convert(char(26), v5.name),
			s.srvname, namelen, xactname

		from master..systransactions s, master..spt_values v1,
		     master..spt_values v2, master..spt_values v3,
		     master..spt_values v4, master..spt_values v5
		where
			s.state = v1.number and v1.type = 'T1'
		and     s.connection = v2.number and v2.type = 'T2'
		and     s.type = v3.number and v3.type = 'T3'
		and     s.coordinator = v4.number and v4.type = 'T4'
		and     s.failover = v5.number and v5.type = 'T5'
			order by xactkey, s.srvname, s.failover
	return (0)
end

if @query_type = "xid"
begin
	if @parm1 is NULL
	begin
		raiserror 18563, "sp_transactions"
		return (1)
	end
	else
	begin
		select xactkey,
			type = convert(char(11),v3.name),
			coordinator = convert(char(10), v4.name),
			starttime=convert(char(20), starttime),
			state = convert(char(17),v1.name),
			connection = convert(char(9), v2.name),
			dbid=masterdbid, spid, loid,
			failover = convert(char(26), v5.name),
			s.srvname, namelen, xactname,
			commit_node =
			 coord_node_name(xactname, s.coordinator, s.type, 7),
			parent_node =
			 coord_node_name(xactname, s.coordinator, s.type, 8),
			gtrid =
			 gtrid(xactname, s.coordinator, s.xactkey, s.failover)

		from master..systransactions s, master..spt_values v1,
		     master..spt_values v2, master..spt_values v3,
		     master..spt_values v4, master..spt_values v5
		where
			s.xactname like "%"+@parm1+"%"
		and     s.state = v1.number and v1.type = 'T1'
		and     s.connection = v2.number and v2.type = 'T2'
		and     s.type = v3.number and v3.type = 'T3'
		and     s.coordinator = v4.number and v4.type = 'T4'
		and     s.failover = v5.number and v5.type = 'T5'
			order by xactkey, s.srvname, s.failover

	   return 0
	end 
end


/*
** If we are interested in finding a row for a particular gtrid,
** try to find it.
*/
if @query_type = "gtrid"
begin
	if @parm1 is NULL
	begin
		raiserror 18563, "sp_transactions"
		return (1)
	end
	else
	begin
		select xactkey,
			type = convert(char(11),v3.name),
			coordinator = convert(char(10), v4.name),
			starttime=convert(char(20), starttime),
			state = convert(char(17),v1.name),
			connection = convert(char(9), v2.name),
			dbid=masterdbid, spid, loid,
			failover = convert(char(26), v5.name),
			s.srvname, namelen, xactname,
			commit_node =
			 coord_node_name(xactname, s.coordinator, s.type, 7),
			parent_node =
			 coord_node_name(xactname, s.coordinator, s.type, 8)

		from master..systransactions s, master..spt_values v1,
		     master..spt_values v2, master..spt_values v3,
		     master..spt_values v4, master..spt_values v5
		where
			s.state = v1.number and v1.type = 'T1'
		and     s.connection = v2.number and v2.type = 'T2'
		and     s.type = v3.number and v3.type = 'T3'
		and     s.coordinator = v4.number and v4.type = 'T4'
		and     s.failover = v5.number and v5.type = 'T5'
		and     gtrid(s.xactname, s.coordinator,
			      s.xactkey, s.failover) = @parm1
		and     s.type != 99
			order by xactkey, s.srvname, s.failover	
		return 0
	end
end

/*
** Select a list of transactions that satisfies xa requirements.
** Do not change this select without taking xalib into account.
*/
if @query_type = "xa_recover"
begin
		select xactname
 
		from master..systransactions s
		where s.state in ( (65536 | 12), (65536 | 13),
			4, (65536 | 4))
		and s.coordinator = 3

	/*
	** Find if there is any database that is not recovered.
	** If so return with a status of 1 to indicate to XA Interface
	** that not all databases have been recovered and hence the
	** list of in-doubt transactions may be incomplete. XA Interface
	** knows what to do with this information.
	*/
	if exists (select * from master..sysdatabases 
		   where (status & 64) != 0)
		return (1)
	else
		return (0)
end
	
/* The only query possible is by "state" */
if @query_type != "state"
begin
	raiserror 18564, "sp_transactions"
	return (1)
end

if @parm1 = "heuristic_commit"
begin
	select @transtate = (65536 | 12)
	select @transtat2 = (65536 | 12)
end
else if @parm1 = "heuristic_abort"
begin
	select @transtate = (65536 | 13)
	select @transtat2 = (65536 | 13)
end
else if @parm1 = "prepared"
begin
	select @transtate = 4
	select @transtat2 = (65536 | 4)
end
/* else, the only other valid value is indoubt in which case we return
** all the above states.  
*/
else if @parm1 != "indoubt"
begin
	raiserror 18565, "sp_transactions"
	return (1)
end

if @parm2 = "xactname"
begin
	select @xid_only = 1
end

/* Now, execute different queries based on xid_only and @parm1 */

if @xid_only = 1
begin
	if @parm1 = "indoubt"
	begin
			select xactname

			from master..systransactions
			where state in ( (65536 | 12), (65536 | 13),
				4, (65536 | 4))
	end
	else if @parm1 != NULL
	begin
			select xactname

			from master..systransactions
			where state = @transtate or state = @transtat2
	end
	else
	begin
			select xactname

			from master..systransactions
	end
end
else
begin
	if @parm1 = "indoubt"
	begin

		select xactkey,
			type = convert(char(11),v3.name),
			coordinator = convert(char(10), v4.name),
			starttime=convert(char(20), starttime),
			state = convert(char(17),v1.name),
			connection = convert(char(9), v2.name),
			dbid=masterdbid, spid, loid,
			failover = convert(char(26), v5.name),
			s.srvname, namelen, xactname

		from master..systransactions s, master..spt_values v1,
		     master..spt_values v2, master..spt_values v3,
		     master..spt_values v4, master..spt_values v5
		where s.state in ( (65536 | 12), (65536 | 13),
				4, (65536 | 4) )
		and     s.state = v1.number and v1.type = 'T1'
		and     s.connection = v2.number and v2.type = 'T2'
		and     s.type = v3.number and v3.type = 'T3'
		and     s.coordinator = v4.number and v4.type = 'T4'
		and     s.failover = v5.number and v5.type = 'T5'
			order by xactkey, s.srvname, s.failover
	end
	else if @parm1 != NULL
	begin
		select xactkey,
			type = convert(char(11),v3.name),
			coordinator = convert(char(10), v4.name),
			starttime=convert(char(20), starttime),
			state = convert(char(17),v1.name),
			connection = convert(char(9), v2.name),
			dbid=masterdbid, spid, loid,
			failover = convert(char(26), v5.name),
			s.srvname, namelen, xactname

		from master..systransactions s, master..spt_values v1,
		     master..spt_values v2, master..spt_values v3,
		     master..spt_values v4, master..spt_values v5
		where
			(s.state = @transtate or s.state = @transtat2)
		and     s.state = v1.number and v1.type = 'T1'
		and     s.connection = v2.number and v2.type = 'T2'
		and     s.type = v3.number and v3.type = 'T3'
		and     s.coordinator = v4.number and v4.type = 'T4'
		and     s.failover = v5.number and v5.type = 'T5'
			order by xactkey, s.srvname, s.failover
	end
	else
	begin
		select xactkey,
			type = convert(char(11),v3.name),
			coordinator = convert(char(10), v4.name),
			starttime=convert(char(20), starttime),
			state = convert(char(17),v1.name),
			connection = convert(char(9), v2.name),
			dbid=masterdbid, spid, loid,
			failover = convert(char(26), v5.name),
			s.srvname, namelen, xactname

		from master..systransactions s, master..spt_values v1,
		     master..spt_values v2, master..spt_values v3,
		     master..spt_values v4, master..spt_values v5
		where
			s.state = v1.number and v1.type = 'T1'
		and     s.connection = v2.number and v2.type = 'T2'
		and     s.type = v3.number and v3.type = 'T3'
		and     s.coordinator = v4.number and v4.type = 'T4'
		and     s.failover = v5.number and v5.type = 'T5'
			order by xactkey, s.srvname, s.failover
	end
end

return 0
go
exec sp_procxmode 'sp_transactions', 'anymode'
go
grant execute on sp_transactions to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
/*
** Include all dtm related installation work here
*/
/*
** raiserror Messages for dtm_inst [Total 1]
**
** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
*/

print "Installing DTM-related changes"

/*
** Adaptive Server Transaction Coordinator requires 'probe' login to
** resolve distributed transaction participants.
**
** Therefore, make sure the 'probe' login exists and has a default database
** of 'sybsystemdb'.
**
** Remember that the 'installmaster' script can be run against a 'master'
** database that is marked for replication.  Therefore, minimize login
** manipulation to avoid un-necessary replication.
*/
if not exists (select * from master.dbo.syslogins where name = "probe")
begin
	/*
	** The 'probe' login is missing.  Before creating the 'probe'
	** login, clean up any orphaned 'probe' users in the 'master' and
	** 'sybsystemdb' databases.
	*/
	if exists (select * from master.dbo.sysusers where name = "probe")
	begin
		use master
		execute sp_dropuser probe
	end
	if exists (select * from sybsystemdb.dbo.sysusers where name = "probe")
	begin
		use sybsystemdb
		execute sp_dropuser probe
	end

	/*
	** Create the 'probe' login.  Make sure we are in the 'master'
	** database when we do this otherwise we will fail if the 'master'
	** database is marked for replication.
	*/
	use master
	execute sp_addlogin probe, "dontcare", sybsystemdb
end
else
begin
	/*
	** The 'probe' login exists.  If the 'probe' login has a default
	** database other than 'sybsystemdb', change the default database
	** to 'sybsystemdb'.  Make sure we are in the 'master' database
	** when we do this otherwise we will fail if the 'master' database
	** is marked for replication.
	*/
	if not exists (select * from master.dbo.syslogins
		       where name = 'probe' and dbname = "sybsystemdb")
	begin
		use master
		execute sp_defaultdb probe, sybsystemdb
	end
end
go

/*
** Create the 'probe' user in the 'master' database if it is not already
** there
*/
if not exists (select * from master.dbo.sysusers where name = "probe")
begin
	use master
	execute sp_adduser probe
end
go

/*
** Create the 'probe' user in the 'sybsystemdb' database if it is not
** already there
*/
if not exists (select * from sybsystemdb.dbo.sysusers where name = "probe")
begin
	use sybsystemdb
	execute sp_adduser probe
end
go

/*
** Add guest user to sybsystemdb so that 2PC stored procedures can be
** executed.
*/
use sybsystemdb
go

if (db_name() != "sybsystemdb")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemdb"
	select syb_quit()
end
go

if not exists (select * from sybsystemdb.dbo.sysusers where name = "guest")
begin
        execute sp_adduser guest, guest
end
go

grant select on syscoordinations to public
go

/*
** We were in the middle of installmaster. Go back
*/
use sybsystemprocs
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dtx_purge_completedxacts')
begin
	drop procedure sp_dtx_purge_completedxacts
end
go
print "Installing sp_dtx_purge_completedxacts"
go

/*
** sp_dtx_purge_completedxacts
**
** This stored procedure deletes all the logically deleted distributed
** transaction meta-data in sybsystemdb..syscoordinations system catalog.
** As a part of diagnostics, the server can be booted with an option to
** not physically delete syscoordinations meta-data after a distributed
** transaction commits or aborts. Instead, the row(s) will be logically
** deleted. With this stored procedure, such row(s) can physically
** deleted.
**
** Parameters:
**	None.
**
** Returns:
**	1 - if error.
**	0 - if no error.
*/

create procedure sp_dtx_purge_completedxacts
as

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_dtx_purge_completedxacts"
	return (1)
end

/* we don't want row count information */
set nocount on

/* Must have sa_role */
if (proc_role("sa_role") < 1)
	return (1)

/*
** Deletes syscoordinations distributed transactions meta-data that
** are logically deleted and managed by dtm services.
*/
delete from sybsystemdb.dbo.syscoordinations
	where (owner = 1) and ((status & 1) = 1) 

return (0)
go
exec sp_procxmode 'sp_dtx_purge_completedxacts', 'anymode'
go
grant execute on sp_dtx_purge_completedxacts to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_fix_dtm_ha_roles')
begin
	drop procedure sp_fix_dtm_ha_roles
end
go
print "Installing sp_fix_dtm_ha_roles"
go

/*
** Messages for "sp_fix_dtm_ha_roles"          18040
**
** 18040, "Catalog procedure '%1!' can not be run in a transaction.
**
** dtm_tm_role and ha_role metadata is not added to the
** system catalog as part of an upgrade from 11.5.x or 11.9.x to 12.0.
** This stored procedure can be used to fix these catalogs if a
** customer has already upgraded from 11.5.x or 11.9.x to 12.0.
**
** NOTE that an upgrade from 11.0.x to 12.0 does not require this
** stored procedure to be executed nor for an upgrade from
** 11.5.x or 11.9.x to a version that is greater than or equal
** to 12.0.0.1 ESD#1.
*/
create procedure sp_fix_dtm_ha_roles
as
declare @sqlstr	varchar(255)
declare @dbname	varchar(30)
declare @rid int
declare @failure int
declare @msg varchar(255)

if (@@trancount > 0)
begin
	/*
	** 18040, "Catalog procedure '%1!' can not be run in a transaction.
	*/
	raiserror 18040, "sp_fix_dtm_ha_roles"
	return (1)
end

/*
** Check if the user has sa role.  Builtin proc_role() will
** also do auditing if required as well as print an error
** message if needed.
*/
if (proc_role("sa_role") = 0)
	return (1)

set transaction isolation level 1
set chained off

/* In case these roles are not in syssrvroles */

if not exists (select 1 from master.dbo.syssrvroles where srid = 7) 
begin
	insert into master.dbo.syssrvroles (srid, name, password) 
	values (7, 'dtm_tm_role', NULL)
end

if not exists (select 1 from master.dbo.syssrvroles where srid = 8)
begin
	insert into master.dbo.syssrvroles (srid, name, password) 
	values (8, 'ha_role', NULL)
end

/*
** Inserts an attribute that holds class id and the password expiration
** for dtm_tm_role and ha_role.
*/
if not exists (select * from master.dbo.sysattributes 
	       where class = 14 and object_type = 'PS' and
		     object_cinfo = 'role' and object = 7)
begin
	insert master.dbo.sysattributes
		(class, attribute, object_type, object_cinfo, object, int_value)
		 values (14, 0, 'PS', 'role', 7, 0)
end

if not exists (select * from master.dbo.sysattributes 
	       where class = 14 and object_type = 'PS' and
		     object_cinfo = 'role' and object = 8)
begin
	insert master.dbo.sysattributes
		(class, attribute, object_type, object_cinfo, object, int_value)
		 values (14, 0, 'PS', 'role', 8, 0)
end

return (0)
	
go
exec sp_procxmode 'sp_fix_dtm_ha_roles', 'anymode'
go
grant execute on sp_fix_dtm_ha_roles to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_create_syscoordinations')
begin
	drop procedure sp_create_syscoordinations
end
go
print "Installing sp_create_syscoordinations"
go


/*
** This procedure creates syscoordinations system table. It must be
** executed from sybsystemdb database only. If executed from any other
** database, the create will return with an appropriate message.
**
** This stored procedure must not be modified, unless the changes are
** reflected in syscoordinations manager and upgrade.
*/

/*
** Messages for "sp_create_syscoordinations"
**
** 17260, "Can't run %1! from within a transaction."
*/

create procedure sp_create_syscoordinations as
begin

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_create_syscoordinations"
	return (1)
end

/* If user does not has the sa role, we cannot continue any further */
if (proc_role("sa_role") = 0)
        return(1)

dbcc astc("crtcoord")

if (@@error != 0)
        return (1)
else
        return (0)

end
go
exec sp_procxmode 'sp_create_syscoordinations', 'anymode'
go
grant execute on sp_create_syscoordinations to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_procqmode')
begin
	drop procedure sp_procqmode
end
go
print "Installing sp_procqmode"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
**
** NOTE: this sproc is obsolete. All pre-system 11
** objects are automatically upgraded whenever you
** upgrade a database and no further action is necessary
** by the user.
*/
create procedure sp_procqmode
as
begin
	print 'sp_procqmode is obsolete.'
	return (0)
end
go
exec sp_procxmode 'sp_procqmode', 'anymode'
go
grant execute on sp_procqmode to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/defaultlanguage */

/*
**  This file defines the primary, foreign, and common keys for the
**  system tables.
*/

/*
**  First do model, then do master.
*/
use model
go

/*
**  Do the primary keys for the system tables.
*/
if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysalternates"))
		execute sp_dropkey primary, sysalternates
go
sp_primarykey sysalternates, suid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syscolumns"))
		execute sp_dropkey primary, syscolumns
go
sp_primarykey syscolumns, id, number, colid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syscomments"))
		execute sp_dropkey primary, syscomments
go
sp_primarykey syscomments, id, number, colid2, colid, texttype
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysdepends"))
		execute sp_dropkey primary, sysdepends
go
sp_primarykey sysdepends, id, number, depid, depnumber
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysindexes"))
		execute sp_dropkey primary, sysindexes
go
sp_primarykey sysindexes, id, indid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syskeys"))
		execute sp_dropkey primary, syskeys
go
sp_primarykey syskeys, id
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysobjects"))
		execute sp_dropkey primary, sysobjects
go
sp_primarykey sysobjects, id
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysprocedures"))
		execute sp_dropkey primary, sysprocedures
go
sp_primarykey sysprocedures, id, number, type, sequence
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysprotects"))
		execute sp_dropkey primary, sysprotects
go
sp_primarykey sysprotects, id, uid, action
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("systypes"))
		execute sp_dropkey primary, systypes
go
sp_primarykey systypes, name
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysusers"))
		execute sp_dropkey primary, sysusers
go
sp_primarykey sysusers, suid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syssegments"))
		execute sp_dropkey primary, syssegments
go
sp_primarykey syssegments, segment
go

/*
**  Now do the foreign keys and common keys.
*/
if exists (select *
		from syskeys
	where type = 2 and id = object_id("sysalternates"))
		execute sp_dropkey foreign, sysalternates, sysusers
go
sp_foreignkey sysalternates, sysusers, suid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syscolumns"))
		execute sp_dropkey common, syscolumns, syscomments
go
sp_commonkey syscolumns, syscomments, id, id
go

sp_dropkey common, syscolumns, syskeys
go
sp_commonkey syscolumns, syskeys, id, key1
go
sp_commonkey syscolumns, syskeys, id, depkey1
go

sp_dropkey common, syscolumns, sysobjects
go
sp_commonkey syscolumns, sysobjects, id, id
go

sp_dropkey common, syscolumns, systypes
go
sp_commonkey syscolumns, systypes, type, type
go
sp_commonkey syscolumns, systypes, usertype, usertype
go
sp_commonkey syscolumns, systypes, domain, domain
go
sp_commonkey syscolumns, systypes, cdefault, tdefault
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syscomments"))
		execute sp_dropkey common, syscomments, sysobjects
go
sp_commonkey syscomments, sysobjects, id, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysdepends"))
		execute sp_dropkey common, sysdepends, sysobjects
go
sp_commonkey sysdepends, sysobjects, id, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysindexes"))
		execute sp_dropkey common, sysindexes, sysobjects
go
sp_commonkey sysindexes, sysobjects, id, id
go

sp_dropkey common, sysindexes, syssegments
go
sp_commonkey sysindexes, syssegments, segment, segment
go

if exists (select *
		from syskeys
	where type = 2 and id = object_id("syskeys"))
		execute sp_dropkey foreign, syskeys, sysobjects
go
sp_foreignkey syskeys, sysobjects, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syskeys"))
		execute sp_dropkey common, syskeys, sysobjects
go
sp_commonkey syskeys, sysobjects, depid, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysobjects"))
		execute sp_dropkey common, sysobjects, sysprocedures
go
sp_commonkey sysobjects, sysprocedures, id, id
go

sp_dropkey common, sysobjects, sysprotects
go
sp_commonkey sysobjects, sysprotects, id, id
go

sp_dropkey common, sysobjects, sysusers
go
sp_commonkey sysobjects, sysusers, uid, uid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysprotects"))
		execute sp_dropkey common, sysprotects, sysusers
go
sp_commonkey sysprotects, sysusers, uid, uid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("systypes"))
		execute sp_dropkey common, systypes, sysusers
go
sp_commonkey systypes, sysusers, uid, uid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysindexes"))
		execute sp_dropkey common, sysindexes, syssegments
go
sp_commonkey sysindexes, syssegments, segment, segment
go

/*
**  Now do the standard systems tables in master.
*/
use master
go

/*
**  Do the primary keys for the system tables.
*/
if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysalternates"))
		execute sp_dropkey primary, sysalternates
go
sp_primarykey sysalternates, suid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syscolumns"))
		execute sp_dropkey primary, syscolumns
go
sp_primarykey syscolumns, id, number, colid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syscomments"))
		execute sp_dropkey primary, syscomments
go
sp_primarykey syscomments, id, number, colid2, colid, texttype
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysdepends"))
		execute sp_dropkey primary, sysdepends
go
sp_primarykey sysdepends, id, number, depid, depnumber
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysindexes"))
		execute sp_dropkey primary, sysindexes
go
sp_primarykey sysindexes, id, indid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syskeys"))
		execute sp_dropkey primary, syskeys
go
sp_primarykey syskeys, id
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysobjects"))
		execute sp_dropkey primary, sysobjects
go
sp_primarykey sysobjects, id
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysprocedures"))
		execute sp_dropkey primary, sysprocedures
go
sp_primarykey sysprocedures, id, number, type, sequence
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysprotects"))
		execute sp_dropkey primary, sysprotects
go
sp_primarykey sysprotects, id, uid, action
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("systypes"))
		execute sp_dropkey primary, systypes
go
sp_primarykey systypes, name
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysusers"))
		execute sp_dropkey primary, sysusers
go
sp_primarykey sysusers, suid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysusages"))
		execute sp_dropkey primary, sysusages
go
sp_primarykey sysusages, dbid, lstart
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysservers"))
		execute sp_dropkey primary, sysservers
go
sp_primarykey sysservers, srvid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysremotelogins"))
		execute sp_dropkey primary, sysremotelogins
go
sp_primarykey sysremotelogins, remoteserverid, remoteusername
go

/*
**  Now do the foreign keys and common keys.
*/
if exists (select *
		from syskeys
	where type = 2 and id = object_id("sysalternates"))
		execute sp_dropkey foreign, sysalternates, sysusers
go
sp_foreignkey sysalternates, sysusers, suid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syscolumns"))
		execute sp_dropkey common, syscolumns, syscomments
go
sp_commonkey syscolumns, syscomments, id, id
go

sp_dropkey common, syscolumns, syskeys
go
sp_commonkey syscolumns, syskeys, id, key1
go
sp_commonkey syscolumns, syskeys, id, depkey1
go

sp_dropkey common, syscolumns, sysobjects
go
sp_commonkey syscolumns, sysobjects, id, id
go

sp_dropkey common, syscolumns, systypes
go
sp_commonkey syscolumns, systypes, type, type
go
sp_commonkey syscolumns, systypes, usertype, usertype
go
sp_commonkey syscolumns, systypes, domain, domain
go
sp_commonkey syscolumns, systypes, cdefault, tdefault
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syscomments"))
		execute sp_dropkey common, syscomments, sysobjects
go
sp_commonkey syscomments, sysobjects, id, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysdepends"))
		execute sp_dropkey common, sysdepends, sysobjects
go
sp_commonkey sysdepends, sysobjects, id, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysindexes"))
		execute sp_dropkey common, sysindexes, sysobjects
go
sp_commonkey sysindexes, sysobjects, id, id
go

sp_dropkey common, sysindexes, syssegments
go
sp_commonkey sysindexes, syssegments, segment, segment
go

if exists (select *
		from syskeys
	where type = 2 and id = object_id("syskeys"))
		execute sp_dropkey foreign, syskeys, sysobjects
go
sp_foreignkey syskeys, sysobjects, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syskeys"))
		execute sp_dropkey common, syskeys, sysobjects
go
sp_commonkey syskeys, sysobjects, depid, id
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysobjects"))
		execute sp_dropkey common, sysobjects, sysprocedures
go
sp_commonkey sysobjects, sysprocedures, id, id
go

sp_dropkey common, sysobjects, sysprotects
go
sp_commonkey sysobjects, sysprotects, id, id
go

sp_dropkey common, sysobjects, sysusers
go
sp_commonkey sysobjects, sysusers, uid, uid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysprotects"))
		execute sp_dropkey common, sysprotects, sysusers
go
sp_commonkey sysprotects, sysusers, uid, uid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("systypes"))
		execute sp_dropkey common, systypes, sysusers
go
sp_commonkey systypes, sysusers, uid, uid
go

/*
**  These are in the master database only.
*/
/*  Define primary keys first */
if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysconfigures"))
		execute sp_dropkey primary, sysconfigures
go
sp_primarykey sysconfigures, config
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysdatabases"))
		execute sp_dropkey primary, sysdatabases
go
sp_primarykey sysdatabases, name
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysdevices"))
		execute sp_dropkey primary, sysdevices
go
sp_primarykey sysdevices, name
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("syslogins"))
		execute sp_dropkey primary, syslogins
go
sp_primarykey syslogins, suid
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysmessages"))
		execute sp_dropkey primary, sysmessages
go
sp_primarykey sysmessages, error, dlevel
go

if exists (select *
		from syskeys
	where type = 1 and id = object_id("sysusages"))
		execute sp_dropkey primary, sysusages
go
sp_primarykey sysusages, dbid, lstart
go

/*
**  Now the foreign and common keys.
*/
if exists (select *
		from syskeys
	where type = 3 and id = object_id("syscurconfigs"))
		execute sp_dropkey common, syscurconfigs, sysconfigures
go
sp_commonkey syscurconfigs, sysconfigures, config, config
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysdatabases"))
		execute sp_dropkey common, sysdatabases, syslocks
go
sp_commonkey sysdatabases, syslocks, dbid, dbid
go

sp_dropkey common, sysdatabases, syslogins
go
sp_commonkey sysdatabases, syslogins, suid, suid
go

sp_dropkey common, sysdatabases, sysprocesses
go
sp_commonkey sysdatabases, sysprocesses, dbid, dbid
go

sp_dropkey common, sysdatabases, sysusages
go
sp_commonkey sysdatabases, sysusages, dbid, dbid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syslocks"))
		execute sp_dropkey common, syslocks, sysprocesses
go
sp_commonkey syslocks, sysprocesses, spid, spid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("syslogins"))
		execute sp_dropkey common, syslogins, sysprocesses
go
sp_commonkey syslogins, sysprocesses, suid, suid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysservers"))
		execute sp_dropkey common, sysservers, sysremotelogins
go
sp_commonkey sysservers, sysremotelogins, srvid, remoteserverid
go

if exists (select *
		from syskeys
	where type = 3 and id = object_id("sysremotelogins"))
		execute sp_dropkey common, sysremotelogins, sysusers
go
sp_commonkey sysremotelogins, sysusers, suid, suid
go

dump transaction master to diskdump with truncate_only
go

dump transaction model to diskdump with truncate_only
go

use sybsystemprocs
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_reportstats')
begin
	drop procedure sp_reportstats
end
go
print "Installing sp_reportstats"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/reportstats */

/*
**  This stored procedure prints out Chargeback Accounting Statistics and
**  percentages.
*/

/*
** Messages for "sp_reportstats"        17935
**
** 17231, "No login with the specified name exists."
**
** NOTE: We need to LOCALIZE the column names of the SELECTs below!!
**
*/

create procedure sp_reportstats
@loginame varchar(255) = NULL		/* name of login to report */
as

declare @cnt int,
	@cputot float,
	@iotot float


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

begin transaction

/*
**  Get totals for all logins except sa.
**  If the total is zero all users have
**  used zero time so far. Change totals
**  to random value (1) and go on. 
**  % usage calculations will appropriately
**  result in zero this way.
*/
select	@cputot = sum(convert(float, totcpu)), 
	@iotot = sum(convert(float, totio))
	from master.dbo.syslogins holdlock

if @cputot = 0
	select @cputot = 1

if @iotot = 0
	select @iotot = 1

if @loginame is not NULL
begin

	if not exists (select * 
			from master.dbo.syslogins 
			where name like @loginame)
	begin
		/* 17231, "No login with the specified name exists." */
		raiserror 17231
		rollback transaction
		return (1)
	end

	/*
	**  Print out the totals for this login, and compare against 
	**  overall totals.
	*/
	select "Name" = name, "Since" = convert(char(11), accdate),
		"CPU" = totcpu, 
		"Percent CPU" = convert(varchar(9), convert(numeric(14,4),
				        round(convert(numeric(20,4), 
					totcpu) / @cputot * 100, 5) ) )
			+ "%",
		"I/O" = totio,
		"Percent I/O" = convert(varchar(9), convert(numeric(14,4),
				        round(convert(numeric(20,4), 
					totio) / @iotot * 100, 5) ) )
			+ "%"
		from master.dbo.syslogins where name like @loginame

end
else
begin

	/*
	**  Print out the totals for all logins except sa, and compare against 
	**  overall totals.
	*/
	select "Name" = name, "Since" = convert(char(11), accdate),
		"CPU" = totcpu, 
		"Percent CPU" = convert(varchar(9), convert(numeric(14,4),
				        round(convert(numeric(20,4), 
					totcpu) / @cputot * 100, 5) ) ) 
			+ "%",
		"I/O" = totio,
		"Percent I/O" = convert(varchar(9), convert(numeric(14,4),
				        round(convert(numeric(20,4), 
					totio) / @iotot * 100, 5) ) )
			+ "%"
		from master.dbo.syslogins
end

/*
**  Print out overall totals.
*/
print ""
select "Total CPU" = convert(varchar(15),@cputot), "Total I/O" = convert(varchar(15),@iotot)
commit transaction
return (0)

go
exec sp_procxmode 'sp_reportstats', 'anymode'
go
grant execute on sp_reportstats to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_clearstats')
begin
	drop procedure sp_clearstats
end
go
print "Installing sp_clearstats"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/clearstats */

/*
** Messages for "sp_clearstats"         17900
**
** 17231, "No login with the specified name exists."
** 17260, "Can't run %1! from within a transaction."
** 17900, "%1! login account(s) cleared."
*/

/*
**  This stored procedure prints out Chargeback Accounting Statistics and
**  percentages using sp_reportstats. In addition, it resets the accounting
**  date, cpu usage, and I/O usage information.
*/
create procedure sp_clearstats
@loginame varchar(30) = NULL		/* name of login to clear */
as

declare @msg varchar(1024)
declare @cnt int,
	@cputot int,
	@iotot int
declare @msg_cnt  varchar(10)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
	raiserror 17260, "sp_clearstats"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

if db_attr(db_name(), "durability") != 'full'  
begin
	/*
	** 17902, "You cannot run stored procedure '%1!'  
	** from a low durbility database."
	*/
	raiserror 17902, "sp_clearstats"
	return (1)
end

begin transaction clearuserstats

if @loginame is not NULL
begin

	if not exists (select * from master.dbo.syslogins where name like @loginame)
	begin
		/*
		** 17231, "No login with the specified name exists."
		*/
		raiserror 17231
		rollback transaction clearuserstats
		return (1)
	end

	/*
	**  Print out the statistics.
	*/
	execute sp_reportstats @loginame

	/*
	**  Update the login, setting the totcpu and totio columns to 0, and
	**  the accdate to current time.
	*/
	update master.dbo.syslogins 
		set accdate = getdate(), totcpu = 0, totio = 0
			where name like @loginame
end
else
begin

	/*
	**  Print out the statistics.
	*/
	execute sp_reportstats

	/*
	**  Update the login, setting the totcpu and totio columns to 0, and the
	**  accdate to current time.
	*/
	update master.dbo.syslogins 
		set accdate = getdate(), totcpu = 0, totio = 0

end
/*
**  Check @@rowcount when it works
*/
select @cnt = @@rowcount
if @cnt > 0
begin
	/*
	** 17900, "%1! login account(s) cleared."
	*/
	exec sp_getmessage 17900, @msg output
	select @msg_cnt = rtrim(convert(char(10), @cnt))
	print @msg, @msg_cnt
end
commit transaction clearuserstats
return (0)
go
exec sp_procxmode 'sp_clearstats', 'anymode'
go
grant execute on sp_clearstats to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_datatype_info')
begin
	drop procedure sp_datatype_info
end
go
print "Installing sp_datatype_info"
go


/* 
** Sccsid = "%Z% generic/sproc/%M% %I% %G%"
**
** History:
**	10.0	steven	1.1	07/13/93	sproc/src/datatype_info
**						Ported from MS catalog SP's
**
** Implementation Notes:
** 	The messiness of 'sp_data_type_info' was to get around the
** problem of returning the correct lengths for user defined types.  The
** join on the type name ensures all user defined types are returned, but
** this puts a null in the data_type column.  By forcing an embedded
** select and correlating it with the current row in systypes, we get the
** correct data_type mapping even for user defined types.  
*/

create procedure sp_datatype_info
@data_type int = 0			/* Provide datatype_info for type # */
as
	if (select @data_type) = 0
	begin
		select	/* Real SQL Server data types */
                        type_name =
                                case
                                   when t.usertype in (44, 45, 46)
                                      then "unsigned " + substring(t.name,
                                                charindex("u", t.name) + 1,
                                                charindex("t", t.name))
                                else
                                   t.name
                                end,
			d.data_type,
			"precison" = isnull(d.data_precision, 
					    convert(int,t.length)),
			d.literal_prefix,
			d.literal_suffix,
			e.create_params,
			d.nullable,
			d.case_sensitive,
			d.searchable,
			d.unsigned_attribute,
			d.money,
			d.auto_increment,
			d.local_type_name,
			d.minimum_scale,
			d.maximum_scale,
			d.sql_data_type,
			d.sql_datetime_sub,
			d.num_prec_radix,
			d.interval_precision
		from 	sybsystemprocs.dbo.spt_datatype_info d, 
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			d.ss_dtype = t.type
			and t.usertype *= e.user_type
			    /* restrict results to "real" datatypes */
			and t.name not in ("nchar","nvarchar",
					   "sysname","longsysname","timestamp",
					   "datetimn","floatn","intn","moneyn",
					   "uintn")
			and t.usertype < 100	/* No user defined types */
		UNION
		select	/* SQL Server user data types */
			type_name = t.name,
			d.data_type,
			"precison" = isnull(d.data_precision, 
					    convert(int,t.length)),
			d.literal_prefix,
			d.literal_suffix,
			e.create_params,
			d.nullable,
			d.case_sensitive,
			d.searchable,
			d.unsigned_attribute,
			d.money,
			d.auto_increment,
			t.name,
			d.minimum_scale,
			d.maximum_scale,
			d.sql_data_type,
			d.sql_datetime_sub,
			d.num_prec_radix,
			d.interval_precision
		from 	sybsystemprocs.dbo.spt_datatype_info d, 
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			d.ss_dtype = t.type
			and t.usertype *= e.user_type
			    /* 
			    ** Restrict to user defined types (value > 100)
			    ** and Sybase user defined types (listed)
			    */
			and (t.name in ("nchar","nvarchar",
					    "sysname","longsysname","timestamp")
			    or t.usertype >= 100)      /* User defined types */
			    order by d.data_type, type_name
	end
	else
	begin
		select	/* Real SQL Server data types */
                        type_name =
                                case
                                   when t.usertype in (44, 45, 46)
                                      then "unsigned " + substring(t.name,
                                                charindex("u", t.name) + 1,
                                                charindex("t", t.name))
                                else
                                   t.name
                                end,
			d.data_type,
			"precison" = isnull(d.data_precision, 
					    convert(int,t.length)),
			d.literal_prefix,
			d.literal_suffix,
			e.create_params,
			d.nullable,
			d.case_sensitive,
			d.searchable,
			d.unsigned_attribute,
			d.money,
			d.auto_increment,
			d.local_type_name,
			d.sql_data_type,
			d.sql_datetime_sub,
			d.num_prec_radix,
			d.interval_precision
		from 	sybsystemprocs.dbo.spt_datatype_info d, 
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			data_type = @data_type
			and d.ss_dtype = t.type
			and t.usertype *= e.user_type
			    /* restrict results to "real" datatypes */
			and t.name not in ("nchar","nvarchar",
					   "sysname","longsysname","timestamp",
					   "datetimn","floatn","intn","moneyn",
					   "uintn" )
			and t.usertype < 100	/* No user defined types */
		UNION
		select	/* SQL Server and user data types */
			type_name = t.name,
			d.data_type,
			"precison" = isnull(d.data_precision, 
					    convert(int,t.length)),
			d.literal_prefix,
			d.literal_suffix,
			e.create_params,
			d.nullable,
			d.case_sensitive,
			d.searchable,
			d.unsigned_attribute,
			d.money,
			d.auto_increment,
			t.name,
			d.sql_data_type,
			d.sql_datetime_sub,
			d.num_prec_radix,
			d.interval_precision
		from 	sybsystemprocs.dbo.spt_datatype_info d, 
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			data_type = @data_type
			and d.ss_dtype = t.type
			and t.usertype *= e.user_type
			    /* 
			    ** Restrict to user defined types (value > 100)
			    ** and Sybase user defined types (listed)
			    */
			and (t.name in ("nchar","nvarchar",
					    "sysname","longsysname","timestamp")
			    or t.usertype >= 100)     /* User defined types */
		order by type_name
	end
return (0)
go
exec sp_procxmode 'sp_datatype_info', 'anymode'
go
grant execute on sp_datatype_info to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addmessage')
begin
	drop procedure sp_addmessage
end
go
print "Installing sp_addmessage"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/* generic/sproc/addmessage	14.2	4/25/91 */

/* 
** Messages from sysmessages
**
** 17210, "Message number must be at least 20000."
** 17211, "Cannot add message until Sysusermessages system table is created properly by Upgrade."
** 17201, "'%1!' is not an official language name from Syslanguages."
** 17212, "A message with number %1! in the specified language already exists."
** 17213, "Drop the old message first if you still wish to add this one."
** 17214, "The message has been inserted."
** 17215, "The message has not been inserted."
** 17216, "Only the System Administrator (SA) or the Database Owner (dbo) may add messages which set the WITH_LOG option to `'true'`."
** 17217, "The only valid @with_log values are TRUE or FALSE."
** 17240, "'%1!' is not a valid name."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
*/
create procedure sp_addmessage
@message_num int,
@message_text varchar(1024),
@language varchar(255) = NULL,
@with_log varchar(5) = 'FALSE',
@replace varchar(7) = NULL
as

    declare @msg varchar(1024)
    declare @returncode int
    declare @dlevel smallint
    declare @suid int
declare	@eventnum int		/* event number for add message auditing */
declare	@mod_ok int		/* successful add message auditing  */
declare	@mod_fail int		/* failure add message auditing  */


select	@eventnum = 15		/* event number for add message */
select	@mod_ok = 1		
select	@mod_fail = 2		
declare @dbname varchar(255)


    /* Use the default language by default */
    declare @lang_id smallint 
    select @lang_id = @@langid


    if @@trancount = 0
    begin
    	set chained off
    end
    set transaction isolation level 1

    if @message_num < 20000
    BEGIN
		/* 17210, "Message number must be at least 20000." */
		raiserror 17210
        return (1)
    END

    /*
    ** Check to be sure Sysusermessages exists
    */
    if not exists (select * from sysobjects
    			where name = "sysusermessages"
    			and type = 'S')
    BEGIN
        /* 
		** 17211, "Cannot add message until Sysusermessages system table is
		**		created properly by Upgrade."
        */
		raiserror 17211
        return (1)
    END

    /*
    ** Check that language is valid.
    */
    if @language is not NULL
    BEGIN
        execute @returncode = sp_validlang @language
        if @returncode != 0
        begin
                /* Us_english is always valid */
                if @language != "us_english"
		BEGIN
	    	/* 
			** 17201, "'%1!' is not an official language
			**	name from Syslanguages."
			*/
			raiserror 17201, @language
	    	return @returncode
		END

		/* set to us_english */
		select @lang_id = NULL
        end

	else
	select @lang_id = langid from master.dbo.syslanguages
		    where @language = name
    END

    /* The langid is assigned 0 since it gets its value from @@langid. */
    /* For us_english, we have to insert it as NULL and not 0, this is */
    /* to maintain compatibility with the current conventions          */

    if @lang_id = 0
    begin
        select @lang_id = NULL
    end

    /*
    ** Only the DBO or SA (has "sa_role") may add messages which set the 
    ** WITH_LOG option to `true'
    */
    if ((user_id() != 1) and (charindex("sa_role",show_role()) = 0)) 
		and (rtrim(upper(@with_log)) = 'TRUE')
	begin
		/*
		** 17216, "Only the System Administrator (SA) or the Database
		** 	owner (dbo) may add messages which set the WITH_LOG 
		**	option to `'true''."
		*/
		raiserror 17216
		return (1)
	end

    /*
    ** @with_log must be 'TRUE' or 'FALSE'
    */
    if (upper(@with_log) not in ('TRUE', 'FALSE'))
	begin
		/*
		** 17217, "The only valid @with_log values are TRUE or FALSE."
		*/
       	raiserror 17217
		return (1)
	end

    /*
    ** Set the dlevel bit accordingly
    */
    if (rtrim(upper(@with_log)) = 'TRUE')
        select @dlevel = hextoint("0x80")
    else
        select @dlevel = 0x0

    /*
    **  Does this message already exist, and if so are we REPLACEing it?
    */
    select @suid = uid from sysusermessages 
	where error = @message_num and langid = @lang_id

    if (@@rowcount > 0)
    BEGIN
	if lower(@replace) = 'replace'
		if (@suid = suser_id())
		begin
			print 'Replacing message.'
			delete from sysusermessages where error = @message_num
				and langid = @lang_id
		end
		else
		begin
			/* 17218, "Message number %1! with language ID %2! was
			** created by user ID %3!. You cannot replace that
			** message; you must first delete the existing message
			** using sp_dropmessage, then add the changed message."
			*/
			raiserror 17218, @message_num, @lang_id, @suid
			return (1)
		end
	else
		begin
			/* 17212, "A message with number %1! in the specified 
			** language already exists." 
			*/
			raiserror 17212, @message_num

			/* 17213, "Drop the old message first if you still wish to 
			** add this one." 
			*/
			raiserror 17213
        	return (1)
		end
    END

    /*
    ** Check that the message is a valid one.
    */
    print @message_text, "<arg1>", "<arg2>", "<arg3>", "<arg4>",
    		    "<arg5>", "<arg6>", "<arg7>", "<arg8>",
    		    "<arg9>", "<arg10>", "<arg11>", "<arg12>",
    		    "<arg13>", "<arg14>", "<arg15>", "<arg16>",
    		    "<arg17>", "<arg18>", "<arg19>", "<arg20>"

    /*
    ** If there was an error, @@error will be non-zero
    */
    if @@error != 0
           return (1)



    /*
    ** Generate successful audit record.
    */
    select @returncode = ad_hoc_audit (@eventnum, @mod_ok, str(@message_num),
	db_name(), "sysusermessages", suser_name(), 0, object_id("sysusermessages")

        )

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

    /* Now, insert the message */
    insert into sysusermessages
    	    values(@message_num, suser_id(), @message_text, @lang_id, @dlevel)
    if @@error != 0
    begin
	/* 17215, "The message has not been inserted." */
	raiserror 17215

	rollback transaction rs_logexec
	return(1)
    end

    /*
    ** Write the log record to replicate this invocation 
    ** of the stored procedure.
    */
    if (logexec() != 1)
    begin
    	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
    	*/
	select @dbname = db_name()
    	raiserror 17756, "sp_addmessage", @dbname
    			
    	rollback transaction rs_logexec
    	return(1)
    end

commit transaction

/* 17214, "The message has been inserted." */
exec sp_getmessage 17214, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_addmessage', 'anymode'
go
grant execute on sp_addmessage to public
go
exec sp_procxmode 'sp_addmessage', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropmessage')
begin
	drop procedure sp_dropmessage
end
go
print "Installing sp_dropmessage"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */
/* generic/sproc/dropmessage		14.2	11/12/91 */

/* 
** Messages from sysmessages
**
** 17201, "'%1!' is not an official language name from Syslanguages."
** 17202, "Message number %1! does not exist in the %2! language."
** 17210, "Message number must be at least 20000."
** 17220, "Message number %1! does not exist."
** 17221, "Message deleted."
** 17222, "User '%1!' does not have permission to drop message number %2!."
** 17223, "User '%1!' does not have permission to drop message number %2! in the %3! language."
** 17224, "Drop failed.  Your curwrite label must match the security label of the message.  Check sysusermessages."
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
*/     

create procedure sp_dropmessage
@message_num int, 
@language varchar(30) = NULL
as

declare @msg varchar(1024)
declare @msg2 varchar(255)
declare @lang_id smallint
declare @privileged smallint
declare @returncode smallint
declare @procval int

declare	@eventnum int		/* event number for add message auditing */
declare	@mod_ok_fail int		/* successful add message auditing  */
declare	@uid int		/* successful add message auditing  */


select	@eventnum = 32		/* event number for add message */
declare @dbname varchar(255)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*
** Checking "OWN"ership of the message by the user is on by default by
** resetting the "priveleged" flag. This is bypassed if needed by setting it
** to 1
*/
select @privileged = 0

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
**  Check sa_role first as it cleans up the code.
*/
if charindex("sa_role", show_role()) > 0
begin
	/*
	** If user has sa_role, wether by explicit granting or by being
	** SA or DBO we assume that "sa_role" is being used to drop the
	** message & thus we want to send an audit record by calling
	** proc_role("sa_role") & we set the privileged flag to say that
	** this does not have to be the owner of the message being dropped
	*/
	select @procval = proc_role("sa_role")
	select @privileged = 1
end
else
begin
	/*
	** If this is the DBO then set privileged flag to check that 
	** ownership of the message is not to be checked
	*/
	if user_id() = 1
	begin
		select @privileged = 1
	end
end

/*
** Check that language is valid.
*/
if @language is null
	select @lang_id = -1		/* (all) */
else
BEGIN
	execute @returncode = sp_validlang @language
	if @returncode != 0
	begin
		/* Us_english is always valid */
                if @language != "us_english"
		BEGIN
			/* 
			** 17201, "'%1!' is not an official language
			**		name from Syslanguages."
			*/
			raiserror 17201, @language
			return @returncode
		END

		/* set to us_english */
		select @lang_id = NULL
        end

	else
	select @lang_id = langid from master.dbo.syslanguages
			where @language = name
END

if @message_num < 20000
begin
	/* 17210, "Message number must be at least 20000." */
		raiserror 17210
        return (1)
end

/*
** Check that message exists 
*/
if not exists (select * from sysusermessages
			    where error = @message_num)
begin
	/* 17220, "Message number %1! does not exist." */
	raiserror 17220, @message_num
	return (1)
end



/*
** ... In the Proper language
*/
if @lang_id != -1 and not exists (select * from sysusermessages
		    where error = @message_num and langid = @lang_id)
begin
	/* 17202, "Message number %1! does not exist in the %2! language." */
	raiserror 17202, @message_num, @language
	return (1)
end

if (@privileged = 1)
BEGIN
	/* get the owner id of the object */
	select @uid = uid from sysusermessages where error = @message_num



	select	@mod_ok_fail = 1	
	/*
	** Generate successful audit record.
	*/
	select @returncode = ad_hoc_audit (@eventnum, @mod_ok_fail, 
					str(@message_num), db_name(), NULL, 
					suser_name(@uid), 0, NULL

					)
	if (@returncode != 0)
	begin
		/* 
		** 18293, "Auditing for '%1!' event has failed due to 
		** internal error. Contact a user with System Security 
		** Officer (SSO) role."
		*/
       	raiserror 18293, @eventnum
	end

	/* Start the transaction to log the execution of this procedure.
	**
	** IMPORTANT: The name "rs_logexec is significant and is used by 
	**            Replication Server
	*/
	begin transaction rs_logexec

	/*
	** Do they want to delete all the messages?
	*/
	if @lang_id = -1
	begin
		delete sysusermessages
				where error = @message_num
	end		
	/*
	** If not, delete only the message with the
	** specific language
	*/
	else
	begin
		delete sysusermessages 
			where error = @message_num and
					langid = @lang_id
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_dropmessage", @dbname
			
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/* 17221, "Message deleted." */
	exec sp_getmessage 17221, @msg output
	print @msg

     END
    else
    /* Only delete the user's specific messages */
     BEGIN
	/*
	** Do they want to delete all the messages?
	*/
	if @lang_id = -1
	begin
		/* get the owner id of the object */
		select @uid = uid from sysusermessages
					where error = @message_num
		if exists (select * from sysusermessages
			    where error = @message_num
					and uid = suser_id())
		begin	/* the user owns the message */


			select	@mod_ok_fail = 1	
		end
		else	/* the use does not own the message */
		begin

			select	@mod_ok_fail = 2	
		end
		/*
		** Generate successful/fail audit record.
		*/
		select @returncode = ad_hoc_audit (@eventnum, 
					@mod_ok_fail, str(@message_num),
					db_name(), NULL, suser_name(@uid), 
					0, NULL	

					)
		if (@returncode != 0)
		begin
			/* 
			** 18293, "Auditing for '%1!' event has failed 
			** due to internal error. Contact a user with 
			** System Security Officer (SSO) role."
			*/
			raiserror 18293, @eventnum
		end
		if exists (select * from sysusermessages
			    where error = @message_num
					and uid = suser_id())
		begin

			/* Start the transaction to log the execution
			** of this procedure.
			**
			** IMPORTANT: The name "rs_logexec is
			** significant and is used by Replication Server
			*/
			begin transaction rs_logexec

			delete sysusermessages
			where error = @message_num
					and uid = suser_id()
			/*
			** Write the log record to replicate this invocation 
			** of the stored procedure.
			*/
			if (logexec() != 1)
			begin
				/*
				** 17756, "The execution of the stored
				**         procedure '%1!' in database
				**         '%2!' was aborted because
				**         there was an error in writing
				**         the replication log record."
				*/
				select @dbname = db_name()
				raiserror 17756, "sp_dropmessage", @dbname
			
				rollback transaction rs_logexec
				return(1)
			end

			commit transaction

			/* 17221, "Message deleted." */
			exec sp_getmessage 17221, @msg output
			print @msg

		end
		else
		begin
			/* 
			** 17222 "User '%1!' does not have permission to 
			** 		drop message number %2!"
			*/
			select @msg2 = user_name()
			raiserror 17222, @msg2, @message_num
		end
	end		
	/*
	** If not, delete only the message with the
	** specific language
	*/
       else
	begin
		/* get the owner id of the object */
		select @uid = uid from sysusermessages
					where error = @message_num
					and langid = @lang_id
		if exists (select * from sysusermessages
			    where error = @message_num
					and langid = @lang_id
					and uid = suser_id())
		begin

			select	@mod_ok_fail = 1	
		end
		else
		begin

			select	@mod_ok_fail = 2	
		end
		/*
		** Generate successful/fail audit record.
		*/
		select @returncode = ad_hoc_audit (@eventnum, 
					@mod_ok_fail, str(@message_num),
					db_name(), NULL, suser_name(@uid), 
					0, NULL	

					)
		if (@returncode != 0)
		begin
			/* 
			** 18293, "Auditing for '%1!' event has failed 
			** due to internal error. Contact a user with 
			** System Security Officer (SSO) role."
			*/
			raiserror 18293, @eventnum
		end
		if exists (select * from sysusermessages
				where error = @message_num
						and langid = @lang_id
						and uid = suser_id())
		begin
			/* Start the transaction to log the execution
			** of this procedure.
			**
			** IMPORTANT: The name "rs_logexec is
			**            significant and is used by
			**            Replication Server
			*/
			begin transaction rs_logexec

			delete sysusermessages 
					where error = @message_num
							and langid = @lang_id
							and uid = suser_id()
			/*
			** Write the log record to replicate this invocation 
			** of the stored procedure.
			*/
			if (logexec() != 1)
			begin
				/*
				** 17756, "The execution of the stored
				**         procedure '%1!' in database
				**         '%2!' was aborted because
				**         there was an error in writing
				**         the replication log record."
				*/
				select @dbname = db_name()
				raiserror 17756, "sp_dropmessage", @dbname
			
				rollback transaction rs_logexec
				return(1)
			end

			commit transaction

			/* 17221, "Message deleted." */
			exec sp_getmessage 17221, @msg output
			print @msg
			
		end
	       else
		begin
			/* 
			** 17223 "User '%1!' does not have permission to 
			** 		drop message number %2! in the %3! language."
			*/
			select @msg2 = user_name()
			raiserror 17223, @msg2, @message_num, @language
			return (1)
		end
	end
    END		
return (0)

go
exec sp_procxmode 'sp_dropmessage', 'anymode'
go
grant execute on sp_dropmessage to public
go
exec sp_procxmode 'sp_dropmessage', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_bindmsg')
begin
	drop procedure sp_bindmsg
end
go
print "Installing sp_bindmsg"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	5.0	1.1	07/31/91	sproc/src/bindmsg */

/*
** Messages for "sp_bindmsg"            17890
**
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 17890, "Constraint name must be in `current' database."
** 17891, "Constraint name must belong to the current user."
** 17892, "Message id must be a user defined message."
** 17893, "No such message exists. Please create the message first using sp_addmessage."
** 17894, "No such referential or check constraint exists. Please check whether
** the constraint name is correct."
** 17895, "Constraint is bound to a message. You must unbind the message first."
** 17896, "Binding message failed unexpectedly. Please try again."
** 17897, "Message bound to constraint."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
*/

create procedure sp_bindmsg
@constrname varchar(767),		/* name of the constraint */
@msgid int 				/* message id */
as

declare @msg varchar(1024)		/* for printing messages */
declare @returncode int                 /* return from ad_hoc_audit builtin */
declare	@eventnum int		/* event number for bind message auditing */
declare	@mod_ok int		/* successful bind message auditing  */
declare	@mod_fail int		/* failure bind message auditing  */

declare @objid int

select	@eventnum = 7		/* evetn number for bindmsg */
select	@mod_ok = 1		
select	@mod_fail = 2		
declare @dbname varchar(30)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on


/* check to see that the object name  is local to the current database */

if (@constrname like "%.%.%")
begin
	/*
	** 17890, "Constraint name must be in `current' database."
	*/
	raiserror 17890
	return (1)
end

/* check to see that the object name belongs to the current user */

if (@constrname like "%.%")
begin
	/*
	** 17891, "Constraint name must belong to the current user."
	*/
	raiserror 17891
	return (1)
end

/* check if the message number is illegal */

if (@msgid < 20000)
begin
	/*
	** 17892,  "Message id must be a user defined message."
	*/
	raiserror 17892
	return (1)
end

/* check if the message number is nonexistent */

if not exists (select * from sysusermessages where error = @msgid)
begin
	/*
	** 17893, "No such message exists. Please create the message first using sp_addmessage."
	*/
	raiserror 17893
	return (1)
end


/* check to see that the constraint exists */

if not exists (select id
		from sysconstraints c, sysobjects o
		where c.constrid = object_id (@constrname)
			and o.id = object_id (@constrname)
			and o.uid = user_id ()
			and (o.sysstat & 15 = 7 /* check constraint */
			or sysstat & 15 = 9) /* referential constraint */ )
begin
	/*
	** 17894, "No such referential or check constraint exists. Please check whether the constraint name is correct."
	*/


	/* Audit the failure to bind a message */
        select @returncode =
        ad_hoc_audit (@eventnum, @mod_fail, convert(varchar(30),@msgid), 
			db_name(), @constrname, user_name(), 0, 
			object_id(@constrname)

			)
	raiserror 17894
	return (1)
end


/* Audit the successful permission  to bind a message */
select @returncode =
ad_hoc_audit (@eventnum, @mod_ok, convert(varchar(30),@msgid), db_name(), 
		@constrname, user_name(), 0, object_id(@constrname)

		)
if (@returncode != 0)
begin
	/* 
	** 18293, "Auditing for '%1!' event has failed due to 
	** internal error. Contact a user with System Security 
	** Officer (SSO) role."
	*/
	raiserror 18293, @eventnum
	return (1)
end
/*
**
** NOTE: If the following section of code is ever "uncommented", change
** the @constrid variable in the SQL Statement to object_id(@constrname).
**
** check if the constraint is already bound to a message
**
** if (exists (select *
**		from sysconstraints
**		where constrid = @constrid
**			and error != 0))
** begin
**	**
** 	** 17895, "Constraint is bound to a message. You must unbind the message first."
**	**
**	raiserror 17895	
**	return (1)
** end
*/

/* update sysconstraints table */

update sysconstraints
	set error = @msgid
	from sysconstraints, sysobjects
	where sysconstraints.constrid = object_id(@constrname)
		and sysobjects.id = object_id(@constrname)
		and sysobjects.uid = user_id ()
		and (sysstat & 15 = 7 /* check constraint */
		or sysstat & 15 = 9) /* referential constraint */

/* check if the update took place */

if @@rowcount != 1
begin
	/*
	** 17896, "Binding message failed unexpectedly. Please try again."
	*/
	raiserror 17896
	return (1)
end

/*
** Since binding a message is a schema change, update schema count
** for the object in the sysobjects table.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

	select @objid = sysobjects.id
	from sysobjects, sysconstraints
	where sysconstraints.constrid = object_id(@constrname)
		and sysobjects.id = sysconstraints.tableid
		and uid = user_id()
		and (sysstat & 15 = 7 /* check constraint */
		or sysstat & 15 = 9) /* referential constraint */

	if (@@rowcount > 0)
	begin

		if (schema_inc(@objid, 0) != 1)
		begin
			/*
			** 17763, "The execution of the stored procedure '%1!'
			**         in database '%2!' was aborted because there
			**         was an error in updating the column
			**         schemacnt in sysobjects."
			*/
			select @dbname = db_name()
			raiserror 17763, "sp_bindmsg", @dbname
			rollback transaction rs_logexec
			return(1)
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_bindmsg", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

commit transaction

/*
** 17897, "Message bound to constraint."
*/
exec sp_getmessage 17897, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_bindmsg', 'anymode'
go
grant execute on sp_bindmsg to public
go
exec sp_procxmode 'sp_bindmsg', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_unbindmsg')
begin
	drop procedure sp_unbindmsg
end
go
print "Installing sp_unbindmsg"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	5.0	1.1	07/31/91	sproc/src/unbindmsg */

/*
** Messages for "sp_unbindmsg"          17940
**
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 17890, "Constraint name must be in `current' database."
** 17891, "Constraint name must belong to the current user."
** 17894, "No such referential or check constraint exists. Please check whether
** the constraint name is correct."
** 17940, "Constraint is not bound to any message."
** 17941, "Unbinding message failed unexpectedly. Please try again."
** 17942, "Message unbound from constraint."
** 18293, "Auditing for '%1!' event has failed due to internal error. Contact a user with System Security Officer (SSO) role."
*/

create procedure sp_unbindmsg

@constrname varchar(767)	/* name of the constraint */
as

declare @msg varchar(1024)	/* message text */
declare @returncode int         /* return from ad_hoc_audit builtin */
declare	@eventnum int		/* event number for bind default auditing */
declare	@mod_ok int		/* successful bind default auditing  */
declare	@mod_fail int		/* failure bind default auditing  */


select	@eventnum = 69		/* unbindmsg event number */
select	@mod_ok = 1		
select	@mod_fail = 2		
declare @dbname varchar(255)
declare @objid int



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set transaction isolation level 1

set nocount on

/* check to see that the object names are local to the current database */

if (@constrname like "%.%.%")
begin
	/* 17890, "Constraint name must be in `current' database." */
	raiserror 17890
	return (1)
end

/* check to see that the object name belongs to the current user */

if (@constrname like "%.%")
begin
	/* 17891, "Constraint name must belong to the current user." */
	raiserror 17891
	return (1)
end


/* check to see that the constraint exists */

if not exists (select id
		from sysconstraints c, sysobjects o
		where c.constrid = object_id (@constrname)
			and o.id = object_id (@constrname)
			and o.uid = user_id ()
			and (sysstat & 15 = 7 /* check constraint */
			or sysstat & 15 = 9) /* referential constraint */ )
begin
	/*
	** "No such referential or check constraint exists. Please check whether the constraint name is correct."
	*/

	/* Audit the failure to unbind a message */
        select @returncode =
        ad_hoc_audit ( @eventnum, @mod_fail, NULL, db_name(), 
			@constrname, user_name(), 0, object_id(@constrname)

			)
	raiserror 17894
	return (1)
end


/* Audit the successful permission to unbind a message */
select @returncode =
ad_hoc_audit (@eventnum, @mod_ok, NULL, db_name(), @constrname, 
		user_name(), 0, object_id(@constrname)

		)

if (@returncode != 0)
begin
	/* 
	** 18293, "Auditing for '%1!' event has failed due to 
	** internal error. Contact a user with System Security 
	** Officer (SSO) role."
	*/
	raiserror 18293, @eventnum
	return (1)
end

/* check if the constraint is bound to a message */

if exists (select c.error
		from sysconstraints c, sysobjects
		where c.constrid = object_id(@constrname)
			and sysobjects.id = object_id(@constrname)
			and sysobjects.uid = user_id ()
			and (sysstat & 15 = 7 /* check constraint */
			or sysstat & 15 = 9) /* referential constraint */ 
			and c.error = 0)
begin
	/*
	** 17940, "Constraint is not bound to any message."
	*/
	raiserror 17940
	return (1)
end


/* update sysconstraints table */

update sysconstraints
	set error = 0
	from sysconstraints, sysobjects
	where sysconstraints.constrid = object_id(@constrname)
		and sysobjects.id = object_id(@constrname)
		and sysobjects.uid = user_id ()
		and (sysstat & 15 = 7 /* check constraint */
		or sysstat & 15 = 9) /* referential constraint */ 

/* check if the update took place */

if @@rowcount != 1
begin
	/*
	** 17941, "Unbinding message failed unexpectedly. Please try again."
	*/
	raiserror 17941
	return (1)
end

/*
** Since unbinding a message is a schema change, update schema count
** for the object in the sysobjects table.
*/

/* 
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

	select @objid = sysobjects.id
	from sysobjects, sysconstraints
	where sysconstraints.constrid = object_id(@constrname)
		and sysobjects.id = sysconstraints.tableid
		and uid = user_id()
		and (sysstat & 15 = 7 /* check constraint */
		or sysstat & 15 = 9) /* referential constraint */ 

	if (@@rowcount > 0)
	begin
		if (schema_inc(@objid, 0) != 1)
		begin
			/*
			** 17763, "The execution of the stored procedure '%1!'
			**         in database '%2!' was aborted because there
			**         was an error in updating the column
			**         schemacnt in sysobjects."
			*/
			select @dbname = db_name()
			raiserror 17763, "sp_undbindmsg", @dbname
			rollback transaction rs_logexec
			return(1)
		end
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_unbindmsg", @dbname
				
		rollback transaction rs_logexec
		return(1)
	end

commit transaction

/*
** 17942, "Message unbound from constraint."
*/
exec sp_getmessage 17942, @msg output
print @msg

return (0)
go
exec sp_procxmode 'sp_unbindmsg', 'anymode'
go
grant execute on sp_unbindmsg to public
go
exec sp_procxmode 'sp_unbindmsg', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_altermessage')
begin
	drop procedure sp_altermessage
end
go
print "Installing sp_altermessage"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/* generic/sproc/altermessage	14.2	4/25/91 */

/* 
** Messages from sysmessages
**
** 18371, "The only valid @parameter value is WITH_LOG."
** 18372, "The only valid @parameter_value values are TRUE or FALSE."
*/
create procedure sp_altermessage
@message_id       int,
@parameter        varchar(30),
@parameter_value  varchar(5)
as
  declare @rows_affected  varchar(16)
  declare @msg            varchar(128)

  select @parameter = upper(@parameter)
  select @parameter_value = upper(@parameter_value)

  /*
  ** Make sure the user (is the DBO) or (has "sa_role")
  */
  if ((user_id() != 1) and (charindex("sa_role",show_role()) = 0)) 
  begin
	  /*
	  ** 17230, "Only the System Administrator (SA) or the Database Owner
	  **	   (dbo) may execute this stored procedure."
	  */
          raiserror 17230 
          return (1)
  end

  /*
  ** Does this message exist?
  */
  if (@message_id < 20000)
  begin
  	if (not exists (select * from master.dbo.sysmessages
                  where error = @message_id))
  	begin
		/*
		** 17220, "Message number %1! does not exist."
		*/
       	raiserror 17220, @message_id
       	return (1)
  	end
  end
  else
  begin
  	if (not exists (select * from sysusermessages
                  where error = @message_id))
  	begin
		/*
		** 17220, "Message number %1! does not exist."
		*/
       	raiserror 17220, @message_id
       	return (1)
  	end
  end

  /*
  ** Is Parameter 'WITH_LOG'?
  */
  if (@parameter <> 'WITH_LOG')
  begin
	  /*
	  ** 18371, "The only valid @parameter value is WITH_LOG."
	  */
          raiserror 18371 
          return (1)
  end

  /*
  ** Is ParameterValue TRUE or FALSE?
  */
  if (@parameter_value not in ('TRUE', 'FALSE'))
  begin
	  /*
	  ** 18372, "The only valid @parameter_value values are TRUE or FALSE."
	  */
          raiserror 18372 
          return (1)
  end

  /*
  ** Determine the number of messages affected
  */
  if (@message_id < 20000)
  begin
  	select @rows_affected = convert(varchar(16), count(*)) from master.dbo.sysmessages
       where error = @message_id
  end
  else
  begin
  	select @rows_affected = convert(varchar(16), count(*)) from sysusermessages
       where error = @message_id
  end
  select @msg = @rows_affected + ' Messages altered.'

  /*
  ** Turn dlevel bit 7 on or off
  */
  if (@parameter_value = 'TRUE')
  begin
  	  if (@message_id < 20000)
          	update master.dbo.sysmessages
                  set dlevel = dlevel | hextoint("0x80")
                          where error = @message_id
	  else
          	update sysusermessages
                  set dlevel = dlevel | hextoint("0x80")
                          where error = @message_id
          if (@@error = 0)
          begin
                  if (convert(int, @rows_affected) = 1) PRINT 'Message altered.'
                  if (convert(int, @rows_affected) > 1) PRINT @msg
          end
  end
  else
  if (@parameter_value = 'FALSE')
  begin
  	  if (@message_id < 20000)
          	update master.dbo.sysmessages
                  set dlevel = dlevel & ~(hextoint("0x80"))
                          where error = @message_id
	  else
          	update sysusermessages
                  set dlevel = dlevel & ~(hextoint("0x80"))
                          where error = @message_id
          if (@@error = 0)
          begin
                  if (convert(int, @rows_affected) = 1) PRINT 'Message altered.'
                  if (convert(int, @rows_affected) > 1) PRINT @msg
          end
  end
  return (0)
go
exec sp_procxmode 'sp_altermessage', 'anymode'
go
grant execute on sp_altermessage to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_role')
begin
	drop procedure sp_role
end
go
print "Installing sp_role"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	5.0	1.0	10/22/91	sproc/src/role */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:19 2006 
*/
/*
** raiserror Messages for role [Total 3]
**
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17884, "Neither 'grant' or 'revoke' is specified -- nothing changed."
*/
/*
** sp_getmessage Messages for role [Total 1]
**
** 17885, "Authorization updated."
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_role
@action  varchar(30),                   /* "grant" or "revoke"	*/
@rolename varchar(255),			/* role name		*/
@grantee varchar(255)			/* user/role name	*/
as
declare @msg varchar(1024)		/* Message text */

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_role"
	return (1)
end

/*
**  Invoke the grant/revoke role command to perform the grant/revoke.
*/
if @action = "grant"
begin
	grant role @rolename to @grantee
end
else if @action = "revoke"
begin
	revoke role @rolename from @grantee
end
else
begin
	/*
	** 17884, "Neither 'grant' or 'revoke' is specified -- nothing changed."
	*/
	raiserror 17884
end

if @@error != 0
begin
	return (1)
end

/*
** If the 'master' database is marked for replication, the T-SQL built-in
** 'logexec()' will log for replication the execution instance of this
** system procedure.  Otherwise, the T-SQL built-in 'logexec()' is a no-op.
*/
if (logexec(1) != 1)
begin
	raiserror 17756, "sp_role", "master"
	return (1)
end

/*
** 17885, "Role updated."
*/
exec sp_getmessage 17885, @msg output
print @msg
return (0)
go
exec sp_procxmode 'sp_role', 'anymode'
go
grant execute on sp_role to public
go
exec sp_procxmode 'sp_role', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_logintrigger')
begin
	drop procedure sp_logintrigger
end
go
print "Installing sp_logintrigger"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Messages for "sp_logintrigger"    
**
** 19388, "Global login trigger updated."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated to the companion 
**	server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for details.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_logintrigger
	@trigname	varchar(256) = NULL
AS
BEGIN

DECLARE	@msg		varchar(1024),
	@authid		int,
	@suid		int,
	@login_class	smallint,
	@attrib		smallint,
	@action		smallint,
	@dummy		int,
	@HA_CERTIFIED	tinyint,   /* Is the SP HA certified ? */
	@retstat	int,
	@config		int,
	@type		char(2),
	@del		int

/*
** The login trigger is stored in sysattributes:
**
**	- class:	20
**	- attribute:	1
**	- type:		'LT'
**	- char_value:	login trigger name. It can include database and
**	  owner, but the total length must be < 256 chars.
**
** If there is a login trigger configured, we will update it, otherwise
** we will insert a new row.
**
** If the trigger name is null, the current trigger name will be displayed.
** If the trigger name is the keyword 'drop', the current trigger will be 
** removed from sysattributes.
**
*/
	select @login_class = 20, @attrib = 1, @type = 'LT'
	if (@trigname is null)
	BEGIN
		select 	'name' = char_value,
			'status' = 
				case when (@@logintrigger is null)
					then 'Disabled'
					else 'Enabled'
				end
		into #tmp
		from master.dbo.sysattributes
		where class = 20 and attribute = 1 and object_type = 'LT'

		exec sp_autoformat 
			@fulltabname = '#tmp',
			@selectlist = '''Global login trigger'' = name, 
				''Status'' = status'
		return 0
	END
		
	
/*
** Only a user with sso_role can set login triggers
*/
	if (proc_role('sso_role') < 1)
		return 1

	select @HA_CERTIFIED = 0
	select @retstat = 0



/* check to see if we are using HA specific SP for a HA enabled server */
	exec @retstat = sp_ha_check_certified 'sp_logintrigger', @HA_CERTIFIED
	if (@retstat != 0)
        	return (1)

	if (upper(@trigname) = 'DROP')
		select @del = 1
	else
		select @del = 0
	

/*
** Check whether a login trigger already exists. If it does, update it
** or delete it, depending on the variable @del.
*/
	if exists(select 1 from master.dbo.sysattributes where
			class = @login_class 
			and attribute = @attrib 
			and object_type = @type)
	BEGIN	
		if (@del = 0)
			select @action = 2 	/* update attribute */
		else
			select @action = 3  	/* delete attribute */
	END
	else 
	BEGIN
		if (@del = 0)
			select @action = 1 	/* insert attribute */	
		else
			/* Nothing to delete. */
			return (0)
	END

/*
** First validate the row. 
*/
	if attrib_valid(@login_class, @attrib, 'LT', NULL, NULL, NULL, NULL,
		NULL, NULL, @trigname, NULL, NULL, NULL, @action) = 0         
	BEGIN
		return(1)
	END



/*
** Now insert/update/delete the row
*/
	if @action = 1
	BEGIN
		insert into master.dbo.sysattributes (class, attribute, 
			object_type, char_value)
		values (@login_class, @attrib, @type, @trigname)
	END
	else if @action = 2 
	BEGIN
	        update master.dbo.sysattributes
			set     char_value = @trigname
			where class = @login_class 
			and attribute = @attrib
			and object_type = @type

	END 
	else if @action = 3
	BEGIN
		delete master.dbo.sysattributes
		where   class = @login_class 
		and attribute = @attrib 
		and object_type = @type
	END

	if (@@error != 0)
		goto clean_lt_all

	/*
	** 19388, "Global login trigger updated."
	*/
	exec sp_getmessage 19388, @msg output
	print @msg



	/*
	** Sync the in-memory RDES with the new values
	** in sysattributes.
	*/
	if attrib_notify(@login_class, @attrib, 'LT', NULL, NULL, NULL,
			NULL, NULL, NULL, @trigname, NULL, NULL, NULL,
			@action) = 0
		return (1)
	else
		return (@retstat)
END

clean_lt_all:

	return (1)
go
exec sp_procxmode 'sp_logintrigger', 'anymode'
go
grant execute on sp_logintrigger to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_modifylogin')
begin
	drop procedure sp_modifylogin
end
go
print "Installing sp_modifylogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*	5.0	1.0	10/22/91	sproc/src/modifylogin */

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:18 2006 
*/
/*
** raiserror Messages for modifylogin [Total 14]
**
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17880, "No such account -- nothing changed."
** 17925, "You entered an invalid option name. No change was made."
** 17927, "Error in changing the value of the specified column."
** 17928, "Invalid role name specified -- nothing changed."
** 17929, "The specified role is not granted to the account -- nothing changed."
** 17930, "Specify a value for the option to be modified."
** 17932, "You entered an invalid value. No change was made."
** 17933, "Specify the name of the option to be modified."
** 18388, "You must be in the master database in order to run '%1!'."
** 18409, "The built-in function '%1!' failed. Please see the other messages printed along with this message."
** 18898, "Login script '%1!' is not valid."
** 19257, "The authentication mechanism '%1!' is not valid."
*/
/*
** sp_getmessage Messages for modifylogin [Total 5]
**
** 17926, "Option changed."
** 17934, "All overrides for the password security option have been removed."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on the companion server '%2!'."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
** 19448 "An existing login mapping for user '%1!' allows only '%2!' 
**		authentication mechanism to be used."
** 19812 "There is no login-specific '%1!' attribute set for this user."
** 19813 "The login-specific '%1!' attribute has been removed."
*/
/*
** End spgenmsgs.pl output.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_modifylogin
@loginame varchar(255),		/* the login name of the account being modified */
@option varchar(30) = NULL,	/* the option to be updated */
@value varchar(255) = NULL	/* the new character value of the option */
as
declare @suid int		/* suid of account to be modified   */
declare @msg varchar(1024)	/* message text */
declare @retstat int		/* return status from other procedures */
declare @enable_login_role int	/* value of the status bit which is used
				** for enabling a role
				*/

declare @action  int        	/* Insert, update or delete 
		            	** Sysattributes entry 
		            	*/		
declare @attrib  int        	/* attribute id in Sysattributes */
declare @passeclass   int	/* Class id in Sysattributes */
declare @int_val  int        	/* convert char input into integer */
declare @deleted  int        	/* toggle to print the right return message */ 
declare @rowcount_saved int	/* Store @@rowcount as "if-then" resets it to 0*/
declare @dummy int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare	@defdb	varchar(255)	/* User's default database */
declare	@dbname	varchar(30)	/* Parsed login script dbname */
declare	@own	varchar(30)	/* Parsed login script owner */
declare	@objname varchar(30)	/* Parsed login script name */
declare @status int		/* Output of sp_namecrack */
declare @procid	int		/* Login script id */
declare	@curdb	varchar(30)	/* User's current database */
declare @sa_role int		/* has sa_role */
declare @sso_role int		/* has sso_role */
declare @sa_audited int		/* proc_role(sa_role) was called */
declare @sso_audited int	/* proc_role(sso_role) was called */
declare @sqltext varchar(2055)	/* a string buffer for concatenated sql */	
declare @authid int		/* authe mechanism id */
declare @allauth int		/* all auth mechanisms mask */
declare @map_authid int		/* auth mech id for login mapping */
declare @map_authnm varchar(30)	/* auth mech name for login mapping */
declare @login_class int	/* sysattributes class for login mapping */
declare @login_attrib int	/* sysattributes attribute for login mapping */
declare @config int
declare @err1 int		/* temp. variable to store @@error */

declare @log_for_rep int
declare @db_rep_level_all int
declare @db_rep_level_none int
declare @db_rep_level_l1 int
declare @lt_rep_get_failed int

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2

if (@loginame is null and @option = 'login script')
begin
        exec @retstat = sp_logintrigger @value
	return @retstat
end

select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_modifylogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/* Initialize variables */
select	@rowcount_saved = 0,
	@enable_login_role = 1,
	@sa_audited = 0,
	@sso_audited = 0,
	@sa_role = charindex("sa_role", show_role()),
	@sso_role = charindex("sso_role", show_role())

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_modifylogin"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_modifylogin"
	return (1)
end

if (@option is NULL)
begin
	/*
	** 17933, "Specify the name of the option to be modified."
	*/
	raiserror 17933 
	return (1)
end
	
/* Allow NULL for 'login script' option when @loginame != 'all overrides' */
if ((@value is NULL) and ((@option != "login script") or
		(@loginame = "all overrides")))
begin
	/*
	** 17930, "Specify a value for the option to be modified."
	*/
	raiserror 17930
	return (1)
end

/* User is trying to modify user's own login */
if (suser_id(@loginame) = suser_id())
begin
	/*
	** Allow only logins with sa/sso role to modify the foll. options:
	** o "min passwd length"
	** o "passwd expiration"
	** o "max failed_logins" 
	** o "login script"
	** o "add default role"
	** o "drop default role"
	** o "authenticate with"
	*/
	

	if (@option = "min passwd length" or 
	    @option = "passwd expiration" or 
	    @option = "max failed_logins" or 
	    @option = "login script" or
            @option = "add default role" or
            @option = "drop default role" or
	    @option = "authenticate with")
	begin

		/* check if user has sa or sso role, proc_role will also do auditing
		** if required. proc_role will also print error message if required.
		*/

		if (@sa_role = 0 and @sso_role = 0)
		begin
			select @dummy = proc_role("sa_role")
			raiserror 17888, "modifylogin"
			return (1)
		end
		else
		begin
			if (@sa_role > 0)
			begin
				select @sa_audited = 1
				select @dummy = proc_role("sa_role")
			end
			if (@sso_role > 0)
			begin
				select @sso_audited = 1
				select @dummy = proc_role("sso_role")
			end
       		end
	end
end
/*
** If user is trying to modify someone else's login then
** check if user has sso role, when modifying non security-related 
** stuff sa role is also allowed. Proc_role will perform auditing
** and print error message if required.
*/
if (suser_id(@loginame) != suser_id())
begin
	if (@option = "add default role" or
		@option = "drop default role" or
		@option = "passwd expiration" or
		@option = "min passwd length" or
		@option = "max failed_logins" or
		@option = "login script" or 
		@option = "authenticate with")
	begin
		/* With or without SSO role, must be audited */
		if (@sso_audited = 0)
			select @dummy = proc_role("sso_role")

		/* Cannot proceed without SSO role */
		if (@sso_role = 0)
			return (1)
	end
	else
	begin
		/* Only SA and SSO can proceed */
		if (@sa_role = 0 and @sso_role = 0)
		begin
			select @dummy = proc_role("sa_role")/* to perform auditing if sa_role fails */
			raiserror 17888, "modifylogin"
			return(1)
		end

		/* Audit whatever has not been done yet */
		if (@sso_role > 0 and @sso_audited = 0)
			select @dummy = proc_role("sso_role")
		if (@sa_role > 0 and @sa_audited = 0)
			select @dummy = proc_role("sa_role")
	end
end

if ((@option = "passwd expiration") or (@option = "min passwd length") or 
	(@option = "max failed_logins"))
begin
	select @passeclass = class from master.dbo.sysattributes where
	object_type = "PS"

	/* With the exception of 'clear', these options expect only numbers */
	select @value = lower(@value)
	if @value != "clear"
	begin
		select @int_val = convert(int, @value)
			
		/*
		** int_val can't be less than -1 or greater than 32767
		** For "min passwd length", it can't be greater than 30
		*/
		if ((@int_val < -1) or ((@option = "min passwd length") and
			(@int_val > 30)) or (@int_val > 32767))
		begin
			/*
			** 17932, "You entered an invalid value. No 
			** change was made."
			*/
			raiserror 17932
			return (1)
		end
	end
end


/* Check if "all overrides". If so, check the new value input.
** If it is -1, then all entries in Sysattributes corresponding 
** to the attribute are deleted. Else, the entries in master.dbo.sysattributes 
** are overwritten with the new value
*/
if (@loginame = "all overrides")
begin

	if (@option = "passwd expiration")
		select @attrib = 0
	else 
	if (@option = "min passwd length")
		select @attrib = 1
	else 
	if (@option = "max failed_logins")
		select @attrib = 2
	else
	begin
		/*
		** 17925, You entered an invalid option name. No change was made."
		*/
		raiserror 17925
		return (1)
	end

	if @int_val = -1
	/* Remove all the overrides for the option */
	begin
		delete from master.dbo.sysattributes
		where class = @passeclass AND attribute = @attrib
		AND object_cinfo = "login"



		/*
		** 17934, "All overrides for the password security option 
		** have been removed."
		*/
		exec sp_getmessage 17934, @msg output
		print @msg
		return (0)
	end

	else
	/* Modify the value of the overrides for the option */
	begin
		if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
			begin tran rs_logexec


		update master.dbo.sysattributes
		set int_value = @int_val
		where class = @passeclass AND attribute = @attrib
		AND object_cinfo = "login"

		select @err1 = @@error, @rowcount_saved = @@rowcount
	


		if (@log_for_rep = 1)
		begin
			/*
			** If the 'master' database is marked for
			** replication, the T-SQL built-in 'logexec()' will
			** log for replication the execution instance of
			** this system procedure.  Otherwise, the T-SQL
			** built-in 'logexec()' is a no-op.
			*/
			if (logexec(1) != 1)
			begin
				raiserror 17756, "sp_modifylogin", "master"
				goto clean_all
			end
		end

		if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
			commit tran rs_logexec
	end
end

else
/* This must be modification for a specific login. */
begin
select @suid = suid
	from master.dbo.syslogins
	where name = @loginame

/* Check if the loginame exists */
if (@suid is NULL)
begin
	/*
	** 17880, "No such account -- nothing changed."
	*/
	raiserror 17880
	return (1)
end


/*
**  Update takes place here: option can only be fullname for C2
*/
if @option = "fullname"
begin

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



        update master.dbo.syslogins set fullname  = @value where suid = @suid
	select @rowcount_saved = @@rowcount
end
else if (@option = "login script" and @loginame != "all overrides")
begin

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



	/*
	** If the 'login script' is provided, get the object id
	** from the default database verifying that it's really 
	** a stored procedure.
	*/
	if (@value is not NULL)
	begin
		set nocount on
 
		select @defdb = dbname
		from master.dbo.syslogins
		where name = @loginame

		exec @status = sp_namecrack @value, @db = @dbname output,
			@owner = @own output, @object = @objname output

		/* If a db name is given, it has to be the user's default */
		if ((@status != 0) or
			((@dbname is not null) and (@dbname != @defdb)))
		begin
			raiserror 18898, @value
			goto clean_all
		end

		/* Verify that the object exists and its a stored proc */
		if (@own is not null)
			exec("declare @dummy int " +
				"select @dummy = 1 from " + @defdb +
				"..sysobjects where name='" + @objname + "'" +
				" and type = 'P'" +
				" and uid = user_id('" + @own + "')")
		else
			exec("declare @dummy int " +
				"select @dummy = 1 from " + @defdb +
				"..sysobjects where name='" + @objname + "'" +
				" and type = 'P'" )

		if (@@rowcount = 0)
			select @procid = NULL
		else if (@own is not null)
			select @procid = object_id(@defdb+'.'+@own+'.'+@objname)
		else
			select @procid = object_id(@defdb+'..'+@objname)

		if (@procid is NULL)
		begin
			raiserror 18898, @value
			goto clean_all
		end
	end
	else
	begin
		select @procid = NULL
	end

	update master.dbo.syslogins set procid = @procid
		where name = @loginame

	select @rowcount_saved = @@rowcount
end

else if @option = "defdb"
begin
	execute @retstat = sp_defaultdb @loginame, @value

	if (@retstat = 0)
	begin
		if (@log_for_rep = 1)
		begin
			/*
			** If the 'master' database is marked for
			** replication, the T-SQL built-in 'logexec()' will
			** log for replication the execution instance of
			** this system procedure.  Otherwise, the T-SQL
			** built-in 'logexec()' is a no-op.
			*/
			if (logexec(1) != 1)
			begin
				raiserror 17756, "sp_modifylogin", "master"
				goto clean_all
			end
		end
	end
	return (@retstat)
end
else if @option = "deflanguage"
begin
	execute @retstat = sp_defaultlanguage @loginame, @value

	if (@retstat = 0)
	begin
		if (@log_for_rep = 1)
		begin
			/*
			** If the 'master' database is marked for
			** replication, the T-SQL built-in 'logexec()' will
			** log for replication the execution instance of
			** this system procedure.  Otherwise, the T-SQL
			** built-in 'logexec()' is a no-op.
			*/
			if (logexec(1) != 1)
			begin
				raiserror 17756, "sp_modifylogin", "master"
				goto clean_all
			end
		end
	end
	return (@retstat)
end
else if @option = "add default role" or @option = "drop default role"
begin
	/* 
	** verify that the role exists
	*/
	if (role_id(@value) is NULL)
	begin
		/*
		** Invalid role name specified -- nothing changed
		*/
		raiserror 17928
		return(1)
	end

	/*
	** verify that the role is granted to the loginame
	*/
	if not exists (select 1 from master.dbo.sysloginroles 
			where suid = @suid and srid = role_id(@value))
	begin
		/*
		** The specified role is not granted to the 
		** account -- nothing changed
		*/
		raiserror 17929
		return(1)
	end

	/*
	** perform the job
	*/

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



	if @option = "add default role"
	begin
		update master.dbo.sysloginroles set 
			status = status | @enable_login_role
			where suid = @suid and srid = role_id(@value)
	end
	else if @option = "drop default role"
	begin
		update master.dbo.sysloginroles set 
			status = status & ~@enable_login_role
			where suid = @suid and srid = role_id(@value)
	end
	
	select @rowcount_saved = @@rowcount
end
else
if ((@option = "passwd expiration") or (@option = "min passwd length") or 
	(@option = "max failed_logins"))
begin
	if (@option = "passwd expiration")
		select @attrib = 0
	else 
	if (@option = "min passwd length")
		select @attrib = 1
	else 
	if (@option = "max failed_logins")
		select @attrib = 2

	if exists (select 1 from master.dbo.sysattributes where
		class = @passeclass  AND attribute = @attrib AND 
		object = @suid AND object_cinfo = "login")
		select @action = 2
       	else
       		select @action = 1

	if @value = "clear"
	begin
		if @action = 1 
		begin
			/* There is no login-specific attr for this user */ 
			exec sp_getmessage 19812, @msg output
			print @msg, @option
			return(1)
		end
		else
		begin
			/* Remove the login-specific setting for this attr */
       			select @action = 0
			if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
				begin tran rs_logexec



			delete from master.dbo.sysattributes
				where class = @passeclass
				AND attribute = @attrib
				AND object = @suid
				AND object_cinfo = "login"

			select @rowcount_saved = @@rowcount
			select @deleted = 1
		end
	end

	else if attrib_valid(@passeclass, @attrib, "PS", @suid, NULL, NULL,
		NULL, "login", @int_val, NULL, NULL, NULL, 
		NULL, @action) = 0
	begin
		/*
		** 17932, "You entered an invalid value. No
		** change was made."
		*/
		raiserror 17932
		return(1)
	end

	else
	begin
		if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
			begin tran rs_logexec



		if @action = 1
		begin
			insert into master.dbo.sysattributes(class,attribute,
				object_type,object,object_cinfo, int_value)
			  values
			  (@passeclass,@attrib,"PS",@suid, "login", @int_val)
		end
		else
		begin
			update master.dbo.sysattributes
			  set int_value = @int_val
			  where class = @passeclass AND attribute = @attrib AND
				object = @suid AND object_cinfo = "login"
		end

		select @rowcount_saved = @@rowcount
	end
end
else if @option like "auth%with"
begin
        /*
        ** Check whether authentication mechanism specified is valid or not.
        ** 'AUTH_DEFAULT' and 'AUTH_MASK' are new values added in spt_values
        ** used to obtain value of default ('ANY') authmech or authentication
        ** mask respectively. They are not valid names that the user can specify
        ** as authentication mechanism.
        */
	select  @authid = low, @config = number
	from master.dbo.spt_values
	where type = 'ua' and name = upper(@value)
	and upper(name) not in ('AUTH_DEFAULT', 'AUTH_MASK')

	if @@rowcount = 0
        begin
                /*
                ** 19257, "The authentication mechanism '%1!' is not valid."
                */
                raiserror 19257, @value
                return(1)
	end

	/*
	** Check if the authentication method is enabled.
	** SMP or SDC, one row is expected.
	*/
	if (@config != 0) and not exists(select 1
		from master.dbo.syscurconfigs a

		where a.config = @config and a.value != 0)


	begin
		/*
		** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
		*/
		exec sp_getmessage 19259, @msg output
		print @msg, @value
	end

	/*
	**  Obtain any login mapping for this login that may conflict
	**  with the new authentication mechanism being set.  The following
	**  query looks for the mapping in sysattributes by suid and
	**  by comparing authid bitmask from object_info1 with the parameter
	**  authid bitmask value. If a row is found, then prevent modifylogin
	**  action from proceeding, thus avoiding the mapping conflict
	**  with the new login restrictions.
	*/
	select @login_class = 20, @login_attrib = 0

	select @map_authid=object_info1 from master.dbo.sysattributes where
		class = @login_class and attribute = @login_attrib and
			object = @suid and ((object_info1 & @authid) = 0)
	if @@rowcount > 0
	begin
		/* Lookup the name for the authid value found. */
		select @map_authnm = name
			from master.dbo.spt_values
			where type = 'ua' and low = @map_authid

		/*		
		** 19448 "An existing login mapping for user '%1!' 
		** allows only '%2!' authentication mechanism to 
		** be used."
		*/
		raiserror 19448, @loginame, @map_authnm
		return (1)
	end

	/* Reset any auth mechanisms bits and set this one. */
	select @allauth = low
	from master.dbo.spt_values
	where type = 'ua' and upper(name) = 'AUTH_MASK'

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		begin tran rs_logexec



        /*
        ** "ANY" is the name used for default authmech in sprocs, whereas the
        **  value is obtained from AUTH_DEFAULT.
        */
        if (upper(@value) = 'ANY')
        begin
                select @authid = low from master.dbo.spt_values
                        where type = 'ua' and upper(name) = 'AUTH_DEFAULT'
        end

        update master.dbo.syslogins 
	set status =  @authid | (status & ~@allauth)
	where suid = @suid

	select @rowcount_saved = @@rowcount



	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_modifylogin", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec
end
else /* error */
begin
	/*
	** 17925, "You entered an invalid option name. No change was made."
	*/
	raiserror 17925
	return (1)
end

end

/*
**  Check @rowcount_saved when it works
*/
if (@rowcount_saved >= 1)
begin



	if (@log_for_rep = 1)
	begin
		/*
		** If the 'master' database is marked for replication, the
		** T-SQL built-in 'logexec()' will log for replication the
		** execution instance of this system procedure.  Otherwise,
		** the T-SQL built-in 'logexec()' is a no-op.
		*/
		if (logexec(1) != 1)
		begin
			raiserror 17756, "sp_modifylogin", "master"
			goto clean_all
		end
	end

	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		commit tran rs_logexec
	
	if (@deleted = 1)
	begin
		exec sp_getmessage 19813, @msg output
		print @msg, @option
	end
	else
	begin
		/*
		** 17926, "Option changed."
		*/
		exec sp_getmessage 17926, @msg output
		print @msg
	end
	return (0)
end
else
begin
	/*
	** 17927, "Error in changing the value of the specified column."
	*/
	raiserror 17927
	goto clean_all	
end

clean_all:
	if ((@log_for_rep = 1) or (@HA_CERTIFIED = 1))
		rollback tran rs_logexec
	return (1)
		
go
exec sp_procxmode 'sp_modifylogin', 'anymode'
go
grant execute on sp_modifylogin to public
go
exec sp_procxmode 'sp_modifylogin', 'rep_master'
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_encryption')
begin
	drop procedure sp_encryption
end
go
print "Installing sp_encryption"
go

/*
** Generated by spgenmsgs.pl on Tue Jul 17 17:47:44 2007 
*/
/*
** raiserror Messages for encryption [Total 20]
**
** 17260, "Can't run %1! from within a transaction."
** 17460, "Object must be in the current database."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 18291, "The parameter value '%1!' is invalid."
** 19213, "Invalid argument or unsupported command: %1!."
** 19387, "The 'encrypted columns' feature must be configured to run sp_encryption 'help'."
** 19415, "The '%1!' parameter is required for the '%2!' command."
** 19603, "There are no encryption keys (key copies) like '%1!' in '%2!'."
** 19604, "There are no encrypted columns like '%1!'."
** 19605, "There are no columns encrypted with key like '%1!' in the current database."
** 19616, "There are no encryption keys (key copies) for user name like '%1!'."
** 19630, "There are no encryption keys (key copies) encrypted with the system encryption password in current database."
** 19632, "You are not authorized to check keys (key copies) for user name like '%1!'."
** 19646, "The execution of the stored procedure '%1!' in database '%2!' was aborted because the system encryption password already exists for this database."
** 19647, "There are no encryption keys (key copies) encrypted with the system encryption password for user '%1!' in the current database."
** 19648, "There are no encryption key copies like '%1!' assigned to '%2!' in '%3!'."
** 19657, "There are no columns encrypted with key like '%1!' in all available databases."
** 19780, "You must be the Database Owner (DBO), or possess either the System Security Officer (SSO) or Key Custodian (KC) role to execute this command/procedure."
** 19781, "The system encryption password has not been set for the current database."
** 19782, "The system encryption password has not been set for all available databases."
*/
/*
** sp_getmessage Messages for encryption [Total 3]
**
** 19674, "The following encrypted column items must be addressed before performing downgrade."
** 19676, "Checking databases for downgrade readiness."
** 19677, "There are no errors which involve encrypted columns."
*/
/*
** End spgenmsgs.pl output.
*/
go

/* 
** file: encryption 
** Administer column level encryption
*/

create procedure sp_encryption 
	@cmd 		varchar(30) = null,
					/* Should be system_encr_passwd,
					** help, helpkey, helpuser, or helpcol
					*/
	@opt1		varchar(600) = null, /* Should be keyname for help,
					     ** newpasswd for system_encr_passwd,
					     ** username for helpuser
					     ** columname for helpcol	
					     */
	@opt2		varchar(600) = null, /* 
					     ** Could be "display_cols", "key_copy",
					     ** "all_dbs", "display_keys" if help or 
					     ** helpkey,
					     ** "oldpasswd" if system_encr_passwd,
					     **	"key_copy", "login_passwd_check" if helpuser
					     ** 
					     */
	@passwd_fmt	int = 0,	    /* for replication or ddlgen*/	
	@passwd_vers	int = 0		    /* for replicating or receiving
					    ** ddlgen system_encr_passwd	
					    */ 
as
declare	@retval		int 
      ,	@procval	int
      , @opt1_buf	varchar(575)	/* To disambiguate @opt1 */
      ,	@dbname		varchar(30)
      ,	@keydbname	varchar(30)
      , @username       varchar(30)
      , @callername	varchar(30)
      , @rows		int
      , @auxproc 	varchar(1024)
      , @sso_role	int		/* indicates user has sso_role */
      , @keycustodian_role int          /* indicates user has keycustodian_role */
      , @dummy		int
      , @dbid		int
      , @is_remote_tdb	int
      , @tdb_instanceid     int
      , @tdb_instancename   varchar(255)
      , @msg		varchar(1024)
      , @owner		varchar(30)
      , @objname	varchar(255)
      , @colname	varchar(255)
      , @db_offline	int             /* indicates a database that is offline */
      , @db_unrecovered  int		/* indicates a database that is not recovered */
      , @db_notrec     int              /* indicates a database that is still in recover process */
      , @db_inlddb    int               /* indicates a database that will not be recovered */
      , @db_archivedb  int              /* indicates a database taht is an archive database */
      , @system_password int
      , @sys_encr_passwd_type   int     /* indicates the type of the system_encr_passwd */ 
      , @login_password int
      , @login_access  int
      , @user_password int	
      , @key_recovery  int
      , @default_key int
      , @key_copy     int               /* indicates a key copy */
      , @encolstatus	int		/* 
					** indicated if a column is 
					** encrypted 
					*/


/* These bits are defined either in encryptkey.h or in database.h */
select @login_password = 16     /* EK_LOGINPASS */
     , @login_access = 8        /* EK_LOGINACCESS */
     , @system_password = 32	/* EK_SYSENCRPASS */
     , @user_password = 256     /* EK_USERPWD */
     , @key_recovery = 64       /* EK_KEYRECOVERY */
     , @key_copy = 16		/* EK_KEYCOPY */
     , @default_key = 4         /* EK_DEFAULT */
     , @db_offline = 16		/* DBT2_OFFLINE */
     , @db_unrecovered = 256    /* DBT_SUSPECT */
     , @db_notrec = 64		/* DBT_NOTREC */
     , @db_inlddb = 32		/* DBT_INLDDB */
     , @db_archivedb = 4194304	/* DBT3_ARCHIVEDB */
/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/

if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_encryption"
        return (1)
end
else
begin
        set chained off
end
set transaction isolation level 1

/*
**  Begin command processing.
*/

select @callername = user_name()

if (@cmd is null)
begin
	select @cmd = "null"
	select @retval = 1
end
else 
if ((@cmd not in ("help", "helpkey", "helpcol", "system_encr_passwd", "helpuser", "verify_downgrade"))
	or ((@cmd in ("help", "helpkey", "helpcol", "helpuser")) and (@passwd_fmt != 0) and (@passwd_vers != 0))) 
begin

	/*
	** 19213, "Invalid argument or unsupported command: %1!."
	*/
	if (@cmd is null)
	begin
		select @cmd = "null"
	end
	raiserror 19213, @cmd
	select @retval = 1
end

/* check for sso_role */
select @sso_role = charindex("sso_role", show_role())
select @keycustodian_role = charindex("keycustodian_role", show_role())

if (@sso_role > 0)
begin
        /* Send an audit record through the proc_role() built-in */
        select @dummy = proc_role("sso_role")
end

if (@keycustodian_role > 0)
begin
        /* Send an audit record through the proc_role() built-in */
        select @dummy = proc_role("keycustodian_role")
end


if (@cmd = "system_encr_passwd")
begin	 /* Setting the system encryption password */
	if (@opt1 is null and @opt2 is null)
	begin
		/*
		** 19415, "The '%1!' parameter is required for the '%2!' command."
		*/
		raiserror 19415, "newpasswd", "system_encr_passwd"
		return(1)
	end


	
        if (@passwd_fmt = 2)
        begin
               /*
               ** Check for existence of system password at replicate site
               ** when accepting system encr password from ddlgen. 
               ** If there is, error out.
               */
               if exists (select 1 from sysattributes 
                  where class = 25 and attribute = 0 and object_type = 'EC')
               begin
                       /*
                       ** 19646, "The execution of the stored procedure '%1!' 
                       ** in database '%2!' was aborted because the system 
                       ** encryption password already exists for this 
                       ** database."
                       */
                       select @dbname = db_name()
                       raiserror 19646, "sp_encryption", @dbname 
                       return(1)
               end
 
               if (@opt2 is not null)
               begin
                       /* 18291, "The parameter value '%1!' is invalid." */
                       raiserror 18291, @opt2
                       return 1
               end
        end

	/*
	** This transaction writes a log record for replicating the invocation
	** of this stored procedure. If logexec() fails, the transaction is
	** aborted.
	** Transaction name rs_logexec is significant and it is used by
	** Replication Server
	*/
	begin transaction rs_logexec
	/* 
	** ENCRCOL2 RESOLVE: when the nonpersistent system_encr_password
	** is implemented, the value of @sys_encr_passwd_type needs to
	** to be determined based on the value of @cmd. For now, by default
	** the type of the system_encr_passwd is 0 (SYS_ENCR_PASSWD_PERSISTENT).
	*/
	select @sys_encr_passwd_type = 0
	select @retval = encr_admin (@cmd, @opt1, @opt2, @passwd_fmt,
			@passwd_vers, @sys_encr_passwd_type)
	if (@retval != 0)
	begin
		rollback transaction rs_logexec

		/* Sufficient error messages delivered from server */
		return(1)
	end

	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		**         in database '%2!' was aborted because there
		**         was an error in writing the replication log
		**         record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_encryption", @dbname

		rollback transaction rs_logexec
		return(1)
	end

	commit transaction rs_logexec

end	/* Setting the system encryption password */ 

/*
** Verify downgrade.
*/
if (@cmd = "verify_downgrade")
begin -- { verify_downgrade.
	declare @errmsg varchar(255)
	, @tmpstr char(4)
	, @err_verify_keycopy int
	, @err_verify_key_recovery int
	, @err_verify_user_passwd int
	, @err_verify_login_passwd int
	, @err_check_key_custodian_roles int
	, @err_check_user_key_custodian_roles int
	, @err_check_SEP_len int
	, @err_check_decrypt_default int
	, @err_check_encrypted_columns int
	, @err_check_restricted_decrypt int
	, @err_check_column_datatype int
	, @ret int


/* These bits are defined either in encryptkey.h or in database.h */
select @err_verify_key_recovery = 1    /* Error for key recovery */
	, @err_verify_keycopy = 2      /* Error for keycopy existence */
	, @err_verify_user_passwd = 3  /* Error for user password */
	, @err_verify_login_passwd = 4 /* Error for login password */
	, @err_check_user_key_custodian_roles = 5 /* Error for user keycustodian roles */
	, @err_check_key_custodian_roles = 6    /* Error for keycustodian_role roles */
	, @err_check_decrypt_default = 7        /* Error for decrypt default */
	, @err_check_encrypted_columns = 8      /* Error for encrypted column */
	, @err_check_column_datatype = 9        /* Error for column datatype */
	, @err_check_SEP_len = 10               /* Error for System Encryption Password greater than 64 bytes */
	, @err_check_restricted_decrypt = 11    /* Error for restricted decrypt being set */


		print ""
		exec sp_getmessage 19676, @errmsg output	
		print @errmsg

		/* login with sso_role */
		if ((@sso_role > 0) or (@keycustodian_role > 0))
		begin -- { Roles

			create table #encrypted_verify_results(
				dbname          varchar(30) null
				, assignee        varchar(30) null
				, tabname       varchar(255) null
				, colname       varchar(255) null
				, type          tinyint null
				, length        tinyint null
				, username      varchar(30) null
				, keydbname     varchar(30) null
				, keyowner      varchar(30) null
				, keyid         int null
				, keyname       varchar(255) null
				, fullcolname   varchar(540) null
				, error         int null
				, errstr        varchar(128) null
			)
			
			create table #encrypted_table_verify(
				dbname            varchar(30) null
				, assignee        varchar(30) null
				, username        varchar(30) null
				, tabname         varchar(255) null
				, colname         varchar(255) null
				, type            tinyint null
				, length          tinyint null
				, keydbname       varchar(30) null
				, keyowner        varchar(30) null
				, keyid           int null
				, keyname         varchar(255) null
				, keystatus       int null
				, action          int null
				, fullcolname     varchar(540) null 
				, fullkeyname     varchar(315) null )


			declare database_cursor cursor for
				select name
					from master.dbo.sysdatabases
				/* Skip databases that have not recovered */
				where status & @db_unrecovered = 0
					/* Skip databases that are offline */
					and status2 & @db_offline = 0
					/* Skip databases that are not recovered */
					and status & @db_notrec = 0
					/* Skip databases that will not be recovered */
					and status & @db_inlddb = 0
					/* Skip databases that are archive databases */
					and status3 & @db_archivedb = 0
			open database_cursor
			fetch database_cursor into @dbname
			select @keydbname = db_name()
			while (@@sqlstatus = 0) 
			begin -- { beginning of while loop.
				select @auxproc = @dbname+".dbo.sp_aux_encr_verify_downgrade"
				if (@opt1 != "15.0" and @opt1 != '15.0ESD1')
				begin -- { Not 15.0 downgrade
					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'verify_keycopy', @dbname, NULL
					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'verify_key_recovery_copy', NULL
					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'verify_user_passwd', NULL
				end -- } Not 15.0 downgrade

					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'check_key_custodian_roles', @dbname

					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'check_decrypt_default', @dbname

					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'check_column_datatype' , @dbname
					truncate table #encrypted_table_verify
					exec @retval = @auxproc 'check_SEP_len', @dbname
					if (@dbname = "master")
					begin
						truncate table #encrypted_table_verify
						exec @retval = @auxproc 'check_user_key_custodian_roles', @dbname

						truncate table #encrypted_table_verify
						exec @retval = @auxproc 'check_restricted_decrypt', @dbname
					end
					if (@opt1 = "15.0" or @opt1 = '15.0ESD1')
					begin
						truncate table #encrypted_table_verify
						exec @retval = @auxproc 'check_encrypted_columns', @dbname
					end

				fetch database_cursor into @dbname

			end -- } End of while loop.
			close database_cursor
			select @dummy=count(*) from #encrypted_verify_results 

			if (@dummy > 0) -- { dummy
			begin
				select @tmpstr=convert(char(4),@dummy)
				print " "
				select @errmsg="Total Error(s) " + @tmpstr 
				print @errmsg
				print " "
				update #encrypted_verify_results
				set fullcolname = 
				case
					when (error = @err_verify_keycopy)
						then dbname + "." + keyowner + "." + keyname +'; assignee: ' + assignee
					when (error = @err_verify_key_recovery)
						then dbname + "." + keyowner + "." + keyname 
					when (error = @err_verify_user_passwd)
						then  dbname + "." + username + "." + keyname
					when (error = @err_check_key_custodian_roles)
						then dbname 
					when (error = @err_check_user_key_custodian_roles) 
						then dbname 
					when (error = @err_check_SEP_len)
						then dbname
					when (error = @err_check_decrypt_default
						or error = @err_check_encrypted_columns
						or error = @err_check_column_datatype)
						then dbname + "." 
							+ username + "." + tabname 
							+ "." + colname
					when (error = @err_check_restricted_decrypt)
						then dbname
				end
				where fullcolname is NULL


				if exists (select 1 from #encrypted_verify_results )
				begin
					print ""
					exec sp_getmessage 19674, @errmsg output	
					print @errmsg
					print ""
					exec sp_autoformat 
						@fulltabname = #encrypted_verify_results,
						@selectlist = "	'Encrypted Columns Item' = fullcolname, 
							'Required Action' = errstr", 
						@orderby = "order by error"
				end

				select @ret=1
			end -- } dummy
			else
			begin
				print ""
				exec sp_getmessage 19677, @errmsg output	
				print @errmsg
				select @ret=0
		end
		deallocate cursor database_cursor
		drop table #encrypted_verify_results
		drop table #encrypted_table_verify
		return @ret
	end -- } login with sso_role 
end -- } verify_downgrade.

/* 
** SP_ENCRYPTION HELP|HELPKEY [, KEY_NAME | WILDCARD]
**                   [, ALL_DBS | KEY_COPY | DISPLAY_COLS]
** SP_ENCRYPTION HELP|HELPKEY, SYSTEM_ENCR_PASSWORD [, DISPLAY_KEYS | ALL_DBS]
*/
if ((@cmd = "help") or (@cmd = "helpkey"))
begin	/* Display key related information */ 
	if not exists (select 1 from sysobjects where name = 'sysencryptkeys')
	begin
		raiserror 19387
		return(1)
	end

	if ((@opt2 is not null) and (@opt2 not in('all_dbs', 'display_cols', 
	                                           'key_copy', 'display_keys')))
	begin
		/* 18291, "The parameter value '%1!' is invalid." */
		raiserror 18291, @opt2
		return 1
	end

	/*
	** SP_ENCRYPTION HELP|HELPKEY, SYSTEM_ENCR_PASSWD [, DISPLAY_KEYS | ALL_DBS]
	** Display system_encr_passwd related information
	*/
	/*
	** SP_ENCRYPTION HELP|HELPKEY, SYSTEM_ENCR_PASSWD, DISPLAY_KEYS
	** Displays all keys that are encrypted with 
	** the system encryption passwords
	*/
	if ((@opt1 = "system_encr_passwd") and (@opt2 = "display_keys"))
	begin
		/* Accumulate encryption key info in a temporary table */
		create table #encr_keys_info(assignee varchar(30) null,
                                                keyname varchar(255) null,
						keyowner varchar(30) null,
						fullkeyname varchar(285) null)
               
		if ((@sso_role > 0) or (@keycustodian_role > 0) or (user_name() = "dbo"))
		begin                
			insert #encr_keys_info(assignee, keyname, keyowner)
				select user_name(e1.uid), o1.name, user_name(o1.uid)
				from sysobjects o1, sysencryptkeys e1, sysattributes a1
				where o1.id = e1.id
				   and (e1.status & @system_password) > 0
	                	   and a1.class = 25
			           and a1.attribute = 0
				   and a1.object_type = "EC"

			if not exists (select 1 from #encr_keys_info)
			begin
				/* 
				** 19630, "There are no encryption keys encrypted with 
				** the system encryption password."
				*/
				raiserror 19630
				return(1)
			end

		end	
		else
		begin	
			/* 
			** Display the encryption key info for 
			** non-privileged user 
			*/
			insert #encr_keys_info(assignee, keyname, keyowner)
				select user_name(e1.uid), o1.name, user_name(o1.uid)
				from sysobjects o1, sysencryptkeys e1, sysattributes a1
				where o1.id = e1.id
				   and (e1.status & @system_password) > 0
				   and (user_name(e1.uid) = user_name() or user_name(o1.uid) = user_name())
				   and a1.class = 25
			           and a1.attribute = 0
				   and a1.object_type = "EC"

			if not exists (select 1 from #encr_keys_info)
			begin
				/* 
				** 19647, "There are no encryption keys (key copies) 
				** encrypted with the system encryption password
				** for user '%1!' in the current database."
				*/
				raiserror 19647, @callername 
				return(1)
			end

		end				


		/* update #encr_keys_info to fill fullkeyname column */
		update #encr_keys_info
		set fullkeyname = keyowner + "." + keyname
		where fullkeyname is NULL

		/* Display the encryption key info */
		exec sp_autoformat @fulltabname = #encr_keys_info,
		@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee",
		@orderby = "order by fullkeyname"
		
		drop table #encr_keys_info	
	end
	
	/*
	** SP_ENCRYPTION HELP|HELPKEY, SYSTEM_ENCR_PASSWD [, ALL_DBS]
	**
	** Displays the properties of the system encryption password
	** in the current database or all avaiable databases.
	*/
	else if ((@opt1 = "system_encr_passwd") and ((@opt2 = "all_dbs") or (@opt2 = NULL)))
	begin
		/* Accumulate system encryption password info in a temporary table */
		create table #sys_encr_passwd_info(dbname varchar(30) null,
                                                typeofpasswd varchar(30) null,
						modifier varchar(30) null,
						moddate smalldatetime null)
		/* 
		** SP_ENCRYPTION HELP|HELPKEY, SYSTEM_ENCR_PASSWD, ALL_DBS
		** Display the system encryption password information across
		** all available databases.
		*/
		if (@opt2 = "all_dbs")
		begin

			/* Only SSO can run this command */
			if (@sso_role = 0)
			begin
				select @dummy = proc_role("sso_role")
				return (1)
			end

			declare database_cursor cursor for
			select name, dbid
			from master.dbo.sysdatabases
				/* Skip databases that have not recovered */
				where status & @db_unrecovered = 0 
				/* Skip databases that are offline */
				and status2 & @db_offline = 0
				/* Skip databases that are not recovered */
				and status & @db_notrec = 0
				/* Skip databases that will not be recovered */
				and status & @db_inlddb = 0
				/* Skip databases that are archive databases */
				and status3 & @db_archivedb = 0
		
			open database_cursor
			fetch database_cursor into @dbname, @dbid

			while (@@sqlstatus = 0) 
			begin
				/*
                                ** In SDC, skip local tempdbs that are only
                                ** accessible from remote instances.
                                */

				select @auxproc =
				@dbname+".dbo.sp_aux_sys_encr_passwd_lookup"

				/*
				** Since sp_aux_sys_encr_passwd_lookup is a system
				** stored procedure, it will execute in the
				** context of dbname if it is called as
				** dbname..sp_aux_sys_encr_passwd_lookup, regardless of
				** which db it is called from.
				**
				** This auxilliary procedure is used to extract
				** the information about system encryption password.
				*/

				exec @auxproc @dbname

				select @retval = @@error

				if (@retval != 0)
				begin
					close database_cursor
					deallocate cursor database_cursor
					return (1)	
				end
				fetch database_cursor into @dbname, @dbid
			end

			close database_cursor
			deallocate cursor database_cursor

			if not exists (select 1 from #sys_encr_passwd_info)
			begin
				/*
				** 19782, "The system encryption password has 
				** not been set for all available databases."
				*/
				raiserror 19782
				return(1)
			end
		end  /* end of all_dbs */
		/* 
		** SP_ENCRYPTION HELP|HELPKEY, SYSTEM_ENCR_PASSWD
		** Display the system encryption password information in 
		** the current database.
		*/
		else
		begin
			/* Only SSO, KC, or DBO can run this command */
			if (@sso_role = 0 and @keycustodian_role = 0 and (user_name() != "dbo") )
			begin
				/* 
				** 19780, "You must be the Database Owner (DBO), or 
				** possess either the System Security Officer (SSO) or 
				** Key Custodian (KC) role to execute this command/procedure.
				*/
				raiserror 19780				
				return (1)
			end

			select @dbname = db_name()
			select @auxproc =
				@dbname+".dbo.sp_aux_sys_encr_passwd_lookup"

			exec @auxproc @dbname

			if not exists (select 1 from #sys_encr_passwd_info)
			begin
				/*
				** 19781, "The system encryption password has 
				** not been set for the current database."
				*/
				raiserror 19781
				return(1)
			end

		end
			
		/*
		** Display the system encryption password info
		*/
		exec sp_autoformat @fulltabname = #sys_encr_passwd_info,
		@selectlist = "'Database' = dbname, 'Type of system_encr_passwd' = typeofpasswd,  'Last modified by' = modifier, 'Date' = moddate ",
		@orderby = "dbname "
		
		drop table #sys_encr_passwd_info

		return (0)


	end
	/* 
	** SP_ENCRYPTION HELP|HELPKEY
	** SP_ENCRYPTION HELP|HELPKEY, KEY_NAME|WILDCARD
	**                   [, ALL_DBS | KEY_COPY | DISPLAY_COLS] 
	*/
	else
	begin
		/*
		** Validate the current database and disambiguate the fully qualified 
		** column name 
		*/
		select @objname = @opt1
		select @opt1_buf = @opt1
		if (@opt1_buf like "%.%.%")
		begin
			if ((substring(@opt1_buf, 1, charindex(".", @opt1_buf) - 1) != 
				db_name()) and (@opt2!= "all_dbs"))
			begin
				/* 17460, "Object must be in the current database." */
				raiserror 17460
				return  (1)
			end
			
			/* Extract the database name */
			select @keydbname = substring(@opt1_buf, 1, charindex(".",
				@opt1_buf)-1)
			select @opt1_buf = substring(@opt1_buf, 
				charindex(".", @opt1_buf)+1, 
				char_length(@opt1_buf))
			/* Extract the owner name */
			select @owner = substring(@opt1_buf, 1, charindex(".", 
				@opt1_buf)-1)
			/* Extract the object name */
			select @objname = substring(@opt1_buf, charindex(".",
				@opt1_buf)+1, char_length(@opt1_buf))

		end
		if (@opt1_buf like "%.%")
		begin
			/* Extract the owner name */
			select @owner = substring(@opt1_buf, 1, charindex(".", @opt1_buf)-1)
			/* Extract the object name */
			select @objname = substring(@opt1_buf, charindex(".", @opt1_buf)+1,
					char_length(@opt1_buf))
		end

		if (@opt1 is NULL)
		begin
			select @opt1 = "%"
		end

		if (@keydbname is NULL)
		begin
			select @keydbname = "%"
		end

		if (@owner is NULL)
		begin
			select @owner = "%"
		end

		if (@objname is NULL)
		begin
			select @objname = "%"
		end
                
		/* 
		** SP_ENCRYPTION HELP|HELPKEY, KEYNAME|WILDCARD, DISPLAY_COLS
		**
		** Non-privileged user gets info only in current db and sso gets
		** info across all dbs.
		*/
		if ((@opt2 = "display_cols"))
		begin
			if not exists (select 1 from (select o1.name 
							from sysobjects o1
							where o1.type = "EK"
							and o1.name like @objname
							and user_name(o1.uid) like @owner) t)

			begin
					/*
					** 19603, "There are no encryption keys (key copies) like 
					** '%1!' in '%2!'."
					*/
					select @dbname = db_name()
					raiserror 19603, @opt1, @dbname 
					return(1)		
			end
	
			/* Accumulate keys and columns in a temporary table */
			create table #encrypted_column_info(
				keyname varchar(255) null, 
				keyowner varchar(30) null,
				dbname varchar(30) null,
				username varchar(30) null,
				objname varchar(255) null,
				colname varchar(255) null)

			/* login with sso_role */
			if (@sso_role > 0)
			begin

				declare database_cursor cursor for
				select name, dbid

				from master.dbo.sysdatabases
					/* Skip databases that have not recovered */
					where status & @db_unrecovered = 0 
					/* Skip databases that are offline */
					and status2 & @db_offline = 0
					/* Skip databases that are not recovered */
					and status & @db_notrec = 0
					/* Skip databases that will not be recovered */
					and status & @db_inlddb = 0
					/* Skip databases that are archive databases */
					and status3 & @db_archivedb = 0
		
				open database_cursor
				fetch database_cursor into @dbname, @dbid


				select @keydbname = db_name()

				while (@@sqlstatus = 0) 
				begin


					select @auxproc =
					@dbname+".dbo.sp_aux_encr_lookup"

					/*
					** Since sp_aux_encr_lookup is a system
					** stored procedure, it will execute in the
					** context of dbname if it is called as
					** dbname..sp_aux_encr_lookup, regardless of
					** which db it is called from.
					**
					** This auxillary procedure is used to extract
					** the qualified column name that the specified
					** key encrypts.
					*/

					exec @auxproc @owner, @objname, @keydbname

					select @retval = @@error, @rows = @@rowcount

					if (@retval != 0)
					begin
						close database_cursor
						deallocate cursor database_cursor
						return (1)	
					end

					if (@rows != 0)
					begin
						update #encrypted_column_info
						set dbname = @dbname
						where dbname is NULL

					end

					fetch database_cursor into @dbname, @dbid

				end
				close database_cursor
				deallocate cursor database_cursor

				if not exists (select 1 from #encrypted_column_info)
				begin
					/*
					** 19657, "There are no columns encrypted
					** with key like '%1!' in all available
					** databases."
					*/
					raiserror 19657, @opt1
					return (1)
				end



			end	/* Login with sso_role */
			
			else    /* Login without sso_role */

			/*
			** ENCR2_RESOLVE: Currently there is no graceful way (without
			**  warnings) to check and see if a login is a valid user in a
			** database. A new Built-in has been proposed to check this.
			** So until this is done, non-privileged users get key-column
			** association information only from current database.
			*/
			begin 

				insert #encrypted_column_info(keyname, keyowner, 
					username, objname, colname)
				select o2.name, user_name(o2.uid), user_name(o1.uid), o1.name, 
					c.name
				from syscolumns c, sysobjects o1, sysobjects o2
				where c.id = o1.id 
					and c.encrkeyid = o2.id
					and o2.type in ('EK')
					and o2.name like @objname
					and user_name(o2.uid) like @owner

				if not exists (select 1 from #encrypted_column_info)
				begin
					/*
					** 19605, "There are no columns encrypted
					** with key like '%1!' in the current database."
					*/
					raiserror 19605, @opt1
					return (1)
				end

			end	 /* Login without sso_role */



			/* 
			** Fill dbname with current database name
			** Note that dbname is not null for sso_role case
			** because it is already filled
			*/
			update #encrypted_column_info
			set dbname = db_name()
			where dbname is NULL
			
			/*
			** Display the encrypted column info
			*/
			exec sp_autoformat @fulltabname = #encrypted_column_info,
			@selectlist = "'Key Name' = keyname, 'Key Owner' = keyowner,  'Database Name' = dbname, 'Table Owner' = username, 'Table Name' = objname, 'Column Name' = colname",
			@orderby = "order by keyname, keyowner, dbname,	username, objname, colname "
		
			drop table #encrypted_column_info

			return (0)
		end
	
		/* 
		** SP_ENCRYPTION HELP|HELPKEY, KEYNAME|WILDCARD [, ALL_DBS]]
		*/
		if ((@opt2 is NULL) or (@opt2 = "all_dbs"))
		begin
			/* Accumulate encryption key info in a temporary table */
			create table #encr_column_info(keyname varchar(255),
						keyowner varchar(30),
						keydbname varchar(30),
						keylength int,
						keyalgorithm varchar(30),
						keytype int,
						random_pad int,
						init_vector int,
						typeofpasswd varchar(30),
						keyrecovery int)

			/* Create a temporary table to store the keycopynum info */
			create table #encr_column_count(keyname varchar(255),
						keyowner varchar(30),
						keydbname varchar(30),
						keylength int,
						keyalgorithm varchar(30),
						keytype varchar(30),
						random_pad int,
						init_vector int,
						typeofpasswd varchar(30),
						keyrecovery int,
						keycopynum int,
						fullkeyname varchar(315) null)
			/* 
			** SP_ENCRYPTION HELP|HELPKEY, KEYNAME|WILDCARD, ALL_DBS
			**
			** Display key properties across all databases
			*/
			if (@opt2 = "all_dbs")
			begin

				/* check if user has sso role, proc_role will 
				** also do auditing if required.
				** proc_role will also print error message if required.
				*/
				if (proc_role("sso_role") = 0)
				begin
					return (1)
				end

				declare db_cursor cursor for 
				select name, dbid
				from master.dbo.sysdatabases
					/* Skip databases that have not recovered */
					where status & @db_unrecovered = 0 
					/* Skip databases that are offline */
					and status2 & @db_offline = 0
					/* Skip databases that are not recovered */
					and status & @db_notrec = 0
					/* Skip databases that will not be recovered */
					and status & @db_inlddb = 0
					/* Skip databases that are archive databases */
					and status3 & @db_archivedb = 0

					/* 
					** Loop through only matching specified
					** database names.
					*/
					and name like @keydbname

		
				open db_cursor
				fetch db_cursor into @dbname, @dbid

				while (@@sqlstatus = 0)
				begin

					/*
					**
					** Since sp_aux_encrkey_info is a system
					** stored procedure, it will execute in the
					** context of dbname if it is called as
					** dbname..sp_aux_encrkey_info, regardless of
					** which db it is called from.
					**
					** This auxillary procedure is used to extract
					** the key properties. 
					*/
					select @auxproc =	
					@dbname+".dbo.sp_aux_encrkey_info"
		
					exec @auxproc @owner, @objname

					select @retval = @@error
					if (@retval != 0)
					begin
						close db_cursor
						deallocate cursor db_cursor
						return (1)	
					end
		
					fetch db_cursor into @dbname, @dbid
				end

				close db_cursor
				deallocate cursor db_cursor

				/*
				** Inserting into temporary table because sp_autoformat
				** currently does not support group by clause.
				** We display number of keycopies (not including the keybase one),
				** That's the reason of using count(*)-1 in the following sql.
				*/
				insert #encr_column_count(keyname, keyowner, keydbname, 
							  keylength, keyalgorithm, 
							  keytype, random_pad, init_vector,
						          typeofpasswd, keyrecovery, keycopynum)
                                select t1.keyname, t1.keyowner, t1.keydbname, t1.keylength
					, t1.keyalgorithm 
					, case (t1.keytype & @default_key)
						when 0 then "symmetric key"
						else "symmetric default key"
			  		end					
					, t1.random_pad
				        , t1.init_vector, t1.typeofpasswd, t1.keyrecovery
					, t2.keycopynum
				from #encr_column_info t1, (select t3.keyname as keyname, 
								t3.keyowner as keyowner, 
								t3.keydbname as keydbname, 
								count(*)-1 as keycopynum
							     from #encr_column_info t3
							     group by t3.keydbname, t3.keyowner, t3.keyname
							   ) t2 
				where (t1.keytype & @key_copy) = 0
                                   and t1.keyname = t2.keyname
				   and t1.keydbname = t2.keydbname
				   and t1.keyowner = t2.keyowner

				if not exists (select 1 from #encr_column_count)
				begin
					/*
					** 19603, "There are no encryption keys (key copies) like 
					** '%1!' in '%2!'."
					*/
					raiserror 19603, @opt1, "all databases"
					return(1)
				end
	
				/* update #encr_column_count to fill fullkeyname column */
				begin	
					update #encr_column_count
					set fullkeyname = keydbname + "." + keyowner + "." + keyname
					where fullkeyname is NULL
				end

				/* Display the encryption key info */
				exec sp_autoformat @fulltabname = #encr_column_count,
				@selectlist = "'Db.Owner.Keyname' = fullkeyname, 'Key Length' = keylength, 'Key Algorithm' = keyalgorithm, 'Key Type' = keytype, 'Pad' = random_pad, 'Initialization Vector' = init_vector, 'Type of Password' = typeofpasswd, 'Key Recovery' = keyrecovery, '# of Key Copies'= keycopynum",
				@orderby = "order by fullkeyname"
			end	/* Display key properties across all dbs */
			else

			/* 
			** SP_ENCRYPTION HELP|HELPKEY [, KEYNAME | WILDCARD]
			** 
			** Lists the properties of base keys in current database
			*/
			begin
				select @dbname = db_name()
				/*
				** Since sp_aux_encrkey_info is a system
				** stored procedure, it will execute in the
				** context of dbname if it is called as
				** dbname..sp_aux_encrkey_info, regardless of
				** which db it is called from.
				**
				** This auxillary procedure is used to extract
				** the key properties. 
				*/
				select @auxproc =	
				@dbname+".dbo.sp_aux_encrkey_info"
		
				exec @auxproc @owner, @objname

				select @retval = @@error
				if (@retval != 0)
				begin
					return (1)	
				end

				/*
				** Inserting into temporary table because sp_autoformat
				** currently does not support group by clause.
				*/

				/* 
				** A typical #encr_column_info t3 before the following query statement
				** is like:
				** 
				** keydbname	keyname   keyowner  keylength  ...  keyrecovery  keycopynum
				** ---------    -------   --------  ---------       -----------  ----------
				** tdb1		key1	  dbo	    128             0            0         (base key)	
				** tdb1		key1      dbo       128             1            0         (key copy)
				** tdb1         key1      dbo       128             0            0         (key copy)
				** tdb1		key2	  dbo       128		    0            0         (base key)
				**
				** sp_encryption help only shows key information about the base keys.
				** We use the subquery in the following statement to get the correct value of 
				** keyrecovery and keycopynum.
				**
				*/

				insert #encr_column_count(keyname, keyowner, keydbname, 
							  keylength, keyalgorithm, 
							  keytype, random_pad, init_vector,
						          typeofpasswd, keyrecovery, keycopynum)
                                select t1.keyname, t1.keyowner, t1.keydbname, t1.keylength
					, t1.keyalgorithm 
					, case (t1.keytype & @default_key)
						when 0 then "symmetric key"
						else "symmetric default key"
			  		end					
					, t1.random_pad
				        , t1.init_vector
					, t1.typeofpasswd 
					, t2.keyrecovery
					, t2.keycopynum
				from #encr_column_info t1, (select t3.keyname as keyname, 
								t3.keyowner as keyowner,
								t3.keydbname as keydbname,
								sum(t3.keyrecovery) as keyrecovery,
								count(t3.keyname)-1 as keycopynum
							     from #encr_column_info t3
							     group by t3.keydbname, t3.keyowner, t3.keyname
							   ) t2
				where (t1.keytype & @key_copy) = 0
                                and t1.keyname = t2.keyname
				and t1.keyowner = t2.keyowner
				and t1.keydbname = t2.keydbname

				if not exists (select 1 from #encr_column_count)
				begin
					/*
					** 19603, "There are no encryption keys (key copies) like 
					** '%1!' in '%2!'."
					*/
					raiserror 19603, @opt1, @dbname
					return(1)
				end
				if ((@sso_role > 0) or (@keycustodian_role > 0) 
					or (user_name() = "dbo"))				
				begin	
					/* Display the encryption key info */
					exec sp_autoformat @fulltabname = #encr_column_count,
					@selectlist = "'Key Name' = keyname, 'Key Owner' = keyowner, 'Key Length' = keylength, 'Key Algorithm' = keyalgorithm, 'Key Type' = keytype, 'Pad' = random_pad, 'Initialization Vector' = init_vector, 'Type of Password' = typeofpasswd, 'Key Recovery' = keyrecovery, '# of Key Copies' = keycopynum",
					@orderby = "order by keyname, keyowner"
				end
				else
				begin
					/* 
					** Display the encryption key info for 
					** non-privileged user 
					*/
					exec sp_autoformat @fulltabname = #encr_column_count,
					@selectlist = "'Key Name' = keyname, 'Key Owner' = keyowner, 'Key Type' = keytype",
					@orderby = "order by keyname, keyowner"
				end	
			end
			drop table #encr_column_info
			drop table #encr_column_count
		end
		
        	/*
		** SP_ENCRYPTION HELP|HELPKEY, KEYNAME|WILDCARD, KEY_COPY
		**
		** Lists all the user access copies of a given key in the current
		** database. 
		*/
		if ((@opt2 = "key_copy"))
		begin
			/* Accumulate encryption key info in a temporary table */
			create table #encryption_keys_info(keyowner varchar(30) null,
                                                keyname varchar(255) null,
						assignee varchar(30) null,
						typeofpasswd varchar(30) null,
						keyrecovery int null,
						fullkeyname varchar(285) null)

			if ((@sso_role > 0) or (@keycustodian_role > 0) 
					or (user_name() = "dbo"))	
			begin                
				insert #encryption_keys_info(keyowner, keyname, assignee,
						typeofpasswd, keyrecovery)
				select user_name(o1.uid),  o1.name, user_name(e1.uid)
					, case  
						when (e1.status & @login_access) > 0 then "Login Access"
						when (e1.status & @login_password) > 0 then "Login Passwd"
                                		when (e1.status & @system_password) > 0 then "System Encr Passwd"
                               			when (e1.status & @user_password) > 0 then "User Passwd"
			  		end
					, case (e1.type & @key_recovery)
						when 0 then 0
						else 1
					  end
				from sysobjects o1, sysencryptkeys e1
				where o1.id = e1.id
	                	    and e1.type & @key_copy > 0
				    and o1.name like @objname
				    and user_name(o1.uid) like @owner

				if not exists (select 1 from #encryption_keys_info)
				begin
					/*
					** 19603, "There are no encryption keys (key copies) like 
					** '%1!' in '%2!'."
					*/
					select @dbname = db_name()
					raiserror 19603, @opt1, @dbname
					return(1)
				end

				/* update #encryption_keys_info to fill fullkeyname column */
				update #encryption_keys_info
				set fullkeyname = keyowner + "." + keyname
				where fullkeyname is NULL

				/* Display the encryption key info */
				exec sp_autoformat @fulltabname = #encryption_keys_info,
				@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee, 'Type of Password' = typeofpasswd, 'Key Recovery' = keyrecovery",
				@orderby = "order by fullkeyname"
			end	
			else
			begin	
				/* 
				** Display the encryption key info for non-privileged user. 
				** A non-privileged key owner can see key copies
				** of his key, and other non-privileged users can only see key copies
				** that were assigned to them. 
				*/
				insert #encryption_keys_info(keyowner, keyname, assignee,
						typeofpasswd, keyrecovery)
				select  user_name(o1.uid), o1.name, user_name(e1.uid) 
					, case  
						when (e1.status & @login_access) > 0 then "Login Access"
						when (e1.status & @login_password) > 0 then "Login Passwd"
                                		when (e1.status & @system_password) > 0 then "System Encr Passwd"
                                		when (e1.status & @user_password) > 0 then "User Passwd"
			  		end
					, case (e1.type & @key_recovery)
						when 0 then 0
						else 1
					end
				from sysobjects o1, sysencryptkeys e1
				where o1.id = e1.id
	        	        	and e1.type & @key_copy > 0
					and o1.name like @objname
					and (user_name(e1.uid) = user_name()
						or user_name(o1.uid) = user_name())

				/* to check if we get something */
				if not exists (select 1 from #encryption_keys_info)
				begin
					/*
					** 19648, "There are no encryption key copies 
					** like '%1!' assigned to '%2!' in '%3!'."
					*/
					select @dbname = db_name()
					raiserror 19648, @opt1, @callername, @dbname
					return(1)
				end
	
				/* update #encryption_keys_info to fill fullkeyname column */
				update #encryption_keys_info
				set fullkeyname = keyowner + "." + keyname
				where fullkeyname is NULL
	
				/* Display the encryption key info */
				exec sp_autoformat @fulltabname = #encryption_keys_info,
				@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee, 'Type of Password' = typeofpasswd, 'Key Recovery' = keyrecovery",
				@orderby = "order by fullkeyname"
			end	
	        	drop table #encryption_keys_info
		end
	end	
end 

/* 
** SP_ENCRYPTION HELPCOL [, COLUMNNAME]
**
** Displays matched column name in current database along with the key 
** used to encrypt the column. 

** For sso, all dbs will be searched wheras for non-privileged users, it 
** applies only to the current db. If the key is present in a different 
** db, then for non-privileged users, the keyid will be displayed instead
** of keyname.
*/
if (@cmd = "helpcol")
begin
	if (@opt2 is not null)
	begin
		/* 19213, "Invalid argument or unsupported command: %1!." */
		raiserror 19213, @opt2
		return  (1)
	end

	/*
	** Resolve @opt1 based on qualified name.
	** The rules are as follows,
	** 1) name -> looks for encrypted columns in table 'name'.
	** If none found, looks for all columns of that 'name'.
	** 2) name.name -> looks for existence of owner.table 
	** If none found, looks for single column table.column 
	** 3) name.name.name -> looks for column based on table.owner.name
	*/
	select @opt1_buf = @opt1
	if (@opt1_buf like "%.%.%.%")
	begin
		if (substring(@opt1_buf, 1, charindex(".", @opt1_buf) - 1) != 
			db_name())
		begin
			/* 17460, "Object must be in the current database." */
			raiserror 17460
			return  (1)
		end
		else
		begin
			/* Strip the database name */
			select @opt1_buf = substring(@opt1_buf, 
				charindex(".", @opt1_buf)+1, 
				char_length(@opt1_buf))
			/* Extract the owner name */
			select @owner = substring(@opt1_buf, 1, charindex(".", 
				@opt1_buf)-1)
			select @opt1_buf = substring(@opt1_buf, charindex(".",
				@opt1_buf)+1, char_length(@opt1_buf))
			/* Extract the table name */
			select @objname = substring(@opt1_buf, 1, charindex(".", 
				@opt1_buf)-1)
			/* Extract the column name */
			select @colname = substring(@opt1_buf, charindex(".", 
				@opt1_buf)+1,
				char_length(@opt1_buf))
		end
	end
	else if (@opt1_buf like "%.%.%")
	begin
		/* Extract the owner name */
		select @owner = substring(@opt1_buf, 1, charindex(".", @opt1_buf)-1)
		select @opt1_buf = substring(@opt1_buf, charindex(".", @opt1_buf)+1,
			char_length(@opt1_buf))
		/* Extract the table name */
		select @objname = substring(@opt1_buf, 1, charindex(".", @opt1_buf)-1)
		/* Extract the column name */
		select @colname = substring(@opt1_buf, charindex(".", @opt1_buf)+1,
			char_length(@opt1_buf))
	end
	else if (@opt1_buf like "%.%")
	begin
		/* Extract the table name */
		select @owner = substring(@opt1_buf, 1, charindex(".", @opt1_buf)-1)
		/* Extract the column name */
		select @objname = substring(@opt1_buf, charindex(".", @opt1_buf)+1,
			char_length(@opt1_buf))
		select @colname = "%"
		if not exists (select 1 from sysobjects where name like @objname and
			user_name(uid) like @owner)
		begin
			select @colname = @objname
			select @objname = @owner
			select @owner = "%"
		end
	end
	else if (@opt1_buf is not NULL)
	begin	
		/* Check if table/view specified exists */
		if exists (select 1 from sysobjects 
			where type in ("S", "U", "V")
				and name like @opt1_buf)
		begin
			select @owner = "%"
			select @objname = @opt1_buf
			select @colname = "%"
		end
		else
		begin
			select @owner = "%"
			select @objname = "%"
			select @colname = @opt1_buf
		end
	end
	else 
	begin
		select @owner = "%"
		select @opt1 = "%"
		select @objname = @opt1
		select @colname = "%"
	end

	if (@owner is NULL)
	begin
		select @owner = "%"
	end

	if (@objname is NULL)
	begin
		select @objname = "%"
	end

	if (@colname is NULL)
	begin
		select @colname = "%"
	end

	/*
	** Accumulate encrypted columns and their tables in a 
	** temporary table 
	*/
	create table #encrypted_table_info(
		username varchar(30) null,
		tabname varchar(255) null,
		colname varchar(255) null,
		keydbname varchar(30) null,
		keyowner varchar(30) null,
		keyid int null,
		keyname varchar(255) null,
		fullcolname varchar(540) null,
		fullkeyname varchar(315) null)

        /* 
	** A temporary table to store the keydbnames which
	** is needed by cursor db_cursor
	*/		
	create table #keydbname_table(keydbname varchar(30) null)


	select @dbname = db_name()
	/* Indicates an encrypted column status */
	select @encolstatus = 128
	
	insert #encrypted_table_info(username, tabname, colname, keydbname, 
		keyid)
	select user_name(o.uid), o.name, c.name
		, case c.encrkeydb
			when null then @dbname
			else c.encrkeydb
		  end
		, c.encrkeyid
	from sysobjects o, syscolumns c
	where ((c.status2 & @encolstatus) = @encolstatus)
		and o.id = c.id	
		and user_name(o.uid) like @owner
		and o.name like @objname
		and c.name like @colname

	insert #keydbname_table 
	select k.keydbname
	from #encrypted_table_info k, master.dbo.sysdatabases s
	where k.keydbname = s.name
		/* Skip databases that have not recovered */
		and s.status & @db_unrecovered = 0 
		/* Skip databases that are offline */
		and s.status2 & @db_offline = 0
		/* Skip databases that are not recovered */
		and s.status & @db_notrec = 0
		/* Skip databases that will not be recovered */
		and s.status & @db_inlddb = 0
		/* Skip databases that are archive databases */
		and s.status3 & @db_archivedb = 0
	
	if (@sso_role > 0)
	begin

		declare db_cursor cursor for 
		select keydbname from #keydbname_table
		
		open db_cursor
		fetch db_cursor into @dbname

		while (@@sqlstatus = 0)
		begin	
			/*
			** Since sp_aux_encrkey_lookup is a system
			** stored procedure, it will execute in the
			** context of dbname if it is called as
			** dbname..sp_aux_encrkey_lookup, regardless of
			** which db it is called from.
			**
			** This auxillary procedure is used for
			** extracting key name for specified
			** keyids.
			*/
			select @auxproc =	
			@dbname+".dbo.sp_aux_encrkey_lookup"
		
			exec @auxproc 

			select @retval = @@error
			if (@retval != 0)
			begin
				close db_cursor
				deallocate cursor db_cursor
				return (1)	
			end
		
			fetch db_cursor into @dbname

		end	
		close db_cursor
		deallocate cursor db_cursor
	end
	else
	begin
		/*
		** ENCR2_RESOLVE: Currently there is no graceful way (without
		**  warnings) to check and see if a login is a valid user in a
		** database. A new Built-in has been proposed to check this.
		** So until this is done, non-privileged users get keyids
		** for those keys that are not in current database.
		*/

		update #encrypted_table_info
		set keyowner = user_name(o.uid)
			, keyname = o.name
		from sysobjects o
		where o.id = keyid
		and db_name() = keydbname

	end

	if not exists (select 1 from #encrypted_table_info)
	begin
		/* 
		** 19604, "There are no encrypted columns like 
		** '%1!'."
		*/
		raiserror 19604, @opt1
		return (1)
	end

	/* Update fullcolname and fullkeyname */
	update #encrypted_table_info
	set fullcolname = username + "." + tabname + "." + colname
	where fullcolname is NULL

	update #encrypted_table_info
	set fullkeyname =
		case keyname
			when NULL then keydbname + "." + convert(varchar(10), keyid)
			else keydbname + "." + keyowner + "." + keyname
		end
	where fullkeyname is NULL

	exec sp_autoformat @fulltabname = #encrypted_table_info,
	@selectlist = "'Owner.Table.Column' = fullcolname, 'Db.Owner.Keyname' = fullkeyname",
	@orderby = "order by fullcolname, fullkeyname"

	drop table #encrypted_table_info
end



/* 
** SP_ENCRYPTION HELPUSER [, USERNAME | WILDCARD] [, KEY_COPY | LOGIN_PASSWD_CHECK]
**
** Displays the keys owned/assigned to a user in the current database.
*/
if (@cmd = "helpuser")
begin	

	if ((@opt2 is not null) and (@opt2 not in ('key_copy','login_passwd_check')))
	begin
		/* 18291, "The parameter value '%1!' is invalid." */
		raiserror 18291, @opt2
		return 1
	end
	
	select @opt1_buf = @opt1
	if (@opt1_buf is NULL)
	begin
		select @opt1 = "%"
	end

        select @username = @opt1

        /* 
	** list all base keys in current database 
	*/ 
        if (@opt2 is null)
        begin 
	        
                create table #encr_basekeys_info(keyowner varchar(30) null,
                                     keyname varchar(255) null,
				     typeofpasswd varchar(30) null,
				     fullkeyname varchar(285) null)

 		/* run by SSO/key custodian/DBO */
		if ((@sso_role > 0) or (@keycustodian_role > 0)
			or (user_name() = "dbo"))
		begin               
                        insert #encr_basekeys_info(keyowner, keyname, typeofpasswd)
	        	     select user_name(o1.uid), o1.name 
				   , case
					when (e1.status & @login_password) > 0 then "Login Passwd"
                                	when (e1.status & @system_password) > 0 then "System Encr Passwd"
                                	when (e1.status & @user_password) > 0 then "User Passwd"
			  	   end					
		              from sysobjects o1, sysencryptkeys e1
		              where o1.id = e1.id
	                         and e1.type & @key_copy = 0
			         and user_name(o1.uid) like @username


	        	if not exists (select 1 from #encr_basekeys_info)
			begin
				/*
				** 19616, "There are no encryption keys for user 
				** name like '%1!'."
				*/
				raiserror 19616, @opt1
				return(1)
			end

		       /* update #encr_basekeys_info to fill fullkeyname column */
			update #encr_basekeys_info
			set fullkeyname = keyowner + "." + keyname
		        where fullkeyname is NULL

			/* display the base encryption keys */
			exec sp_autoformat @fulltabname = #encr_basekeys_info,
			@selectlist = "'Owner.Keyname' = fullkeyname, 'Type of Password' = typeofpasswd",
			@orderby = "order by fullkeyname"
		end	
		else
                /* run by a non-privileged user */
               	begin	

			/* 
			** a non-priviledged user is only allowed to 
			** check his own keys 
			*/
			if (user_name()  not like @username)
			begin
				/*
				** 19632. "You are not authorized to check keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19632, @opt1
				return(1)
			end
			insert #encr_basekeys_info(keyowner, keyname,
	        		typeofpasswd)
	        	     select user_name(o1.uid), o1.name 
				     , case
					 when (e1.status & @login_password) > 0 then "Login Passwd"
                                	 when (e1.status & @system_password) > 0 then "System Encr Passwd"
                                	 when (e1.status & @user_password) > 0 then "User Passwd"
			  	     end
		             from sysobjects o1, sysencryptkeys e1
		             where o1.id = e1.id
	                         and e1.type & @key_copy = 0
			         and user_name(o1.uid) like @username
                                 and user_name(o1.uid) = user_name()
                                 
	        	if not exists (select 1 from #encr_basekeys_info)
			begin
				/*
				** 19616, "There are no encryption keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19616, @callername
				return(1)
			end

		       /* update #encr_basekeys_info to fill fullkeyname column */
			update #encr_basekeys_info
			set fullkeyname = keyowner + "." + keyname
		        where fullkeyname is NULL

			/* display the base encryption keys */
			exec sp_autoformat @fulltabname = #encr_basekeys_info,
			@selectlist = "'Owner.Keyname' = fullkeyname, 'Type of Password' = typeofpasswd",
			@orderby = "order by fullkeyname"
		end
		drop table #encr_basekeys_info
	end
	/* 
	** SP_ENCRYPTION HELPUSER, USERNAME|WILDCARD, KEY_COPY 
	*/
	else if (@opt2 = "key_copy")
	begin
		/* Accumulate encryption key info in a temporary table */
		create table #encr_keycopies_info(keyowner varchar(30) null,
						keyname varchar(255) null,
						assignee varchar(30) null,
						typeofpasswd varchar(30) null,
						keyrecovery int null,
						fullkeyname varchar(285) null)

		/* run by SSO/key custodian/DBO */
		if ((@sso_role > 0) or (@keycustodian_role > 0)
			or (user_name() = "dbo"))
		begin
			insert #encr_keycopies_info(keyowner, keyname, assignee,
						typeofpasswd, keyrecovery)
				select user_name(o1.uid), o1.name, user_name(e1.uid) 
					, case  
						when (e1.status & @login_access) > 0 then "Login Access"
						when (e1.status & @login_password) > 0 then "Login Passwd"
						when (e1.status & @system_password) > 0 then "System Encr Passwd"
						when (e1.status & @user_password) > 0 then "User Passwd"
					end					
					, case (e1.type & @key_recovery)
						when 0 then 0
						else 1
					end
				from sysobjects o1, sysencryptkeys e1
				where o1.id = e1.id
	                  	and e1.type & @key_copy > 0
			  	and user_name(e1.uid) like @username
		
			if not exists (select 1 from #encr_keycopies_info)
			begin
				/*
				** 19616, "There are no encryption keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19616, @opt1
				return(1)
			end
		
			/* Update #encr_keycopies_info to fill fullkeyname column */
			update #encr_keycopies_info
			set fullkeyname = keyowner + "." + keyname
		        where fullkeyname is NULL

			/* Display the encryption key info */
			exec sp_autoformat @fulltabname = #encr_keycopies_info,
			@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee, 'Type of Password' = typeofpasswd, 'Key Recovery' = keyrecovery",
			@orderby = "order by assignee"
		end	
		/* Run by non-privileged users */
		else
		begin

			/* 
			** a non-priviledged user is only allowed to 
			** check his own keys 
			*/
			if (user_name()  not like @username)
			begin
				/*
				** 19632. "You are not authorized to check keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19632, @opt1
				return(1)
			end

			insert #encr_keycopies_info(keyowner, keyname, assignee,
						typeofpasswd, keyrecovery)
				select user_name(o1.uid), o1.name, user_name(e1.uid) 
					, case  
						when (e1.status & @login_access) > 0 then "Login Access"
						when (e1.status & @login_password) > 0 then "Login Passwd"
						when (e1.status & @system_password) > 0 then "System Encr Passwd"
						when (e1.status & @user_password) > 0 then "User Passwd"
					end					
					, case (e1.type & @key_recovery)
						when 0 then 0
						else 1
					end
				from sysobjects o1, sysencryptkeys e1
				where o1.id = e1.id
	                  	and e1.type & @key_copy > 0
			  	and user_name(e1.uid) like @username
				and user_name(e1.uid) like user_name()

			if not exists (select 1 from #encr_keycopies_info)
			begin
				/*
				** 19616, "There are no encryption keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19616, @callername
				return(1)
			end
		
			/* update #encr_keycopies_info to fill fullkeyname column */
			update #encr_keycopies_info
			set fullkeyname = keyowner + "." + keyname
		        where fullkeyname is NULL

			/* Display the encryption key info */
			exec sp_autoformat @fulltabname = #encr_keycopies_info,
			@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee, 'Type of Password' = typeofpasswd, 'Key Recovery' = keyrecovery",
			@orderby = "order by assignee"
	
		end	
		drop table #encr_keycopies_info
	end

	/*
        ** SP_ENCRYPTION HELPUSER, USERNAME|WILDCARD, LOGIN_PASSWD_CHECK
	*/
	else if (@opt2 = "login_passwd_check")
	begin
		/* Accumulate login passwd and login access keycopy info in a temporary table */
		create table #encr_loginpwdcheck_info(keyowner varchar(30) null,
						keyname varchar(255) null,
						assignee varchar(30) null,
						typeofpasswd varchar(30) null,
						fullkeyname varchar(285) null,
              					dateofupdate datetime null,
						consistent int null)                

		/* run by SSO/key custodian/DBO */
		if ((@sso_role > 0) or (@keycustodian_role > 0)
			or (user_name() = "dbo"))
		begin
			insert #encr_loginpwdcheck_info(keyowner, keyname, assignee,
						typeofpasswd,dateofupdate)
				select user_name(o1.uid), o1.name, user_name(e1.uid) 
					, case  
						when (e1.status & @login_access) > 0 then "Login Access"
						when (e1.status & @login_password) > 0 then "Login Passwd"
					end					
					, e1.pwdate	
				from sysobjects o1, sysencryptkeys e1
				where o1.id = e1.id
	                  	and e1.type & @key_copy > 0
				and (((e1.status & @login_access) > 0)
					or ((e1.status & @login_password) > 0))
			  	and user_name(e1.uid) like @username
		
			if not exists (select 1 from #encr_loginpwdcheck_info)
			begin
				/*
				** 19616, "There are no encryption keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19616, @opt1
				return(1)
			end
		
			/* Update #encr_loginpwdcheck_info to fill fullkeyname column */
			update #encr_loginpwdcheck_info
			set fullkeyname = keyowner + "." + keyname
		        where fullkeyname is NULL
			
			/* Update #encr_loginpwdcheck_info to fill consistent column */
			update #encr_loginpwdcheck_info
                        set consistent =
				case
                                       when (e.pwdate >= l.pwdate) then 1
                                       else 0
                                end                               
			from master..syslogins l, sysencryptkeys e, sysusers u, sysobjects o
                        where e.uid=u.uid
			and u.suid=l.suid
			and o.id=e.id
			and assignee=user_name(e.uid)
			and keyname=o.name
			
			/* Display the encryption key info */
			exec sp_autoformat @fulltabname = #encr_loginpwdcheck_info,
			@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee, 'Type of Password' = typeofpasswd, 'Last Updated' = dateofupdate, 'Synchronized with Password' = consistent",
			@orderby = "order by assignee"
		end	
		/* Run by non-privileged users */
		else
		begin

			/* 
			** a non-priviledged user is only allowed to 
			** check his own key copies 
			*/
			if (user_name()  not like @username)
			begin
				/*
				** 19632. "You are not authorized to check keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19632, @opt1
				return(1)
			end

			insert #encr_loginpwdcheck_info(keyowner, keyname, assignee,
						typeofpasswd, dateofupdate)
				select user_name(o1.uid), o1.name, user_name(e1.uid) 
					, case  
						when (e1.status & @login_access) > 0 then "Login Access"
						when (e1.status & @login_password) > 0 then "Login Passwd"
					end				
					, e1.pwdate	
				from sysobjects o1, sysencryptkeys e1
				where o1.id = e1.id
	                  	and e1.type & @key_copy > 0
				and (((e1.status & @login_access) > 0)
					or ((e1.status & @login_password) > 0))
			  	and user_name(e1.uid) like @username
				and user_name(e1.uid) like user_name()

			if not exists (select 1 from #encr_loginpwdcheck_info)
			begin
				/*	
				** 19616, "There are no encryption keys (key copies) 
				** for user name like '%1!'."
				*/
				raiserror 19616, @callername
				return(1)
			end
		
			/* Update #encr_loginpwdcheck_info to fill fullkeyname column */
			update #encr_loginpwdcheck_info
			set fullkeyname = keyowner + "." + keyname
		        where fullkeyname is NULL
			
			/* Update #encr_loginpwdcheck_info to fill consistent column */
			update #encr_loginpwdcheck_info
                        set consistent =
				case
                                       when (e.pwdate >= l.pwdate) then 1
                                       else 0
                                end                               
			from master..syslogins l, sysencryptkeys e, sysusers u, sysobjects o
                        where e.uid=u.uid
			and u.suid=l.suid
			and o.id=e.id
			and assignee=user_name(e.uid)
			and keyname=o.name
			
			/* Display the encryption key info */
			exec sp_autoformat @fulltabname = #encr_loginpwdcheck_info,
			@selectlist = "'Owner.Keyname' = fullkeyname, 'Assignee' = assignee, 'Type of Password' = typeofpasswd, 'Last Updated' = dateofupdate, 'Synchronized with Password' = consistent",
			@orderby = "order by assignee"
		end	
		drop table #encr_loginpwdcheck_info
	end
end

if (@retval != 1)
begin
	return(0)
end
else
begin
	print "sp_encryption Usage: sp_encryption command [, option1 [, option2]]"
	print "sp_encryption commands:"
	print "sp_encryption 'system_encr_passwd', 'newpasswd'[, 'oldpasswd']"
	print "sp_encryption 'help'[, 'keyname'[, 'display_cols']]"
	print "sp_encryption 'helpkey'[, 'keyname'[, 'display_cols']]"
	print "sp_encryption 'helpkey', 'system_encr_passwd' [, 'display_keys' | 'all_dbs']"
	print "sp_encryption 'helpcol'[, 'colname'][, 'display_keys']]"
	print "sp_encryption 'helpuser'[, 'username'][, 'key_copy', 'login_passwd_check']"
	print "sp_encryption 'verify_downgrade'[,'to_version']"
end

return (1)
go
exec sp_procxmode 'sp_encryption', 'anymode'
go
grant execute on sp_encryption to public
go
exec sp_procxmode 'sp_encryption', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_passwordpolicy')
begin
	drop procedure sp_passwordpolicy
end
go
print "Installing sp_passwordpolicy"
go

/*
** Messages for "sp_passwordpolicy" 
** 17231, "No login with the specified name exists."
** 17260, "Can't run %1! from within a transaction."
** 17925, "You entered an invalid option name. No change was made."
** 17932, "You entered an invalid value. No change was made."
** 18409, "The built-in function '%1!' failed. Please see the other messages printed along with this message."
** 19213, "Invalid argument or unsupported command: %1!."
** 19633, "Network password encryption keypair will be regenerated at %1!."
** 19844, "There is no password protected role like '%1!'."
*/

create procedure sp_passwordpolicy
	@cmd		varchar(30) = null,
	@opt1		varchar(30) = null,
	@opt2		int = null
as
declare	@optname	varchar(30),	/*
					** To store mapped name of the 
					** attribute in spt_values
					*/
	@retval		int,
	@opt2str	varchar(8),
        @count1         int,		/* Temperory variable 1 */
        @count2         int,		/* Temperory variable 2 */
        @result         varchar(5),
        @validation_step varchar(50),
        @validation_test varchar(65),
	@return_status  int,
	@nextregen	datetime,
	@log_for_rep		int,	/* Replication status of master db */
	@db_rep_level_all	int,	/* Replication constants.	   */	
	@db_rep_level_none	int,
	@db_rep_level_l1	int,
	@lt_rep_get_failed	int,
	@lt_rep_all		int,
	@lt_rep_l1		int,
        @entered_date   datetime,        /* Stores datetime specified for
                                         ** expiring stale login or role
                                         ** passwords
                                         */
	@allow_pwd_dwn_status	int,
	@msg			varchar(1024),
	@allow_pwd_dwn_dt 	smalldatetime,
	@allow_pwd_dwn_dt_int 	int
 
/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/

if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_passwordpolicy"
        return (1)
end
else
begin
        set chained off
end
set transaction isolation level 1

/*
**  Begin command processing.
*/

/* 
** Check for sso_role. The built-in proc_role() will audit
** the event.
*/
if (proc_role("sso_role") = 0)
begin
	return (1)
end

/* 
** Set the command text to lowercase so that we always compare it using
** the same case.
*/
select @cmd = lower(@cmd)

if (@cmd is null)
begin
        /* Display sp_passwordpolicy usage information */
        select @retval = 2
	goto usage
end
else
if (@cmd not in ('set', 'clear', 'list', 'validate password options',
                  'expire login passwords', 'expire role passwords',
                  'expire stale login passwords',
                  'expire stale role passwords', 'regenerate keypair',
		  'downgrade','prepare_downgrade')) 
begin

        /*
        ** 19213, "Invalid argument or unsupported command: %1!."
        */
        raiserror 19213, @cmd
        /* Display sp_passwordpolicy usage information */
        select @retval = 2
	goto usage 
end

/* Check if opt1 entered is valid */
if (@opt1 is null and (@cmd = 'set' or @cmd = 'expire stale login passwords'
                         or @cmd = 'expire stale role passwords'))
begin
	/*
	** 17932, "You entered an invalid value. No
	** change was made."
	*/
	raiserror 17932
	select @retval = 2
	goto usage
end

/* Lists the option values */
if (@cmd = 'list')
begin
	/*
	** Traditionally, the names stored in spt_values match some
	** internal name in ASE, where the maximum length is 28 to
	** account for quoted identifiers. In this case, spt_values
	** is used store option names that must match sysattributes
	** options with 255 chars names. The option 'systemwide password 
	** expiration' is 30 chars long, and it does not fit in spt_values,
	** and the name has been chaged to 'password expiration'.
	** The variable @opt1 stores the sysattributes option name,
	** while the variable @optname stores the mapped name in
	** spt_values.
	*/
	if (@opt1 = 'systemwide password expiration')
		select @optname = 'password expiration'
	else
			 select @optname = @opt1

	if ((@opt1 is not null)
		and not exists(select 1 from master.dbo.spt_values
		where (type in ('PC', 'PT', 'LG')) 
		and name = @optname))
	begin
		/*
		** 17925, "You entered an invalid option name.
		** No change was made."
		*/
		raiserror 17925
		select @retval = 2
		goto usage
	end
	if (@opt2 is not null)
	begin
		/*
		** 17932, "You entered an invalid value. No
		** change was made."
		*/
		raiserror 17932
		select @retval = 2
		goto usage
	end

	if (@opt1 = 'allow password downgrade')
	begin
		/*
		** when 'allow password downgrade' is set to 0,
		** date is recorded in syattributes.object column.
		** This column is of data type int.
		** To retrieve data from it in date format,
		** convert function is used.
		** Date is converted to binary first and then to date format, 
		** ASE does not support direct date -> int conversion.
		*/
		select @allow_pwd_dwn_status = int_value,
			@allow_pwd_dwn_dt_int = object from sysattributes
			where class = 31
		if (@allow_pwd_dwn_status = NULL)
		begin
			/*
	                ** 19679, New 15.0.2 master database.
        	        */
                	exec sp_getmessage 19679, @msg output
                	select 'value' = @allow_pwd_dwn_status,
                	@msg as message
		end
		else if (@allow_pwd_dwn_status = 1)
		begin
			/*
			** 19678, Password downgrade is allowed.
			*/	
			exec sp_getmessage 19678, @msg output
			select 'value' = @allow_pwd_dwn_status,
			@msg as message
		end
		else if (@allow_pwd_dwn_status = 0)
		begin
			select @allow_pwd_dwn_dt = 
				convert(smalldatetime, convert(binary(4), @allow_pwd_dwn_dt_int))
			/*
			** 19680, Last Password downgrade was allowed on
			*/
			exec sp_getmessage 19680, @msg output
			select 'value' = @allow_pwd_dwn_status,
				@msg + " " + convert(char(20), @allow_pwd_dwn_dt) as message
		end
	end
	else
	begin
		select 'Policy_option' = a.object_cinfo, 
		       'Curr_value' = a.int_value, 'Min_value' = s.low,
		       'Max_value' = s.high
		from master.dbo.spt_values s, master.dbo.sysattributes a,
			master.dbo.sysmessages m
		where (((s.name = a.object_cinfo) or
			(a.object_cinfo = 'systemwide password expiration' 
			and s.name = 'password expiration'))
			and (s.msgnum = m.error)
			and (s.type in ('PC', 'PT', 'LG'))
			and (a.object_cinfo = @opt1 or @opt1 is null))
	end
return 0
end

if (@cmd = 'regenerate keypair')
begin
	/* 
	** @opt2 is not passed to password_admin(),
	** hence check for null value here itself.
	*/
	if (@opt2 is not null)
	begin
		/*
                ** 17932, "You entered an invalid value. No
                ** change was made."
                */
                raiserror 17932
		select @retval = 2
		goto usage
	end

        select @retval = password_admin('set', 'regenerate keypair', @opt1)
	if @retval = 0
	begin
		/* Display the current date if none was specified, i.e. NOW. */
		if @opt1 = NULL
			select @nextregen = getdate()
		else
			select @nextregen = @@nextkpgendate
		/*
		** 19633, "Network password encryption keypair will be 
		** regenerated at %1!."
		*/
		raiserror 19633, @nextregen
	end
	return @retval
end

if (@cmd like '%downgrade')
begin
	select @retval = password_admin('set', @cmd)
	return @retval
end

if (@cmd = 'validate password options')
begin
	/* 
	** @opt1 and @opt2 are not passed to password_admin(),
	** hence check for null value here itself.
	*/
	if ((@opt1 is not null) or (@opt2 is not null))
	begin
		/*
                ** 17932, "You entered an invalid value. No
                ** change was made."
                */
                raiserror 17932
		select @retval = 2
		goto usage
	end

        select @retval = password_admin('set', 'policy', @cmd)
        select @count1 = 0
        select @count2 = 1
	select @return_status = 0

        /* 
	** create a temporary table to store the information of validation 
	** tests.
	*/
        create table #helpdisplay
        (
                validation_step varchar(50),
                result          varchar(5),
                validation_test varchar(65)
        )
	/*
	** Each validation test is represented by two bits. 
	** If odd bit of the corresponding two bits for the test is set to 1,
	** the result is NA.
	** If even bit is set to 1, then result is Pass
	** else if even bit is set to 0, then result is Fail.
	*/
        while(@count1 <= 10)
        begin
                if (@retval & power(2,@count1)) != 0
                        select @result = "NA"
                else if (@retval & power(2,@count2)) != 0
                        select @result = "Pass"
                else
		begin
                        select @result = "Fail"
			select @return_status = 1
		end

                if @count1 = 0
                begin
                        select @validation_step = "min alpha in password"
                        select @validation_test = "minalpha >= (minupper + minlower)"
                end
                else if @count1 = 2
                begin
                        select @validation_step = "minimum password length - 1"
                        select @validation_test = "minlength >= (mindigit + minspc + minalpha)"
                end
                else if @count1 = 4
                begin
                        select @validation_step = "minimum password length - 2"
                        select @validation_test = "minlength >= (mindigit + minspc + minupper + minlower)"
                end
                else if @count1 = 6
                begin
                        select @validation_step = "maximum password length - 1"
                        select @validation_test = "max password length >= (mindigit + minspc + minalpha)"
                end
                else if @count1 = 8
                begin
                        select @validation_step = "maximum password length - 2"
                        select @validation_test = "max password length >= (mindigit + minspc + minupper + minlower)"
                end
                else if @count1 = 10
                begin
                        select @validation_step = "password exp warn interval"
                        select @validation_test = "pwdexpwarn <= pwdexp"
                end

                insert into #helpdisplay values(@validation_step, @result, @validation_test)
                select @count1 = @count1 + 2
                select @count2 = @count2 + 2
        end
        exec sp_autoformat @fulltabname = #helpdisplay,
        @selectlist = "'Validation Step' = validation_step, 'Pass/Fail/NA' = result,
                       'Validation Test' = validation_test"
	drop table #helpdisplay
			       
	return @return_status		       
end

/* Initialize constants need for replication */
select  @db_rep_level_all = -1,
	@db_rep_level_none = 0,
	@db_rep_level_l1 = 1,
	@lt_rep_get_failed = -2,
	@lt_rep_all = 2048,
	@lt_rep_l1 = 4096 

if (@opt1 != 'allow password downgrade')
begin
	/* Get the replication status of the 'master' database */
	select @log_for_rep = getdbrepstat(1)
	
	if (@log_for_rep = @lt_rep_get_failed)
	begin
		/*
		** 18409, "The built-in function getdbrepstat() failed. Please
		** see the other messages printed along with this message."
		*/
		raiserror 18409, "getdbrepstat"
		return 1
	end

	/* Convert the replication status to boolean */
	if ((@log_for_rep & @lt_rep_all = @lt_rep_all) or
	    (@log_for_rep & @lt_rep_l1 = @lt_rep_l1))

		select @log_for_rep = 1
	else
		select @log_for_rep = 0

end
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (upper(db_name()) != upper("master"))
begin
	/*
	** 18388, "You must be in the master database in order to
	**	   run '%1!'"
	*/
	raiserror 18388, "sp_passwordpolicy"
	return (1)
end

/* 
** If replication is active, open the transaction.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** replication.
*/
if (@log_for_rep = 1)
begin
	begin tran rs_logexec
end

if (@cmd = 'expire login passwords')
begin
	/* 
	** @opt2 is not passed to password_admin(),
	** hence check for null value here itself.
	*/
	if (@opt2 is not null)
	begin
		/*
                ** 17932, "You entered an invalid value. No
                ** change was made."
                */
                raiserror 17932
		select @retval = 2
		goto usage
	end

        if(@opt1 is null)
        begin
                select @opt1 = '%'
        end
	
       	if not exists(select name from master.dbo.syslogins 
			where name like @opt1)
        begin
                /*
                ** 17231, "No login with the specified name exists."
                **      (was "Invalid Login user.")
                */
                raiserror 17231
		select @retval = 1
        end
	else
	begin
		select @retval = password_admin('set', 'policy', @cmd, @opt1)
	end
end
else if (@cmd = 'expire role passwords')
begin
	/* 
	** @opt2 is not passed to password_admin(),
	** hence check for null value here itself.
	*/
	if (@opt2 is not null)
	begin
		/*
                ** 17932, "You entered an invalid value. No
                ** change was made."
                */
                raiserror 17932
		select @retval = 2
		goto usage
	end

        if(@opt1 is null)
        begin
                select @opt1 = '%'
        end

        if not exists(select name from master.dbo.syssrvroles
                        where name like @opt1 and password is not null)
        begin
                /*
		** 19844, "There is no password protected role like '%1!'."
                */
		raiserror 19844, @opt1
		select @retval = 1
        end
	else
	begin
		select @retval = password_admin('set', 'policy', @cmd, @opt1)
	end
end
else if ( (@cmd = 'expire stale login passwords') or 
	  (@cmd = 'expire stale role passwords') )
begin
	/* 
	** @opt2 is not passed to password_admin(),
	** hence check for null value here itself.
	*/
	if (@opt2 is not null)
	begin
		/*
                ** 17932, "You entered an invalid value. No
                ** change was made."
                */
                raiserror 17932
		select @retval = 2
		goto usage
	end

	select @entered_date = @opt1
	
	/* 
	** Convert the entered date and time into required form 
	** of mm dd yy hh:mm:ss:zzzAM(PM) using style number 9
	*/
	select @opt1 = convert(char(30), @entered_date, 9)
	
        select @retval = password_admin('set', 'policy', @cmd, @opt1)
end
/* Changes or inserts the option value as specified. */
else if (@cmd = 'set')
begin
	select @opt2str = convert(varchar(8), @opt2)
	select @retval = password_admin(@cmd, 'policy', @opt1, @opt2str)
end
/* Changes the option values to hardcoded values */
else if (@cmd = 'clear')
begin
	/* 
	** @opt2 is not passed to password_admin(),
	** hence check for null value here itself.
	*/
	if (@opt2 is not null)
	begin
		/*
                ** 17932, "You entered an invalid value. No
                ** change was made."
                */
                raiserror 17932
		select @retval = 2
		goto usage
		
	end
	else if (@opt1 = 'allow password downgrade')
	begin
		/*
		** 19658, "Option 'allow password downgrade' cannot be 
		** unset using 'clear' command"
		*/
		raiserror 19658
		select @retval = 2
		goto usage
	end
	else
	begin
		select @retval = password_admin(@cmd, 'policy', @opt1)
	end
end

if (@retval = 0) 
begin
	/*
	** If the 'master' database is marked for replication, the T-SQL builtin
	** logexec(), will log the execution of this system procedure.
	*/
	if (@log_for_rep = 1) 
	begin
		if (logexec(1) != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure '%1!'
			** 	   in database '%2!' was aborted because there
			**	   was an error in writing the replication log
			**	   record."
			*/
			raiserror 17756, "sp_passwordpolicy", "master"
			goto cleanup
		end
	end
	commit transaction
	return 0
end

usage:
	if (@retval = 2)
	begin
		print "sp_ passwordpolicy Usage: sp_passwordpolicy command [, option1 [, option2]]"
	        print "sp_passwordpolicy commands:"
		print "sp_passwordpolicy 'set',"
		print "                  {'enable last login updates' | 'disallow simple passwords' |"
	        print "                   'min digits in password' | 'min alpha in password' |"
	        print "                   'min special char in password' | 'min upper char in password' |"
	        print "                   'min lower char in password' | 'password exp warn interval' |"
	        print "                   'systemwide password expiration' | 'minimum password length' |"
	        print "                   'maximum failed logins' | 'expire login' |"
	        print "                   'allow password downgrade'},"
	        print "                  'value'"
		print "sp_passwordpolicy 'list',"
		print "                  ['enable last login updates' | 'disallow simple passwords' |"
	        print "                   'min digits in password' | 'min alpha in password' |"
	        print "                   'min special char in password' | 'min upper char in password' |"
	        print "                   'min lower char in password' | 'password exp warn interval' |"
	        print "                   'systemwide password expiration' | 'minimum password length' |"
	        print "                   'maximum failed logins' | 'expire login' |"
		print "                   'allow password downgrade']"
		print "sp_passwordpolicy 'clear',"
		print "                  {'enable last login updates' | 'disallow simple passwords' |"
	        print "                   'min digits in password' | 'min alpha in password' |"
	        print "                   'min special char in password' | 'min upper char in password' |"
	        print "                   'min lower char in password' | 'password exp warn interval' |"
	        print "                   'systemwide password expiration' | 'minimum password length' |"
	        print "                   'maximum failed logins' | 'expire login'}"
		print "sp_passwordpolicy 'expire login passwords'[, '{loginame | wildcard}']"
		print "sp_passwordpolicy 'expire role passwords'[, '{rolename | wildcard}']"
		print "sp_passwordpolicy 'expire stale login passwords', 'datetime'"
		print "sp_passwordpolicy 'expire stale role passwords', 'datetime'"
		print "sp_passwordpolicy 'regenerate keypair'[, 'datetime']"
	        print "sp_passwordpolicy 'validate password options'"
	end

cleanup:
	if (@log_for_rep = 1)
		rollback tran rs_logexec
	return 1
go
exec sp_procxmode 'sp_passwordpolicy', 'anymode'
go
grant execute on sp_passwordpolicy to public
go
exec sp_procxmode 'sp_passwordpolicy', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_update_authmech_value')
begin
	drop procedure sp_update_authmech_value
end
go
print "Installing sp_update_authmech_value"
go


/*
** This stored procedure is used to update the syslogins.status from 224 or 
** 480 to 0 for logins upgraded from pre 12.5.4 to 12.5.4 or 15.0.2.
** Logins created on pre 12.5.4 code had the status equal to 224 which
** indicated 'ANY' authentication. 224 is formed by ASE, LDAP and PAM bits,
** viz. 32, 64, 128 respectively.
** From 12.5.4 onwards, KERBEROS was also included in this status. So,
** effectively, the value that would indicate 'ANY' became 32+64+128+256 = 480
** If now the ASE is upgraded to 12.5.4 or 15.0.2, the new ASE will compare
** it with 480 instead of 224 to check if the authentication is 'ANY'.
** In case of KERBEROS authentication, new ASE server was looking for status
** as 256 for KERBEROS logins, which lead to their failure. In order to avoid
** this, this procedure will update the status bits appropriately.
*/
/*
** Messages for update_authmech_value [Total 3]
** 17260, "Can't run %1! from within a transaction."
** 19882, "sp_update_authmech_value should not be executed on this release of Adaptive Server, no changes made."
** 19883, "Updated authentication mechanism for %1! row(s) on %2! server."
*/

create procedure sp_update_authmech_value
as
declare @ase_version            char(10),/* Indicate current ASE version */
        @HA_CERTIFIED           tinyint, /* Is the SP HA certified ? */
        @retstat                int,
        @auth_mask              int,     /* Authentication Mask */
        @auth_1253_all          int,     /* ASE, LDAP and PAM bit mask */
        @msg                    varchar(1024),
        @prisavedupdatecount    int     /* Number of rows updated on
                                         ** primary server
                                         */

select @HA_CERTIFIED = 0



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_update_authmech_value',
                        @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
        /* 17260, "Can't run %1! from within a transaction." */
        raiserror 17260, "sp_update_authmech_value"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1

/*
** Check for the version of ASE on which this procedure is getting executed.
** Procedure should be executed only on 12.5.4 or 15.0.2 servers where an
** update to status is required.
*/
if (((@@version_as_integer = 12500) AND (@@version_number < 12540)) OR
    ((@@version_as_integer = 15000) AND (@@version_number < 15020)) OR
     (@@version_as_integer < 12500))
begin
        /*
        ** 19882, "sp_update_authmech_value should not be executed on this
        ** release of Adaptive Server, no changes made."
        */
        raiserror 19882
        return (1)
end

/*
** Check if user has sso role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sso_role") = 0)
        return (1)



/* Obtain the authentication mask value from master.dbo.spt_values */
select @auth_mask = low from master.dbo.spt_values
        where type = 'ua' and name = 'AUTH_MASK'

/* Obtain bitmask for ASE, LDAP, PAM bits */
select @auth_1253_all = (select low from master.dbo.spt_values
                                where name = 'ASE') |
                        (select low from master.dbo.spt_values
                                where name = 'LDAP') |
                        (select low from master.dbo.spt_values
                                where name = 'PAM')

/*
** Update all the master.dbo.syslogins row to unset the authentication
** mechanism bits where the status has value of 224 i.e ASE, LDAP and PAM
** bits set which indicated 'ANY' authentication mechanism in pre 12.5.4
** versions.
*/
update master.dbo.syslogins set status = status & ~@auth_mask
        where ((status & @auth_1253_all) = @auth_1253_all)

select @prisavedupdatecount = @@rowcount


return (0)

clean_all:

        return (1)
go
exec sp_procxmode 'sp_update_authmech_value', 'anymode'
go
grant execute on sp_update_authmech_value to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg_config')
begin
	drop procedure sp_inst15015msg_config
end
go
print "Installing sp_inst15015msg_config"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg_us_mesg')
begin
	drop procedure sp_inst15015msg_us_mesg
end
go
print "Installing sp_inst15015msg_us_mesg"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg_addlimsg')
begin
	drop procedure sp_inst15015msg_addlimsg
end
go
print "Installing sp_inst15015msg_addlimsg"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg_oth_mesg')
begin
	drop procedure sp_inst15015msg_oth_mesg
end
go
print "Installing sp_inst15015msg_oth_mesg"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg_all_us_mesgs')
begin
	drop procedure sp_inst15015msg_all_us_mesgs
end
go
print "Installing sp_inst15015msg_all_us_mesgs"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg_all_oth_mesgs')
begin
	drop procedure sp_inst15015msg_all_oth_mesgs
end
go
print "Installing sp_inst15015msg_all_oth_mesgs"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_inst15015msg')
begin
	drop procedure sp_inst15015msg
end
go
print "Installing sp_inst15015msg"
go


/*
** Wrapper of instmsgs.ebf
*/

/*
** SP_INST15015MSG_CONFIG
**
** Description:
**      sproc to configure before install 15015 msgs.
**
*/
create procedure sp_inst15015msg_config
as
begin   -- {

	set nocount on
	dump tran master with truncate_only
	declare @size int
		select @size = (2048 - sum(size)) / 512
		from master.dbo.sysusages where dbid = 1

	if (@size = 1)
	begin
		alter database master on master = 1
	end
	else if (@size = 2)
	begin
		alter database master on master = 2
	end
	
	return

end     -- }
go

/*
** SP_INST15015MSG_US_MESG
**
** Description:
**	sproc to install English msgs.
**
** Parameter:
**      @error_number
**	@severity_number
**	@message_text
**
*/
create procedure sp_inst15015msg_us_mesg
	@error_number int,
	@severity_number int,
	@message_text varchar(255)
as
declare @retval int
declare @fmtbuf varchar(255)
set nocount on
select @retval = 0
select @retval = (select 1 
		     from master.dbo.sysmessages 
			where error = @error_number and langid is NULL
		  )
/* message is not available so insert it. */
if (@message_text IS NOT NULL)
	begin
	if (@retval = 1) 
		begin
		select @fmtbuf = (select "Modifying Message: " 
			+ convert(varchar(8),@error_number) + " Severity: " 
			+ convert(varchar(8),@severity_number))
		print @fmtbuf
		begin tran
		update master.dbo.sysmessages 
			set error=@error_number,
			severity=@severity_number,
			dlevel=2,	/* dlevel is always 2 */
			description=@message_text,
			langid=NULL	/* messages are shipped in English. */
			where langid is NULL and error=@error_number
		commit tran
		end
	else
		begin
		select @fmtbuf = "Adding Message: "
			+ convert(varchar(8),@error_number) + " Severity: "
			+ convert(varchar(8),@severity_number)
		print @fmtbuf
		begin tran
		insert master.dbo.sysmessages values (
			@error_number,
			@severity_number,
			2,		/* dlevel is always 2 */
			@message_text,
			NULL,
			NULL)		/* messages are shipped in English. */
		commit tran
		end
	end
go


/*
** SP_INST15015MSG_ADDLIMSG
**
** Description:
**	sproc to install non-English msgs.
**
** Parameter:
**      @error
**	@message
**	@langid
**	@debug
**
*/
create procedure sp_inst15015msg_addlimsg
		(
		@error		int,		/* Error being installed. */
		@message	varchar(255),	/* Text of new message.   */
		@langid		int,		/* Message's language ID. */
		@debug		bit = 0		/* Turned on for debug.   */
		)
as

/*	Variable declarations.		*/

declare	@oldseverity	int,		/* Old message severity.	*/
	@olddlevel	int, 		/* Old message dlevel.		*/
	@olddesc	varchar(255),	/* Old message text.		*/
	@engseverity	int,		/* English message severity.	*/
	@engdlevel	int,		/* English message dlevel.	*/
	@engdesc	varchar(255),	/* English message text.	*/
	@tstr		varchar(4),	/* Temporary string holder.	*/
	@strlength	int,		/* Temporary string length var.	*/
	@remaining	int,		/* Length of string remaining.	*/
	@cindex		int,		/* Temporary charindex holder.	*/
	@pindex		int,		/* Temporary parameter count.	*/
	@tindex		int,		/* Temporary copy of cindex.	*/
	@engcount	int,		/* English message param count.	*/
	@newcount	int,		/* New message param count.	*/
	@debugmsg	varchar(255),	/* Debug message string.	*/
	@maxparams	int		/* Maximum number of params.	*/

/*	Initialize variables that are used as #DEFINE type constants.	*/

select	@maxparams = 12		/* Maximum number of params in a msg.	*/
				/* this value comes from ex_print.c	*/
if @debug = 1
	begin
	select	@debugmsg = "Starting message "
		+ convert( varchar, @error )
		+ "."
	print @debugmsg
	end	/* IF DEBUG	*/

/*	Get the English message from sysmessages.	*/

select	@engseverity = severity, @engdlevel = dlevel,
	@engdesc = description
	from master.dbo.sysmessages
	where error = @error
	  and langid is NULL

if @debug = 1
	begin
	select	@debugmsg = "English message:  severity = "
		+ convert( varchar, @engseverity )
		+ ", dlevel = "
		+ convert( varchar, @engdlevel )
		+ ", description follows -- "
	print @debugmsg
	print @engdesc
	end	/* IF DEBUG	*/

/*
**	If there is no English message, and the stored procedure is not
**	being asked to delete the equivalent translated message, then
**	there is a problem; there should not be a translation when there
**	is no English equivalent!
*/

if @engseverity is NULL and @message != "delete"
	return 7	/* 7 = no English equivalent.	*/

/*	Get the old translated version of the message.	*/

select	@oldseverity = severity, @olddlevel = dlevel,
	@olddesc = description
	from master.dbo.sysmessages
	where error = @error
	  and langid = @langid

if @debug = 1
	begin
	select	@debugmsg = "Old message:  severity = "
		+ convert( varchar, @oldseverity )
		+ ", dlevel = "
		+ convert( varchar, @olddlevel )
		+ ", description follows -- "
	print @debugmsg
	print @olddesc
	end	/* IF DEBUG	*/

/*
**	Check to see if we are being asked to delete a message; if so,
**	we can skip all the rest of the processing and just perform the
**	delete.  If there is an English version of the message, then
**	indicate that we are (in essence) replacing the translated version
**	with an English one.  Also check to see if it is actually
**	necessary to perform the delete (i.e., if there is a message
**	to delete).
*/
/* =========================BEGIN add_LImsg3=============================*/

if @message =  "delete"
	begin

	if @oldseverity is NULL		/* No old version of msg.	*/
		return 3		/* 3 = already installed.	*/

	else	begin			/* Old version exists.		*/
		delete	from master.dbo.sysmessages
			where error = @error
			  and langid = @langid
		if @@error != 0
			return 10	/* 10 = delete failed.		*/
		if @engseverity is NULL
			return 4	/* 4 = message deleted.		*/
		else	return 5	/* 5 = message replaced by Eng.	*/
		end	/* ELSE	*/

	end	/* IF	*/

/*
**	Having reached this point, we know that we are going to insert
**	or update a message.  Therefore, we check to be sure that the
**	new message has the same number of parameters as the English
**	version, and that the parameters are numbered appropriately.
**	We don't check the order of the parameters, because word order
**	varies from one language to another.
*/

if @debug = 1
	print "Searching English message for parameters."

/*	Initialize variables, get parameter 1.		*/

select	@tstr = "%"
select	@cindex = charindex( @tstr, @engdesc ),
	@pindex = 0, @strlength = datalength( @engdesc )
	/* @pindex = 0, @strlength = datalength( @engdesc ) */

if @cindex = 0
	select	@remaining = 0
else	select	@remaining = @strlength - @cindex

/* =========================BEGIN add_LImsg4==============================*/

if @debug = 1
	begin
	select	@debugmsg = "Values:  CINDEX = "
		+ convert( varchar, @cindex )
		+ ", PINDEX = "
		+ convert( varchar, @pindex )
		+ ", STRLENGTH = "
		+ convert( varchar, @strlength )
		+ ", REMAINING = "
		+ convert( varchar, @remaining )
		+ "."
	print @debugmsg
	end	/* IF DEBUG	*/

/*
**	Keep getting parameters until there are no more.  We assume
**	that the English version has the correct number of parameters.
*/

while @cindex != 0
	begin

	if @cindex = @strlength	/* Single percent sign is last char.	*/
		return 14	/* 14 = Corrupted English message.	*/

	if "%" =		/* Look for escaped % characters (%%).	*/
		(
		select	substring( @engdesc, @cindex+1, 1 )
		)
		begin

		if @debug = 1
			begin
			select	@debugmsg = "Escaped percent sign string "
				+ "'%%' found at character "
				+ convert( varchar, @cindex )
				+ "."
			print @debugmsg
			end	/* IF DEBUG	*/


		select	@cindex = @cindex + 2,
			@remaining = ( @strlength - @cindex )

		if @cindex > @strlength
			break	/* '%%' at end of string, exit WHILE loop */

		select	@tindex = charindex( @tstr,
			substring( @engdesc, @cindex, @remaining+1 ) )

		if @tindex = 0
			select @cindex = 0		/* No more parameters.	*/
		else	
			/* Potential parameter found. */
			select @cindex = @cindex + @tindex - 1,
			@remaining = @strlength - @cindex

		if @debug = 1
			begin
			select	@debugmsg = "Values:  CINDEX = "
				+ convert( varchar, @cindex )
				+ ", PINDEX = "
				+ convert( varchar, @pindex )
				+ ", STRLENGTH = "
				+ convert( varchar, @strlength )
				+ ", REMAINING = "
				+ convert( varchar, @remaining )
				+ "."
			print @debugmsg
			end	/* IF DEBUG	*/

		continue	/* Return to beginning of WHILE loop.	*/

		end	/* IF	*/


/* =========================BEGIN add_LImsg5=============================*/

	if @debug = 1
		begin
		select	@debugmsg = "Parameter found at character "
			+ convert( varchar, @cindex )
			+ "."
		print @debugmsg
		end	/* IF DEBUG	*/

	/*	Found a valid parameter.	*/

	select	@pindex = @pindex + 1	/* Increment parameter count. */

	if @debug = 1
		begin
		select	@debugmsg = "Values:  CINDEX = "
			+ convert( varchar, @cindex )
			+ ", PINDEX = "
			+ convert( varchar, @pindex )
			+ ", STRLENGTH = "
			+ convert( varchar, @strlength )
			+ ", STRLENGTH remaining = "
			+ convert( varchar, @remaining )
			+ "."
		print @debugmsg
		end	/* IF DEBUG	*/

	/*	Continue searching from current string location on.	*/

	select	@tindex = @cindex + charindex( @tstr,
			substring( @engdesc, @cindex+1, @remaining ) )

	if @cindex = @tindex
		select @cindex = 0		/* No more parameters.	*/
	else	select @cindex = @tindex	/* Potential parameter found. */

	select	@remaining = @strlength - @cindex

	end	/* WHILE	*/

/*	Store the number of parameters.		*/

/* =========================BEGIN add_LImsg6==============================*/

select	@engcount = @pindex

if @debug = 1
	begin
	select	@debugmsg = "Number of parameters in English message was "
		+ convert( varchar, @engcount )
		+ "."
	print @debugmsg
	end	/* IF DEBUG	*/

/*
**	Now perform the same count on the new message to ensure that
**	it has the same number of parameters as the English equivalent.
**	Also, check that the new message does not skip any parameter
**	numbers.
*/

if @debug = 1
	print "Searching translated message for parameters."

/*	Ensure there is no zero-eth parameter.	*/

if 0 !=
	(
	select	charindex( "%0!", @message )
	)
	return 12	/* 12 = format error; parameter 0 found. */

select	@tstr = "%1!"

select	@cindex = charindex( @tstr, @message ),
	@pindex = 0, @tindex = 0, @strlength = datalength( @message )
	/* @pindex = 0, @tindex = 0, @strlength = datalength( @message ) */

/*=========================BEGIN add_LImsg7==================================*/

if @debug = 1
	begin
	select	@debugmsg = "Values:  CINDEX = "
		+ convert( varchar, @cindex )
		+ ", PINDEX = "
		+ convert( varchar, @pindex )
		+ ", STRLENGTH = "
		+ convert( varchar, @strlength )
		+ "."
	print @debugmsg
	end	/* IF DEBUG	*/

while @cindex != 0	/* Got one!	*/
	begin

	if @debug = 1
		begin
		select	@debugmsg = "Parameter '"
			+ @tstr
			+ "' found at character "
			+ convert( varchar, @cindex )
			+ "."
		print @debugmsg
		end	/* IF DEBUG	*/

	/*	Make sure that the parameter number appears only once.	*/

	if 0 !=
		(
		select	charindex( @tstr,
				substring( @message, @cindex+1,
				@strlength-@cindex ) )
		)
		return 13	/* 13 = format error; duplicate parameter. */

	select	@pindex = @pindex + 1	/* Increment number found.	*/
	select	@tstr = "%"
		+ convert( varchar, @pindex+1 )	/* Next one to look for. */
		+ "!"

	select	@cindex = charindex( @tstr, @message )	/* Search!	*/

/*=========================BEGIN add_LImsg8==================================*/

	if @debug = 1
		begin
		select	@debugmsg = "Values:  CINDEX = "
			+ convert( varchar, @cindex )
			+ ", PINDEX = "
			+ convert( varchar, @pindex )
			+ ", STRLENGTH = "
			+ convert( varchar, @strlength )
			+ "."
		print @debugmsg
		end	/* IF DEBUG	*/

	end	/* WHILE	*/

select	@newcount = @pindex

if @debug = 1
	begin
	select	@debugmsg = "Highest parameter number was "
		+ convert( varchar, @newcount )
		+ "."
	print	@debugmsg
	end	/* IF DEBUG	*/

select	@pindex = @pindex + 1	/* Skip over n+1 parameter.	*/

/*	Ensure that no parameter number was skipped.	*/

if @debug = 1
	print "Searching new message for skipped parameter numbers."

while ( @pindex < @maxparams )
	begin

	select	@pindex = @pindex + 1	/* Next number to look for.	*/
	select	@tstr = "%"
		+ convert( varchar, @pindex )
		+ "!"

/*=========================BEGIN add_LImsg9==================================*/

	select	@cindex = charindex( @tstr, @message )	/* Search!	*/

	if @debug = 1
		begin
		select	@debugmsg = "Values:  CINDEX = "
			+ convert( varchar, @cindex )
			+ ", PINDEX = "
			+ convert( varchar, @pindex )
			+ ", STRLENGTH = "
			+ convert( varchar, @strlength )
			+ "."
		print @debugmsg
		end	/* IF DEBUG	*/

	if @cindex != 0			/* Found a match.	*/
		return 11		/* 11 = message format error.	*/

	end	/* WHILE	*/

/*	Now see if the parameter counts match.		*/

if @engcount != @newcount
	return 6		/* 6 = format count mismatch.	*/

/*
**	Okay to proceed.  Now check to see if the new message is a
**	duplicate of the message it is supposed to replace.  We need
**	to check severity and dlevel as well as the message text,
**	because the upgrade may be to one of those values rather than
**	the string itself.
*/

if @oldseverity is not NULL
	and @olddesc = @message
	and @oldseverity = @engseverity
	and @olddlevel = @engdlevel
	return 3		/* 3 = message already installed.	*/

/*
**	If we are here, it is not a complete duplicate, so it must
**	either be a new message or a replacement message.
*/


/*=========================BEGIN add_LImsg10=================================*/

if @oldseverity is not NULL	/* Replacement message.	*/
	begin

	update	master.dbo.sysmessages
		set	severity = @engseverity,
			dlevel = @engdlevel,
			description = @message
		where	error = @error
		  and	langid = @langid

	if @@error != 0
		return 9	/* 9 = update failed.	*/

	return 2		/* 2 = message updated.	*/

	end

/*	If we are here, then it is a new message.	*/

insert	into master.dbo.sysmessages
		(
		error, severity, dlevel, langid, description
		)
	values	(
		@error, @engseverity, @engdlevel, @langid, @message
		)

if @@error != 0
	return 8		/* 8 = insert failed.	*/

return 1			/* 1 = message inserted.	*/ 
go

/*                      --------------------------------                      */
/* ====================        DONE WITH SQL TEXT        ==================== */
/* ==================== BEGIN ACTUAL CODE FOR new_msgs() ==================== */
/*                      --------------------------------                      */

/*
** SP_INST15015MSG_OTH_MESG
**
** Description:
**	sproc to install other msgs.
**
** Parameter:
**      @error
**	@message
**	@langname
**
**
*/
create procedure sp_inst15015msg_oth_mesg 
		(
		@error 		int,		/* Error being installed. */
		@message	varchar(255),	/* Text of new message. */
		@langname	varchar(255)	/* language name */
		)
as	

/* Variable declarations */
declare @retval	int	/* return value */
declare @msg varchar(255)
declare @langid int


set nocount on
select @retval = 0
select @langid = langid from master.dbo.syslanguages where name = @langname
if (@message = "delete")
begin
	select @langid = langid from master.dbo.syslanguages
	if @langid is NULL
	begin
		select @msg = "No languages installed"
		print @msg
		return 0
	end
end
else
begin
	select @langid = langid from master.dbo.syslanguages where name = @langname
	if @langid is NULL
	begin
		select @msg = convert(varchar(8),@langname) + " language is not installed"
		print @msg
		return 0
	end
end
exec @retval = sp_inst15015msg_addlimsg @error,@message,@langid

if @retval = 1
begin
	select @msg = "Added Message #" + convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 2
begin
	select @msg = "Updated Error #" + convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 3
begin
	select @msg = "Message #" + convert(varchar(6),@error) + " not found in database for delete for" + @langname + " language"
end
else if @retval = 4
begin
	select @msg = "Deleted localized versions of message #" + convert(varchar(6),@error)
end
else if @retval = 5
begin
	select @msg = "Deleted localized versions of message #" + convert(varchar(6),@error)
end
else if @retval = 6
begin	
	select @msg = "Format count of + @langname" + " message #" + convert(varchar(6),@error) + " does not match English message" 
end
else if @retval = 7
begin
	select @msg = "English Message Not found for + message #" + convert(varchar(6),@error)
end
else if @retval = 8
begin
	select @msg = "Insert failed for message #" + convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 9
begin
	select @msg = "Update failed for message #" + convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 10
begin
	select @msg = "Delete failed for message #" + convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 11
begin
	select @msg = "Skipped parameter number in message #"+convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 12
begin
	select @msg = "Illegal parameter 0 found in message #"+convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 13
begin
	select @msg = "Duplicate parameter found in message #"+convert(varchar(6),@error) + " for " + @langname + " language"
end
else if @retval = 14
begin
	select @msg = "English message is corrupted for message #"+convert(varchar(6),@error)
end
else
begin
	select @msg = "Bad return code"
end
print @msg
go
	
/*
** SP_INST15015MSG_ALL_US_MESGS
**
** Description:
**
*/
create procedure sp_inst15015msg_all_us_mesgs
as
begin   -- {

exec sp_inst15015msg_us_mesg 180, 15, "There are too many parameters in this CREATE PROCEDURE statement.  The maximum number is %d."

exec sp_inst15015msg_us_mesg 217, 16, "Maximum stored procedure nesting level exceeded (limit %d)."

exec sp_inst15015msg_us_mesg 280, 16, "Only TEXT, IMAGE and UNITEXT datatypes are valid with the TEXTPTR function."

exec sp_inst15015msg_us_mesg 540, 16, "Schema for table '%.*s' has changed since compilation of this query.  Please re-execute query."

exec sp_inst15015msg_us_mesg 713, 10, "Sort failed because there is insufficient procedure cache for the configured number of sort buffers. Please retry the query after configuring lesser number of sort buffers."

exec sp_inst15015msg_us_mesg 863, 20, "Buffer resources in cache %s, id %d are unavailable. Please re-run this query or ask the system administrator to re-configure buffer cache memory."

exec sp_inst15015msg_us_mesg 872, 20, "Process %d is trying to get a %s latch on buffer 0x%x (dbid: %d, pageno: %d) while already holding a %s latch on the buffer."

exec sp_inst15015msg_us_mesg 913, 11, "Could not find row in sysdatabases with database id %d and name '%.*s' accessed through stored procedure '%.*s'. Run DBCC CHECKTABLE on sysdatabases."

exec sp_inst15015msg_us_mesg 942, 20, "Database cannot be opened because a system descriptor cannot be installed."

exec sp_inst15015msg_us_mesg 952, 20, "Database '%.*s' cannot be opened because a system index descriptor cannot be installed."

exec sp_inst15015msg_us_mesg 1031, 16, "The optimizer will to complete the compilation of this query; the query will be executed normally."

exec sp_inst15015msg_us_mesg 1043, 16, "To experiment with the optimizer behavior, this AP can be modified and then passed to the optimizer using the PLAN clause: SELECT/INSERT/DELETE/UPDATE ... PLAN '( ... )"

exec sp_inst15015msg_us_mesg 1265, 20, "A lock manager routine expected a lock record as an argument but was passed something else. lr=0x%p, lrmagic=%c."

exec sp_inst15015msg_us_mesg 1548, 10, "The Create Index is done using %s"

exec sp_inst15015msg_us_mesg 1805, 10, "CREATE DATABASE: allocating %ld logical pages (%d.%d megabytes) on disk '%.*s' (%ld logical pages requested)."

exec sp_inst15015msg_us_mesg 1945, 16, "Cannot create unique index '%.*s' on table '%.*s'. The table partition condition and the specified index keys make it impossible to enforce index uniqueness across partitions."

exec sp_inst15015msg_us_mesg 2235, 16, "QUIESCE DATABASE Error: Database %.*s is already specified earlier in this command."

exec sp_inst15015msg_us_mesg 2525, 16, "Table Corrupt: Object id wrong; tables: alloc page %ld  extent id=%ld  l page#=%ld objid in ext=%ld (name = %S_OBJID) objid in page=%ld (name = %S_OBJID) objid in sysindexes=%ld (name = %S_OBJID)"

exec sp_inst15015msg_us_mesg 2592, 10, "%s index successfully restored for object '%.*s' in '%.*s' database."

exec sp_inst15015msg_us_mesg 2805, 20, "Bad pointer 0x%lx encountered while remapping stored procedure '%.*s'.  Must re-create procedure."

exec sp_inst15015msg_us_mesg 2811, 18, "Cannot create procedure dbid %d, objid %ld, with a group number of %d."

exec sp_inst15015msg_us_mesg 2813, 20, "Procedure %.*s in procedure buffer 0x%lx not properly linked with procedure header 0x%lx."

exec sp_inst15015msg_us_mesg 2814, 20, "Procedure %.*s in procedure buffer 0x%lx does not contain the same object id as procedure header 0x%lx."

exec sp_inst15015msg_us_mesg 2815, 20, "Procedure %.*s in procedure buffer 0x%lx contains page address 0x%lx which is not aligned on a 2K boundary."

exec sp_inst15015msg_us_mesg 2816, 20, "Procedure %.*s in procedure buffer 0x%lx contains page address 0x%lx which is not within any memory map."

exec sp_inst15015msg_us_mesg 2817, 20, "Procedure %.*s in procedure buffer 0x%lx contains page address 0x%lx which should be allocated."

exec sp_inst15015msg_us_mesg 2823, 20, "Process %d tried to remove a PROC_BUF 0x%lx named '%.*s' that it does not hold in the hold procedure linked list."

exec sp_inst15015msg_us_mesg 2824, 19, "Process %d cannot hold PROC_BUF 0x%lx named '%.*s' because it holds another PROC_BUF 0x%lx named '%.*s'.  A process can only hold one view, rule, or default at a time."

exec sp_inst15015msg_us_mesg 2825, 20, "Process %d tried to remove a PROC_BUF 0x%lx named '%.*s' that it does not hold."

exec sp_inst15015msg_us_mesg 2826, 20, "Process %d has held the PROC_BUF 0x%lx named '%.*s' in the hold procedure linked list already; Check your procedure cache."

exec sp_inst15015msg_us_mesg 2827, 20, "Procedure '%.*s' in procedure buffer 0x%lx is not properly hashed."

exec sp_inst15015msg_us_mesg 3019, 10, "Unable to write statistics for object %ld in database %ld. Please run update statistics on this table after loading this database or prior to accessing the table in the loaded database."

exec sp_inst15015msg_us_mesg 3020, 10, "Unable to write statistics for index %ld of object %ld in database %ld. Please run update statistics on this index after loading this database or prior to using this index in the loaded database."

exec sp_inst15015msg_us_mesg 3021, 10, "Unable to write statistics for all indexes of object %ld in database %ld. Please run update statistics on all indexes after loading this database or prior to using the indexes in the loaded database."

exec sp_inst15015msg_us_mesg 3121, 16, "Index %s.%s (objid=%ld, indid=%d) may be invalid. It uses CHAR or VARCHAR columns in its key and was created under a different sort order ID (%d) or charset ID (%d) than the ones on this server (SortOrd=%d, CharSet=%d)."

exec sp_inst15015msg_us_mesg 3123, 16, "The dump header contains an invalid dump type code: %ld.  This is not a valid transaction log dump or database dump."

exec sp_inst15015msg_us_mesg 3124, 10, "This is a %S_MSG dump of database ID %d, name '%.*s', from %S_DATE. ASE version: %.*s. Backup Server version: %.*s. Database page size is %ld."

exec sp_inst15015msg_us_mesg 3125, 10, "Database contains %ld pages; checkpoint RID=(%S_RID); next object ID=%ld; sort order ID=%d, status=%d; charset ID=%d."

exec sp_inst15015msg_us_mesg 3127, 10, "All dumped pages have been loaded. ASE is now clearing pages above page %ld, which were not present in the database just loaded."

exec sp_inst15015msg_us_mesg 3136, 10, "Database log version=%d; database upgrade version=%ld."

exec sp_inst15015msg_us_mesg 3146, 16, "Adaptive Server cannot load this database dump because the version in the dump is not compatible with the version in the database. Database: log version=%d, upgrade version=%d. Dump: log version=%d, upgrade version=%d."

exec sp_inst15015msg_us_mesg 3165, 16, "LOAD DATABASE across platform is not supported for this database dump version of ASE. Upgrade version of this dump is %ld."

exec sp_inst15015msg_us_mesg 3166, 10, "segmap: 0x%08lx lstart=%d vstart=[vpgdevno=%d vpvpn=%d] lsize=%d unrsvd=%d"

exec sp_inst15015msg_us_mesg 3214, 21, "%s: virtual page %ld does not belong to any valid disk device."

exec sp_inst15015msg_us_mesg 3216, 10, "Backup Server session id is:  %ld.  Use this value when executing the 'sp_volchanged' system stored procedure after fulfilling any volume change request from the Backup Server."

exec sp_inst15015msg_us_mesg 3221, 20, "Could not install a function required to create a %s; returned error code is %ld."

exec sp_inst15015msg_us_mesg 3222, 20, "Attempt to write a %S_MSG failed; returned error code is %ld."

exec sp_inst15015msg_us_mesg 3223, 20, "Attempt to read a %S_MSG failed; returned error code is %ld."

exec sp_inst15015msg_us_mesg 3225, 21, "I/O failed while attempting to clear pages starting at page %ld of disk number %ld."

exec sp_inst15015msg_us_mesg 3227, 10, "No large buffers were available, so pages are being cleared by writing each page separately. Please be patient; %ld pages are being written, which may take a substantial amount of time. (Rough estimate: %ld minutes.)"

exec sp_inst15015msg_us_mesg 3237, 20, "%s failed to find disk status entry for virtual page '%ld'."

exec sp_inst15015msg_us_mesg 3238, 20, "Internal I/O error on %S_MSG pysical device on virtual page number '%ld' while %s was remirroring loaded database."

exec sp_inst15015msg_us_mesg 3244, 20, "%s failed for database '%S_DBID' with an internal transaction logging system failure; returned error code is %ld."

exec sp_inst15015msg_us_mesg 3248, 16, "LOAD DATABASE / TRANSACTION failed because of page size incompatibility. The current page size is %ld, and the page size in the dump is %ld."

exec sp_inst15015msg_us_mesg 3250, 16, "The devices,'%s' and '%s', specified in the command should be different."

exec sp_inst15015msg_us_mesg 3305, 21, "Page %ld in database '%.*s' read in during LOAD TRANSACTION recovery was uninitialized."

exec sp_inst15015msg_us_mesg 3306, 21, "Process %d was expected to hold logical lock on page %ld instead of process %d."

exec sp_inst15015msg_us_mesg 3307, 21, "Process %d was expected to hold logical lock on page %ld in database %S_DBID for object %S_OBJID, index number %d."

exec sp_inst15015msg_us_mesg 3308, 21, "Page %ld was expected to have %s lock on it."

exec sp_inst15015msg_us_mesg 3309, 21, "While in backout, process %d was chosen as deadlock victim while waiting for a resource lock on page %ld."

exec sp_inst15015msg_us_mesg 3310, 21, "Cannot find log record with RID: (%ld, %d)."

exec sp_inst15015msg_us_mesg 3311, 22, "Space left (%d bytes) on page %ld is insufficient to move data of %d length."

exec sp_inst15015msg_us_mesg 3312, 22, "Free offset %d is invalid on page %ld. It must be within %d and %d."

exec sp_inst15015msg_us_mesg 3318, 21, "Failed to start a scan on syslogs, Error number %ld"

exec sp_inst15015msg_us_mesg 3403, 22, "During recovery initialization, page %ld was encountered. This page belongs to object %ld, not the log."

exec sp_inst15015msg_us_mesg 3412, 21, "Database %d, table %ld. Attempt to mark table as suspect.  Getnext SCAN_CLUST on sysobjects.objid failed."

exec sp_inst15015msg_us_mesg 3413, 21, "Database %d. Attempt to mark database as suspect failed.  Getnext NC scan on sysdatabases.dbid failed."

exec sp_inst15015msg_us_mesg 3424, 21, "No more room in transaction table for transaction (%ld, %d)."

exec sp_inst15015msg_us_mesg 3425, 21, "Transaction (%ld, %d) not found in transaction table."

exec sp_inst15015msg_us_mesg 3474, 21, "During redo the page timestamp value is less than old timestamp from log. Page #=%ld, object id = %ld, page timestamp=%04x %08lx. Log old timestamp=%04x %08lx. Log record marker = (%ld, %d)."

exec sp_inst15015msg_us_mesg 3478, 21, "During undo the page timestamp value is less than new timestamp from log. Page #=%ld, object id = %ld, page timestamp=%04x %08lx. Log new timestamp=%04x %08lx. Log record marker = (%ld, %d)."

exec sp_inst15015msg_us_mesg 3508, 10, "Attempt to set '%.*s' database to single user mode failed because the usage count is %ld. Make sure that no other users are currently using this database and rerun CHECKPOINT."

exec sp_inst15015msg_us_mesg 3513, 10, "Cannot set database '%.*s' in read-only mode because it has %ld active transaction(s). Verify that no transaction is using this database, then retry the command."

exec sp_inst15015msg_us_mesg 3612, 10, "Execution Time %ld."

exec sp_inst15015msg_us_mesg 3613, 10, "Parse and Compile Time %ld."

exec sp_inst15015msg_us_mesg 3614, 10, "Total writes for this command: %ld"

exec sp_inst15015msg_us_mesg 3615, 10, "Table: %.*s scan count %ld, logical reads: (regular=%ld apf=%ld total=%ld), physical reads: (regular=%ld apf=%ld total=%ld), apf IOs used=%ld"

exec sp_inst15015msg_us_mesg 3616, 22, "Non-leaf page %ld in table %ld, index %d is empty - please rebuild the index."

exec sp_inst15015msg_us_mesg 3625, 10, "Table: %.*s scan count %lu, logical reads: %lu, physical reads: %lu, estimated I/O cost: %lu."

exec sp_inst15015msg_us_mesg 3630, 10, "Total estimated I/O cost for statement %u (at line %u): %ld."

exec sp_inst15015msg_us_mesg 3650, 0, "Large buffers: configured %ld, maximum possible %ld, requested %ld, used %ld."

exec sp_inst15015msg_us_mesg 3663, 16, "Multiple tracing from the same session is not allowed."

exec sp_inst15015msg_us_mesg 3703, 11, "Cannot drop the %S_MSG with object-id %ld in database %d, because it doesn't exist in the system catalogs."

exec sp_inst15015msg_us_mesg 3741, 16, "Cannot drop object '%.*s' because it is tagged as partitioned (# of slices=%ld) although it shouldn't."

exec sp_inst15015msg_us_mesg 3904, 21, "Can't unsplit logical page %ld in %S_PTNINFO - both pages together contain more data than will fit on one page."

exec sp_inst15015msg_us_mesg 3905, 21, "Can't unsplit logical page %ld in %S_PTNINFO - row number %d is used on both pages."

exec sp_inst15015msg_us_mesg 3931, 16, "Transaction Manager API '%.*s' failed. It was invoked with a wrong transaction type '%ld'."

exec sp_inst15015msg_us_mesg 3941, 10, "The MSDTC Interface %s failed with error 0x%lx -- %s."

exec sp_inst15015msg_us_mesg 4205, 16, "Syslogs does not exist in its own segment in database '%S_DBID' with segmap '%ld' with logical start page number of '%ld'. You cannot use DUMP TRANSACTION in this case, use DUMP DATABASE instead."

exec sp_inst15015msg_us_mesg 4211, 23, "Couldn't complete DUMP TRANsaction WITH NO_TRUNCATE on database '%.*s', because the log pointer in sysdatabases (page number %ld) is not accurate."

exec sp_inst15015msg_us_mesg 4212, 16, "Page %ld in database '%.*s' cannot be used as a truncation page because the page belongs to object ID %ld and not to the log.  Choose another page."

exec sp_inst15015msg_us_mesg 4213, 16, "Page %ld in database '%.*s' cannot be used as a truncation page because the page is not allocated.  Choose another page."

exec sp_inst15015msg_us_mesg 4214, 16, "Cannot use page %ld in database '%.*s' as the trunc page because the LTM trunc state is not set to TRUNC_VALID.  Set LTM trunc state to TRUNC_VALID with DBCC SETTRUNC."

exec sp_inst15015msg_us_mesg 4215, 21, "%s failed in database %.*s:  %ld not first log page in serially allocated log extent or allocation page.  Should be:  %ld.  Previous log record in  scan:  %ld."

exec sp_inst15015msg_us_mesg 4216, 21, "%s failed in database %.*s:  unexpected end of log encountered on page %ld while scanning for page %ld."

exec sp_inst15015msg_us_mesg 4218, 21, "Failure during DUMP of database '%.*s':  serial log page allocation rules  broken.  Current page: %ld;  next page: %ld;  piece end: %ld;   end-of-scan: %ld."

exec sp_inst15015msg_us_mesg 4219, 21, "DUMP TRANsaction encountered an unexpected end to the log page chain. Last page in log as scanned:  %ld."

exec sp_inst15015msg_us_mesg 4222, 16, "DUMP TRANSACTION for database '%S_DBID' failed: log page (%ld) is on a data-only segment. This is probably due to an incomplete move of the log to a device separate from the data. Complete the log migration or contact the System Administrator."

exec sp_inst15015msg_us_mesg 4234, 21, "%s failed on database %.*s: Unable to get the secondary truncation page %ld."

exec sp_inst15015msg_us_mesg 4313, 20, "Recreate index failed for table %ld, index %d. The table has been left in an inconsistent state, and the index is missing, so LOAD TRANSACTION errors may result. Run DBCC CHECKTABLE on the table if LOAD TRANSACTION succeeds."

exec sp_inst15015msg_us_mesg 4314, 20, "Cannot find table %ld to recreate index %d."

exec sp_inst15015msg_us_mesg 4317, 21, "Could not read log page %ld for database '%*s'; the DBINFO structure for this database is invalid, or the page chain is corrupt.  Cannot proceed with LOAD TRANSACTION."

exec sp_inst15015msg_us_mesg 4318, 21, "Last log page 'next free byte' value is out of range: %ld; should be no greater than %ld."

exec sp_inst15015msg_us_mesg 4321, 16, "ASE can not load this transaction log dump because version information in the dump does not match information in the database. Database: log version=%d, upgrade version=%ld. Dump: log version=%d, upgrade version=%ld."

exec sp_inst15015msg_us_mesg 4322, 16, "ASE cannot load a dump of the master database that was dumped from an older version of ASE. The current master database upgrade version is %ld, the dump master database upgrade version is %ld."

exec sp_inst15015msg_us_mesg 4408, 19, "The query and the views in it exceed the limit of %d tables."

exec sp_inst15015msg_us_mesg 4430, 19, "The number of tables including the derived tables in the query exceeded the limit of %ld tables."

exec sp_inst15015msg_us_mesg 4905, 21, "ALTER TABLE failed because page %ld of the system catalog sysindexes in database '%.*s' is not in the cache."

exec sp_inst15015msg_us_mesg 4916, 16, "Cannot add new identity field to '%.*s' via alter table because the number of existing rows (%ld) exceeds the maximum value for the specified precision (%d)."

exec sp_inst15015msg_us_mesg 4942, 16, "ALTER TABLE '%.*s' failed. You cannot drop column '%.*s' which has a default bound to it. Unbind the default (object id '%ld') before dropping this column."

exec sp_inst15015msg_us_mesg 4943, 16, "Dropping a column which is a primary key is not allowed. Drop the constraint (object id '%ld') before dropping this column."

exec sp_inst15015msg_us_mesg 4944, 16, "Dropping a column which is a foreign key is not allowed. Drop the constraint (object id '%ld') before dropping this column."

exec sp_inst15015msg_us_mesg 4946, 16, "Dropping a column from a table which has a constraint associated with it is not allowed. Drop the constraint (object id '%ld') before dropping this column."

exec sp_inst15015msg_us_mesg 4974, 21, "Process %d was expected to hold logical lock on object %ld."

exec sp_inst15015msg_us_mesg 5005, 10, "Extending database by %ld pages (%d.%d megabytes) on disk %.*s"

exec sp_inst15015msg_us_mesg 5115, 16, "I/O error during disk initialization. PHYSNAME '%.*s' may be incorrect or %ld (VSTART + SIZE) may exceed the size of the device. Please consult the ASE error log for more details."

exec sp_inst15015msg_us_mesg 5120, 10, "Bad segment map (%d) in sysusages for row with Dbid = %d, Logical Start = 0x%lx, Virtual Start = 0x%lx, and Size = 0x%lx.  Recommend you patch this value with correct information after Disk Refit completes."

exec sp_inst15015msg_us_mesg 5135, 10, "Starting Dynamic Mirroring of %ld pages for logical device '%.*s'."

exec sp_inst15015msg_us_mesg 5143, 10, "The remaining %ld pages are currently unallocated and will be mirrored as they are allocated."

exec sp_inst15015msg_us_mesg 5146, 16, "The VDEVNO of %ld is out of range.  The maximum VDEVNO allowed is %ld."

exec sp_inst15015msg_us_mesg 5147, 10, "Device size set to %ld blocks."

exec sp_inst15015msg_us_mesg 5164, 10, "Initializing %ld pages only; insufficient disk space."

exec sp_inst15015msg_us_mesg 5839, 16, "The value of 'max network packet size', '%ld', must be greater than or equal to the value of the 'default network packet size', '%ld'."

exec sp_inst15015msg_us_mesg 5840, 16, "Illegal value (%ld) specified for the number of large extents."

exec sp_inst15015msg_us_mesg 5843, 16, "Invalid Configuration: Cache alignment '%ld' is invalid.  Alignment must be a power of 2 greater than or equal to 2048.  Retry the command with a legal value."

exec sp_inst15015msg_us_mesg 5846, 16, "Illegal value '%ld' specified for configuration option '%s'. The legal values are between '%ld' and '%ld'."

exec sp_inst15015msg_us_mesg 5848, 16, "Warning: Unknown parameter '%s' found on line '%ld' of configuration file '%s'. This parameter is ignored. Edit the configuration file to remove or correct this parameter."

exec sp_inst15015msg_us_mesg 5853, 16, "'%s' has been modified from '%ld' to '%ld' by the verification routine."

exec sp_inst15015msg_us_mesg 5858, 10, "The configuration option '%s' has been changed by '%s' from '%ld' to '%ld'."

exec sp_inst15015msg_us_mesg 5861, 16, "The current 'max memory' value '%ld', is not sufficient to change the parameter '%s' to '%ld'. 'max memory' should be greater than 'total logical memory' '%ld' required for the configuration."

exec sp_inst15015msg_us_mesg 5881, 16, "The value of 'default network packet size', '%ld', must be less than or equal to the value of the 'max network packet size', '%ld'."

exec sp_inst15015msg_us_mesg 5883, 0, "The value of 'number of locks', '%ld', is not enough to configure 'user connections' to '%ld'. 'number of locks' should be at least twice the value of 'user connections'."

exec sp_inst15015msg_us_mesg 5887, 16, "Configuration Error: Duplicate Named Cache '%s' found around line '%ld' in the configuration file."

exec sp_inst15015msg_us_mesg 5899, 16, "The value of the 'max memory' parameter (%ld) defined in the configuration file is not high enough to set the other parameter values specified in the configuration file."

exec sp_inst15015msg_us_mesg 6008, 10, "Unable to write statistics for object %ld in database %ld. Please run update statistics on this table after boot-up or prior to accessing the table next time."

exec sp_inst15015msg_us_mesg 6009,10, "Unable to write statistics for all objects in database %ld. Please run update statistics on all objects in this database after boot-up or after loading this database."

exec sp_inst15015msg_us_mesg 6010,10, "Unable to write statistics for index %ld of object %ld in database %ld. Please run update statistics on this index after boot-up or prior to using this index."

exec sp_inst15015msg_us_mesg 6011,10, "Unable to write statistics for all indexes of object %ld in database %ld. Please run update statistics on all indexes after boot-up or prior to using the indexes next."

exec sp_inst15015msg_us_mesg 6229,10, "Cursor name '%.*s' is declared at nesting level '%ld'."

exec sp_inst15015msg_us_mesg 6234,10, "There have been %ld rows read, %ld rows updated and %ld rows deleted through this cursor."

exec sp_inst15015msg_us_mesg 6239,10, "The number of rows returned for each FETCH is %ld."

exec sp_inst15015msg_us_mesg 6253,10, "This cursor is declared on a stored procedure. It is using %ld bytes of memory.  The procedure's plan (%ld bytes) will be returned to the procedure cache when the cursor is closed."

exec sp_inst15015msg_us_mesg 6254,10, "This cursor is using %ld bytes of memory."

exec sp_inst15015msg_us_mesg 6255,10, "The cursor id is %ld."

exec sp_inst15015msg_us_mesg 6271,10, "The cursor was compiled at isolation level %ld."

exec sp_inst15015msg_us_mesg 6701,16, "Could not open dbid %d, object %ld."

exec sp_inst15015msg_us_mesg 6702,20, "Protection hash chain corrupt: element of type UNUSED found in hash chain (dbid %d, object %ld, protection type %d, protection status %d, column map %ld)"

exec sp_inst15015msg_us_mesg 6902,21, "Page timestamp value falls between the old and new timestamps from log. Page #=%ld, object id = %ld, page timestamp=%04x %08lx. Log: old timestamp=%04x %08lx, new timestamp=%04x %08lx. Log record marker = (%ld, %d)."

exec sp_inst15015msg_us_mesg 6908,21, "During redo the page timestamp value is less than old timestamp from log. Page #=%ld, object id = %ld, page timestamp=%04x %08lx. Log old timestamp=%04x %08lx."

exec sp_inst15015msg_us_mesg 7112,16, "Deadlock occurred while trying to lock page %ld, which is held by process %d."

exec sp_inst15015msg_us_mesg 7114,22, "Page %ld is not a valid text page."

exec sp_inst15015msg_us_mesg 7120,22, "Log record %ld:%d was not found in the LOG."

exec sp_inst15015msg_us_mesg 7121,22, "Free offset %d is invalid on page %ld."

exec sp_inst15015msg_us_mesg 7123,16, "Invalid text pointer value %s."

exec sp_inst15015msg_us_mesg 7124,16, "The offset and length specified in the READTEXT command is greater than the actual data length of %ld."

exec sp_inst15015msg_us_mesg 7125,16, "Text pointer value %s conflicts with the column name specified."

exec sp_inst15015msg_us_mesg 7126,16, "Text pointer value %s references a data page with an invalid text status."

exec sp_inst15015msg_us_mesg 7127,16, "Text pointer value %s references a data page with an invalid time stamp."

exec sp_inst15015msg_us_mesg 7128,16, "Text pointer value %s references a data page which is no longer allocated."

exec sp_inst15015msg_us_mesg 7134,16, "The text table and the table referenced by the text pointer value %s disagree."

exec sp_inst15015msg_us_mesg 7137,20, "Textptr Write Failed: An error occured while attempting to write TEXT/IMAGE/UNITEXT replication information for database %.*s, table %.*s, column %.*s. Please contact Sybase Technical Support for assistance. ( page %ld, datapage %ld, datarow %d )"

exec sp_inst15015msg_us_mesg 7155,22, "The st-node page linkage appears to be broken or corrupt. The command 'dbcc rebuild_text (%ld, %d, %ld)' can be executed to repair the st-node. (objid=%ld, colid=%d, FTP=%ld)."

exec sp_inst15015msg_us_mesg 7156,16, "Cannot read text value starting on page %ld because it has a different character set than is currently installed. This row needs to be re-inserted to convert it to the current character set. (CSID from tipsa %d, current CSID %d)."

exec sp_inst15015msg_us_mesg 7164,16, "Text/Image Replication Failure: An index for replication is missing for column ID = %d, table %s, in database %s. Run DBCC REINDEX to fix this error."

exec sp_inst15015msg_us_mesg 7165,16, "Text/Image Replication Failure: Table %s, column ID = %d, datarow for textpointer %s is missing. Run DBCC REINDEX to fix this error."

exec sp_inst15015msg_us_mesg 7401,10, "Could not allocate memory for the threshold task's argument list; threshold task cannot be spawned for database %d, segment %d, free space %ld."

exec sp_inst15015msg_us_mesg 7402,10, "Could not spawn the threshold handler procedure for database %d, segment %d, when only %ld free pages were left in the segment."

exec sp_inst15015msg_us_mesg 7403,10, "Threshold task could not use database %d, and so cannot execute the threshold procedure for segment %d, free space %ld."

exec sp_inst15015msg_us_mesg 7404,10, "Could not find row in systhresholds for database %.*s describing segment %d, free space %ld."

exec sp_inst15015msg_us_mesg 7405,10, "Threshold procedure name is missing from the systhresholds row in database %.*s for segment %d, free space %ld."

exec sp_inst15015msg_us_mesg 7407,10, "Failed to execute the threshold procedure for database %d, segment %d, free space %ld."

exec sp_inst15015msg_us_mesg 7414,10, "Threshold procedure '%.*s' returned an error indication (@status=%d) when called for database '%.*s', segment '%.*s', free_space %ld."

exec sp_inst15015msg_us_mesg 7717,20, "Attempted to drop temporary table with object id %ld, which is not in the temporary object lists for this task."

exec sp_inst15015msg_us_mesg 7735,16, "The specfied row count '%ld' for the cursor '%.*s' is invalid. The rowcount should always be greater than zero."

exec sp_inst15015msg_us_mesg 7736,20, "Unable to find lock request for tabid %ld dbid %d.  This is an internal error."

exec sp_inst15015msg_us_mesg 7743,16, "An explicit value for the identity field in table '%.*s' can only be specified in an insert statement when a field list is used."

exec sp_inst15015msg_us_mesg 7757,16, "The order-by position number '%ld' is out of range of the number of items in the select-list."

exec sp_inst15015msg_us_mesg 7777,16, "Changing certification state of object %S_OBJID, database %S_DBID to SUSPECT because of change in state of dependent object %.*s (previous object id %ld), database %S_DBID."

exec sp_inst15015msg_us_mesg 7783,10, "Internal error -- server failed to do garbage collection on this procedure, id = %ld.  Please save the query tree and procedure text and inform the technical support.  This is not a critical error, so server continues processing."

exec sp_inst15015msg_us_mesg 7791,16, "Unable to remap lockid for table %.*s in database %S_DBID. Printing diagnostic information: tobjp: 0x%lx, lkr: 0x%lx, rgtabid: %ld."

exec sp_inst15015msg_us_mesg 7905,10, "The number of rows in sysindexes for this table was %ld.  It has been corrected to %ld."

exec sp_inst15015msg_us_mesg 7906,10, "The number of data pages in sysindexes for this table was %ld.  It has been corrected to %ld."

exec sp_inst15015msg_us_mesg 7907,16, "The status in the first page (%ld) of the no_log table %.*s and the status in the sysobjects row, do not match."

exec sp_inst15015msg_us_mesg 7910,16, "Page %ld allocated 	(Alloc page: %ld Extent ID: %ld Alloc mask: 0x%x)"

exec sp_inst15015msg_us_mesg 7911,16, "Page %ld deallocated 	(Alloc page: %ld Extent ID: %ld Alloc mask: 0x%x)"

exec sp_inst15015msg_us_mesg 7912,16, "EXTID:%ld (Alloc page: %ld) is initialized.  Extent follows:"

exec sp_inst15015msg_us_mesg 7913,16, "PTNID=%d SPARE=%d OBJID=%ld RESERVE=0x%x FORWARD=0x%x ALLOC=0x%x DEALLOC=0x%x INDID=%d STATUS=0x%x"

exec sp_inst15015msg_us_mesg 7914,10, "Allocation page %ld extid %ld is not referenced, but there are referenced pages within this extent.  Contact Technical Support for assistance on object %ld."

exec sp_inst15015msg_us_mesg 7915,10, "Allocation page %ld extid %ld is referenced, but there are no referenced pages within this extent.  Contact Technical Support for assistnace on object %ld."

exec sp_inst15015msg_us_mesg 7916,10, "Total (# alloc pages = %ld, # of alloc pages modified = %ld)."

exec sp_inst15015msg_us_mesg 7917,16, "Total (# pages allocated=%ld pages deallocated=%ld extents deleted=%ld)."

exec sp_inst15015msg_us_mesg 7918,16, "Alloc page %ld (pgs allocated=%ld pgs deallocated=%ld extents deleted=%ld)."

exec sp_inst15015msg_us_mesg 7920,16, "Processed %ld entries in the sysindexes for dbid %d."

exec sp_inst15015msg_us_mesg 7921,16, "Found %ld bad entries in the sysindexes."

exec sp_inst15015msg_us_mesg 7923,16, "TABLE: %.*s		OBJID = %ld"

exec sp_inst15015msg_us_mesg 7924,16, "PARTITION ID=%ld FIRST=%ld ROOT=%ld SORT=%d"

exec sp_inst15015msg_us_mesg 7925,16, "Indid : %d, partition : %d. %ld Index pages allocated and %ld Extents allocated."

exec sp_inst15015msg_us_mesg 7926,16, "Data level: indid %d, partition %d. %ld Data pages allocated and %ld Extents allocated."

exec sp_inst15015msg_us_mesg 7927,16, "TOTAL # of extents = %ld"

exec sp_inst15015msg_us_mesg 7928,16, "Index %.*s is not consistent; found %d leaf rows but %ld data rows. Drop and recreate the index."

exec sp_inst15015msg_us_mesg 7938,16, "Table Corrupt: The oam entry for object %ld, indid %ld, alloc pg %ld, has a used count of %d and an unused count of %d.  The used count should be %d and the unused count should be %d."

exec sp_inst15015msg_us_mesg 7939,16, "Table Corrupt: The entry is missing from the OAM for object id %ld indid %d partition %ld for allocation page %ld."

exec sp_inst15015msg_us_mesg 7948,16, "Page %ld, object %ld, partition %ld, index %d, level %d, was found with fixed-row status improperly set. That status has been cleared by DBCC."

exec sp_inst15015msg_us_mesg 7949,16, "The number of pages used and unused for object %ld index %d partition %ld on allocation page %ld do not match the counts in the OAM entry. Actual used/unsed counts: [%d, %d]. Used/unused counts in OAM entry: [%d, %d]."

exec sp_inst15015msg_us_mesg 7953,10, "Unable to acquire an exclusive lock on text page %ld. This text value has not been recalculated.  In order to recalculate those TEXT pages you must release the lock and reissue the DBCC FIX_TEXT command."

exec sp_inst15015msg_us_mesg 7967,20, "Allocation page %ld in database %d does not hold the address lock required for initializing the diagnostic bitmaps or correcting its allocation errors."

exec sp_inst15015msg_us_mesg 7969,10, "Allocation reports cannot be generated for object %ld in database %d."

exec sp_inst15015msg_us_mesg 7972,10, "The oam counts for objid %ld indid %d are corrected."

exec sp_inst15015msg_us_mesg 7977,16, "First page %ld and Root page %ld are not same."

exec sp_inst15015msg_us_mesg 7978,20, "One or more text chain(s) for object %ld in database %ld is corrupt."

exec sp_inst15015msg_us_mesg 7979,16, "Text chain linkage corrupted for Page %ld of Object %ld."

exec sp_inst15015msg_us_mesg 7980,16, "Unreferenced text chain found for page %ld, nextpage %ld, prevpage %ld."

exec sp_inst15015msg_us_mesg 7989,16, "The serial allocation flag was found to be improperly set in allocation unit %ld, at extent ID %ld, with alloc map = %d and objid = %ld.  This flag has been cleared by DBCC."

exec sp_inst15015msg_us_mesg 8005,15, "Received a procedure name length of %ld. The TDS datastream is incorrect."

exec sp_inst15015msg_us_mesg 8015,10, "Adaptive Server has truncated parameter number %d passesd to rpc '%.*s' on server '%.*s'. The remote server does not support character or binary data wider than 255 bytes."

exec sp_inst15015msg_us_mesg 8201,26, "Keep count of descriptor (objid=%ld, dbid=%d) was expected to be %d. Instead %d was found."

exec sp_inst15015msg_us_mesg 8211,26, "Mismatch found between the name and id descriptor hash table for table '%.*s', objid = %ld. Descriptor hashed by name = 0x%0x and hashed by id = 0x%0x."

exec sp_inst15015msg_us_mesg 8215,14, "An attempt was made to drop the DES of object %ld, which is not a user-defined object."

exec sp_inst15015msg_us_mesg 8401,21, "Object with id of %ld was not found in database number %d."

exec sp_inst15015msg_us_mesg 8402,21, "Index row for object %ld (index id %d) was not found in database %d."

exec sp_inst15015msg_us_mesg 8415,21, "Unexpected value '%d' returned from lock manager after waiting for lock on page %ld, dbid %d."

exec sp_inst15015msg_us_mesg 8438,21, "Updating wrong indexrow in dbid %d. Objid for actual row updated is %ld, objid for intended row was %ld. Index id for intended row was %d. Index page is %ld, field updated is %d. Index row address is %0x, row number is %d."

exec sp_inst15015msg_us_mesg 8608,18, "pss=0x%lx has been marked sick. pss->p3stat=0x%lx pss->pspid=%d pss->pkspid=%d pss->pmasterxact=0x%lx. There might be open xdes/sdes associated with the pss. Please report this problem to Sybase Tech. Support."

exec sp_inst15015msg_us_mesg 8701,26, "Sitebuf has invalid state or keepcount. sitebuf=0x%lx, state=%d, keepcount=%ld."

exec sp_inst15015msg_us_mesg 8702,26, "Sitebuf has invalid state. sitebuf=0x%lx, state=%d."

exec sp_inst15015msg_us_mesg 8703,26, "Invalid keep count in sitebuf. sitebuf=0x%lx, keepcount=%ld."

exec sp_inst15015msg_us_mesg 8704,26, "Could not get the address lock. address=0x%lx, status=%d."

exec sp_inst15015msg_us_mesg 8706,26, "Invalid keep count in sitebuf. sitebuf=0x%lx, keepcount=%ld, lcfreed=%d."

exec sp_inst15015msg_us_mesg 8801,26, "Logconn has invalid state or keepcount. logconn=0x%lx, state=%d, keepcount=%d."

exec sp_inst15015msg_us_mesg 8802,26, "Logconn has invalid state. logconn=0x%lx, state=%d."

exec sp_inst15015msg_us_mesg 8806,26, "Corrupted pre-read data list in lc__flush. logconn=0x%lx, dtbeg=0x%lx, dtend=0x%lx."

exec sp_inst15015msg_us_mesg 8901,26, "Databuf has invalid state. databuf=0x%lx, state=%ld."

exec sp_inst15015msg_us_mesg 8902,26, "Logconn has invalid state or keepcount. logconn=0x%lx, state=%d, keepcount=%d."

exec sp_inst15015msg_us_mesg 8903,26, "Invalid state in logconn. logconn=0x%lx, state=%d."

exec sp_inst15015msg_us_mesg 8904,26, "Invalid state in databuf or corrupted databuf chain.  databuf=0x%lx, state=%ld, dnext=0x%lx."

exec sp_inst15015msg_us_mesg 9004,20, "I/O error detected on disk buffer 0x%X for page request %ld, dbid %d."

exec sp_inst15015msg_us_mesg 9142,16, "Usage: DBCC REPLICATE_TXTCOL (objid, colid, { always_replicate | replicate_if_changed | do_not_replicate } )"

exec sp_inst15015msg_us_mesg 9147,16, "Replication Not Enabled: Replication on table %.*s in database %.*s, has not been enabled yet. Run sp_setreplicate or sp_setrepcol before calling DBCC REPLICATE_TXTCOL, the DBCC REPLICATE_TXTCOL command is not executed. (objid %ld)"

exec sp_inst15015msg_us_mesg 9211,20, "%S_REPAGNT: Received the following error message from the Replication Server: Msg %ld. %.*s."

exec sp_inst15015msg_us_mesg 9283,20, "%S_REPAGNT: Aborting because a cross database stored procedure execution was detected. This event needs to be manually applied, and skipped before restarting the RepAgent. (sproc dbid %d, sproc objid %ld, current marker (%d, %d))"

exec sp_inst15015msg_us_mesg 9513,18, "The builtin function 'syb_sendmsg' failed to send the message '%.*s' to the destination address '%.*s' due to a failure to bind the socket to a local port number %ld provided by using dbcc tune. Please report this error to your Systems Administrator."

exec sp_inst15015msg_us_mesg 9817,16, "Invalid object ID %ld. Valid user object ID is a positive integer."

exec sp_inst15015msg_us_mesg 9819,11, "Object ID %ld does not exist in database `%.*s'."

exec sp_inst15015msg_us_mesg 9820,11, "Partition number %d for object ID %ld in database `%.*s' does not exist."

exec sp_inst15015msg_us_mesg 9904,10, "Total (# of text chains = %ld  text pages = %ld) in this table."

exec sp_inst15015msg_us_mesg 9905,10, "Processed %ld tables. Found %ld good text entries, %ld bad text entries in this database"

exec sp_inst15015msg_us_mesg 9911,10, "Object %ld has one row in Syspartitions"

exec sp_inst15015msg_us_mesg 9912,10, "Object %ld has partition %ld instead of %ld in Syspartitions"

exec sp_inst15015msg_us_mesg 9922,16, "The first page %ld in sysindexes for table '%.*s' does not match with first page %ld for the table's first partition in Syspartitions."

exec sp_inst15015msg_us_mesg 9923,16, "The first page %ld in syspartitions for partition %ld of table '%.*s' has previous page # %ld in its page header. The previous page # should be NULL."

exec sp_inst15015msg_us_mesg 9924,16, "The last page %ld in syspartitions for partition %ld of table '%.*s' has next page # %ld in its page header. The next page # should be NULL."

exec sp_inst15015msg_us_mesg 9931,22, "The %S_MSG page (%ld) found in the page chain does not match with the %S_MSG page (%ld) found in the slice control page (%ld), for table '%.*s', on slice %ld. The table may be corrupt."

exec sp_inst15015msg_us_mesg 9935,10, "ASE will not refresh index descriptor as the object descriptor for objid %ld in dbid %d is not installed in cache."

exec sp_inst15015msg_us_mesg 9936,20, "Error while trying to refresh sysindexes row within index descriptor with indid %d objid %ld and dbid %d."

exec sp_inst15015msg_us_mesg 9996,16, "Keys of index id %d for table '%.*s' in %S_MSG not in proper order. Drop and recreate the index. (index page %ld)"

exec sp_inst15015msg_us_mesg 9997,16, "Root page %ld in index id %ld of object id %ld does not have BT_ROOT bit set"

exec sp_inst15015msg_us_mesg 9998,16, "Index page %ld has object id %ld which is different from object id %ld"

exec sp_inst15015msg_us_mesg 9999,16, "Rids not in ascending order in index page %ld for row %ld at offset %ld (indid %ld, object %ld). Drop and recreate the index."

exec sp_inst15015msg_us_mesg 10218,10, "        Executed in parallel by coordinating process and %ld worker processes."

exec sp_inst15015msg_us_mesg 10219,10, "        Executed in parallel by %ld worker processes."

exec sp_inst15015msg_us_mesg 10220,10, "%s  Executed in parallel with a %ld-way partition scan."

exec sp_inst15015msg_us_mesg 10221,10, "    Executed in parallel by coordinating process and %ld worker processes."

exec sp_inst15015msg_us_mesg 10225,10, "Auxiliary scan descriptors required: %ld"

exec sp_inst15015msg_us_mesg 10231,10, "The current batch id '%lu' does not match the specified batch id '%ld'. Specify just the spid value to obtain the current batch id."

exec sp_inst15015msg_us_mesg 10232,10, "The current context id '%ld' does not match the specified context id '%ld'. Specify just the spid value to obtain the current context id."

exec sp_inst15015msg_us_mesg 10236,10, "        Executed by %ld worker processes."

exec sp_inst15015msg_us_mesg 10237,10, "%s  Executed in parallel with a %ld-way hash scan."

exec sp_inst15015msg_us_mesg 10257,10, "        Executing a newly cached statement."

exec sp_inst15015msg_us_mesg 10258,10, "        Executing a previously cached statement."

exec sp_inst15015msg_us_mesg 10355,16, "Changing certification state of object %S_OBJID, database %S_DBID to SUSPECT because of change in state of dependent object %.*s (previous object id %ld), database %S_DBID."

exec sp_inst15015msg_us_mesg 10472,10, "systemwide password expiration is the number of days that passwords remain in effect after they are changed. The default is 0 (passwords do not expire)."

exec sp_inst15015msg_us_mesg 10697,10, "maximum failed logins is the number of _consecutive_ failed login attempts permitted before the targeted login is locked. It is set to zero after every successful login."

exec sp_inst15015msg_us_mesg 10698,10, "minimum password length is the minimum number of characters a password must have to be accepted for any new logins. Logins that were set up using the previously set minimum password length can continue having fewer characters for their passwords."
exec sp_inst15015msg_us_mesg 10762,16, "Cannot initialize the Java Virtual Machine because the Java class library ($SYBASE/$SYBASE_ASE/lib/runtime.zip) is either missing, corrupted, or incompatible with the current server release. Contact your System Administrator for help."

exec sp_inst15015msg_us_mesg 10818,10, "Warning: the value provided for 'parallel_degree' ('%ld') was less than the value of 'scan_parallel_degree' ('%ld'). The value of 'scan_parallel_degree' has been adjusted to '%ld'."

exec sp_inst15015msg_us_mesg 10819,10, "The value of 'scan_parallel_degree' ('%ld') cannot be larger than the value of 'scan_parallel_degree' set by a calling procedure. The value '%ld' is used."

exec sp_inst15015msg_us_mesg 10823,16, "The specified memory, '%ldK', is not big enough to configure the configuration parameter, '%s', to a valid value."

exec sp_inst15015msg_us_mesg 10824,16, "Illegal value '%s' specified for configuration option '%s'. The legal values are between '%ld' and '%ld'."

exec sp_inst15015msg_us_mesg 10825,16, "Configuration parameter, '%s', will consume more than %ld bytes of memory if configured at %ld."

exec sp_inst15015msg_us_mesg 10826,16, "The value of the 'max memory' parameter '%ld' is not high enough to set the other parameter values for the current ASE configuration."

exec sp_inst15015msg_us_mesg 10841,16, "The value of parameter 'max memory' '%ld' cannot be less than the 'total logical memory' size '%ld'. Please reconfigure 'max memory' to be greater than or equal to the total logical memory required."

exec sp_inst15015msg_us_mesg 10846,16, "Overflow error: 'total logical memory' '%d' (2k pages) exceeds the maximum size of memory available on a '%d' bit platform: '%lu' bytes. Please reduce the configuration values that are consuming large amounts of memory."

exec sp_inst15015msg_us_mesg 10864,16, "Unable to create cache (%.*s) online. There is insufficient heap memory to allocate %ld bytes. To create a cache online, increase configuration parameter 'heap memory per user' or try the command when there is less activity on the system."

exec sp_inst15015msg_us_mesg 10879,16, "The current 'max memory' value '%ld', is not sufficient to change the size of cache '%.*s' to '%.*s' (%d KB). 'max memory' should be greater than 'total logical memory' '%ld' required for the configuration."

exec sp_inst15015msg_us_mesg 11001,10, "Row count exceeded limit of %ld."

exec sp_inst15015msg_us_mesg 11002,10, "Estimated IO cost exceeded limit of %ld."

exec sp_inst15015msg_us_mesg 11003,10, "Actual IO cost exceeded limit of %ld."

exec sp_inst15015msg_us_mesg 11004,10, "Query batch running time exceeded limit of %ld."

exec sp_inst15015msg_us_mesg 11005,10, "Transaction's running time exceeded limit of %ld."

exec sp_inst15015msg_us_mesg 11031,16, "Execution of %S_MSG %.*s failed because of errors parsing the source text in syscomments during upgrade. Please drop and recreate %.*s."

exec sp_inst15015msg_us_mesg 11056,16, "Exceeded tempdb space limit of %ld pages."

exec sp_inst15015msg_us_mesg 11080,16, "The definition tree (object id: %ld) of computed column '%.*s' is missing."

exec sp_inst15015msg_us_mesg 11236,16, "Update or 'complex INSERT' of non-NULL TEXT/IMAGE data is unsupported by server '%.*s'. Use WRITETEXT instead."

exec sp_inst15015msg_us_mesg 11238,16, "Complex INSERT of TEXT/IMAGE data is not supported. Use WRITETEXT instead."

exec sp_inst15015msg_us_mesg 11249,10, "....... Executing Partial Query Remotely"

exec sp_inst15015msg_us_mesg 11250,10, "....... EXISTS TABLE: Executing Query Remotely"

exec sp_inst15015msg_us_mesg 11265,10, "....... Executing Query Remotely"

exec sp_inst15015msg_us_mesg 11284,16, "The target of a 'select into existing table' statement must be a proxy table."

exec sp_inst15015msg_us_mesg 11294,16, "The remote server ('%.*s') class %d is not supported by UPDATE STATISTICS in import mode."

exec sp_inst15015msg_us_mesg 11718,16, "%ld is not a valid partition number. Partition number must be greater than 0."

exec sp_inst15015msg_us_mesg 11719,16, "Error converting %ld to IDENTITY_START value."

exec sp_inst15015msg_us_mesg 12034,17, "Collection of monitoring data for table '%.*s' failed due to insufficient memory. Retry when there is less load, or fewer users, on the server. %lu rows were not returned because %lu bytes of memory could not be allocated."

exec sp_inst15015msg_us_mesg 12203,18, "Lock cache entry not found for spid %d, lock 0x%lx, type %d, suff class %d. Please notify your system administrator."

exec sp_inst15015msg_us_mesg 12205,17, "Could not acquire a lock within the specified wait period. %s level wait period=%d seconds, spid=%d, lock type=%s, dbid=%d, objid=%ld, pageno=%ld, rowno=%ld. Aborting the transaction."

exec sp_inst15015msg_us_mesg 12207,10, "Could not acquire a lock within the specified wait period. %s level wait period=%d seconds, spid=%d, lock type=%s, dbid=%d, objid=%ld, pageno=%ld, rowno=%ld."

exec sp_inst15015msg_us_mesg 12307,26, "Row %d of Page %ld in table '%.*s' (id = %ld) in dbid %d is not locked."

exec sp_inst15015msg_us_mesg 12308,21, "Internal error : Invalid row id (Row %d, Page %ld) encountered in the table '%.*s' in the database '%.*s'."

exec sp_inst15015msg_us_mesg 12309,21, "Expanding update on object '%.*s' in database '%.*s' cannot succeed on page %ld, because the contiguous_free_bytes of %d is less than the difference of %d between new rowlen and old rowlen. This is an internal error."

exec sp_inst15015msg_us_mesg 12310,21, "Internal error: split or shrink propagation failed to commit after changing the page %ld of index id %d of table '%S_OBJID' (id = %ld) in database '%S_DBID'. Xactid is (%ld,%d). Drop and re-create the index."

exec sp_inst15015msg_us_mesg 12311,20, "Internal error: address lock request on page %ld of index id %d of table '%S_OBJID' (id = %ld) in database '%S_DBID' failed with status %d. No need to drop the index."

exec sp_inst15015msg_us_mesg 12312,20, "Index with id %d of table '%S_OBJID' (id = %ld) in database '%S_DBID' is already at the maximum allowed height. It cannot grow any further. Try dropping and recreating the index."

exec sp_inst15015msg_us_mesg 12313,21, "Internal error: Insert into page id %ld of index id %d of table '%S_OBJID' (id = %ld) in database '%S_DBID' tried to replace undeleted RID (%ld,%d) at slot %d and ridposn %d. Try dropping and recreating the index."

exec sp_inst15015msg_us_mesg 12314,21, "Bad child page pointer found on page %ld of index with id %d of table '%.*s' in database '%.*s'. Expected child page pointer to be %ld but found %ld. Check if the index is consistant using DBCC."

exec sp_inst15015msg_us_mesg 12315,21, "Corrupt page, Internal error: Mismatch between tail timestamp '%04x' and the low two bytes of timestamp in the page header '%04x' while accessing page '%ld' of object '%ld' in database '%d'. Please contact Sybase Technical Support."

exec sp_inst15015msg_us_mesg 12317,20, "Internal error: Insert of a key of size %ld into page %ld of index id %d of table '%S_OBJID' (id = %ld) in database '%S_DBID' failed because page has freespace of size %ld. Try again or drop and recreate the index."

exec sp_inst15015msg_us_mesg 12318,20, "Fatal internal error ecountered during scan on the index with id %d on table '%.*s' in database '%.*s'. Isolation level is %d. Scan status is %ld. Current index scan page is %ld. Please contact Sybase Technical Support."

exec sp_inst15015msg_us_mesg 12321,20, "Internal error: No split point found for page %ld of index %d of object %ld. Old page : %d entries, free space = %d. Split point information : <(%d), (%d), (%d, %d, %d)>."

exec sp_inst15015msg_us_mesg 12323,20, "Internal error occured during rebuild of index id %d of table '%S_OBJID' (id = %ld) in database '%S_DBID' while processing page %ld. Run dbcc checktable to see if the index is consistent."

exec sp_inst15015msg_us_mesg 12326,21, "Table Corrupt: Free offset in page header is not reasonable; free offset should be >= %d and <= %d; check this page and offset (page#=%ld freeoffset on the page header=%ld)."

exec sp_inst15015msg_us_mesg 12327,16, "Could not find index partition for index '%d' associated with data partition '%d' of object '%ld' in database dbid '%d'."

exec sp_inst15015msg_us_mesg 12328,21, "The calculated row offset '%d' of an index key on page '%ld' for object '%ld' in database '%d' is out of bounds (table offset on page = '%d', page status = '%d', local offset table address = 0x%lx)."

exec sp_inst15015msg_us_mesg 12332,16, "Table id %ld contains suspect partitions. This table is only available for read-only purposes until the REORG REBUILD or Repartition (ALTER TABLE PARTITION BY) command has been run on the indicated table to repair the partitions."

exec sp_inst15015msg_us_mesg 12334,21, "Attempts to read logical page '%ld', virtpage '%ld' from virtual device '%d' for %S_PTNINFO failed due to read failure in prefetch. Please contact Sybase Technical Support."

exec sp_inst15015msg_us_mesg 12504,10, "Timestamp mismatch error was not generated on page because page is marked for deallocation. Page #=%ld, object id = %ld, page timestamp=%04x %08lx. Log old timestamp=%04x %08lx."

exec sp_inst15015msg_us_mesg 12505,18, "could not open table '%ld' in database '%d' by id"

exec sp_inst15015msg_us_mesg 12506,18, "sysstatistics upgrade error in table '%.*s' index '%.*s' distribution page %ld - bad page format - run update statistics on this table after upgrade"

exec sp_inst15015msg_us_mesg 12507,18, "sysstatistics upgrade error in table '%.*s' index '%.*s' distribution page %ld - nulls not a beginning of page - run update statistics on this table after upgrade"

exec sp_inst15015msg_us_mesg 12508,18, "sysstatistics upgrade error in table '%.*s' index '%.*s' distribution page %ld - values not in ascending order - run update statistics on this table after upgrade"

exec sp_inst15015msg_us_mesg 12519,18, "sysstatistics upgrade error in table '%.*s' index '%.*s' distribution page %ld - exception occurred - run update statistics on this table after upgrade"

exec sp_inst15015msg_us_mesg 12531,16, "Cannot recover from log record %s at %S_RID affecting page %ld in '%S_DBID'. Reapply the log records using an earlier (pre-12.0) version of Adaptive Server, or contact Sybase Technical Support for assistance."

exec sp_inst15015msg_us_mesg 12540,10, "Modified timestamp on page %ld of (%d, %d) which falls between log old ts (%d, %d) and log new ts (%d, %d) during recovery of database id %d."

exec sp_inst15015msg_us_mesg 12541,10, "Modified timestamp on page %ld of (%d,%d) which is older than log old ts (%d, %d) during recovery of database id %d."

exec sp_inst15015msg_us_mesg 12546,18, "During undo the timestamp to be assigned to a page is less than the current page timestamp. Page = %ld, object id = %ld, page timestamp = (%04x %08lx), new page timestamp = (%04x %08lx)."

exec sp_inst15015msg_us_mesg 12586,10, "Database '%.*s', checkpoint=(%ld, %d), first=(%ld, %d), last=(%ld, %d)."

exec sp_inst15015msg_us_mesg 12717,10, "Suspect data encountered: Database '%.*s', object '%.*s', index ID '%ld', page ID '%ld'."

exec sp_inst15015msg_us_mesg 12718,10, "Suspect data encountered: Database: '%.*s', Page: '%ld' (object information not available)."

exec sp_inst15015msg_us_mesg 12721,10, "Suspect Granularity: Page '%ld' of database '%.*s' was made accessible to all users from previous state '%.*s'."

exec sp_inst15015msg_us_mesg 12722,10, "Suspect Granularity: The access state of page '%ld' of database '%.*s' was changed from '%.*s' to '%.*s'."

exec sp_inst15015msg_us_mesg 12723,10, "Suspect Granularity: Object '%ld' with index '%ld' of database '%.*s' was made accessible to all users from previous state '%.*s'."

exec sp_inst15015msg_us_mesg 12724,10, "Suspect Granularity: The access state of object '%ld' with index '%d' of database '%.*s' was changed from '%.*s' to '%.*s'."

exec sp_inst15015msg_us_mesg 12732,18, "Recovery (Suspect Granularity): Unable to mark suspect object '%ld'.Inform your System Administrator."

exec sp_inst15015msg_us_mesg 12736,10, "Recovery (Suspect Granularity): Allocation page %ld is corrupted."

exec sp_inst15015msg_us_mesg 12747,10, "Recovery (Suspect Granularity): Suspect page encountered: database '%.*s', page '%ld', session (%ld, %d), log row ID (%ld, %d)."

exec sp_inst15015msg_us_mesg 12748,10, "Recovery (Suspect Granularity): Suspect object in database '%.*s', object '%.*s', index '%ld'."

exec sp_inst15015msg_us_mesg 12761,10, "Recovery (Suspect Granularity): Page '%ld' of database '%.*s' is removed from suspect page list because it was unallocated at end of recovery due to page/extent deallocation. This page is clean and no action is required."

exec sp_inst15015msg_us_mesg 12767,10, "Suspect data encountered:  Database: '%.*s', Object: '%ld'"

exec sp_inst15015msg_us_mesg 12768,10, "Suspect Granularity: (for Testing only) Simulated error to create suspect pages. Objid: '%ld', Indid: '%ld', Errtype: '%d', Logtype: '%d', Pagetype: '%d', PageNo: '%ld', Simulation Type: '%.*s'."

exec sp_inst15015msg_us_mesg 12770,10, "Suspect index encountered: database '%.*s', object '%.*s', index '%ld'."

exec sp_inst15015msg_us_mesg 12802,16, "Invalid partition number %ld. Valid partition number is a positive integer."

exec sp_inst15015msg_us_mesg 12827,16, "Warning: command 'addcert' adds certificate path %s with its common name field different from server name or from the common name set in the directory service entry."

exec sp_inst15015msg_us_mesg 12829,16, "Warning: command 'addcert' adds certificate path '%s' that is not yet valid. Error '%s'."

exec sp_inst15015msg_us_mesg 12830,16, "Warning: command 'addcert' adds certificate path '%s' that has expired. Error %s."

exec sp_inst15015msg_us_mesg 12844,10, "The value of 'repartition_degree' (`%ld') cannot be larger than the value of configuration parameter 'max repartition degree' (`%ld'). The value '%ld' is used for 'repartition_degree'."

exec sp_inst15015msg_us_mesg 12845,10, "The value of 'resource_granularity' (`%ld') cannot be larger than the value of configuration parameter 'max resource granularity' (`%ld'). The value '%ld' is used for 'resource_granularity'."

exec sp_inst15015msg_us_mesg 12856,16, "Incorrect UPDATE STATISTICS calibration percentage '%ld' requested. Enter a value between '0' and '100'."

exec sp_inst15015msg_us_mesg 12905,16, "Index %ld of object %ld corrupt; key values in child page %ld inconsistent for parent page %ld. Drop and recreate the index."

exec sp_inst15015msg_us_mesg 12906,16, "Index %ld of object %ld has wrong level %d for page %ld, parent %ld is at level %d"

exec sp_inst15015msg_us_mesg 12908,16, "Index %ld of object %ld has orphan leaf page %ld. Drop and recreate the index."

exec sp_inst15015msg_us_mesg 12909,16, "Table with object id=%ld (name = %S_OBJID) inconsistent after Large Scale Allocation. %ld pages in extent %ld were found reserved."

exec sp_inst15015msg_us_mesg 12910,16, "Page %ld in extent %ld in Table with object id %ld (name = %S_OBJID) and index %ld is in the process of being allocated. To verify if the page is indeed allocated, run TABLEALLOC with the FIX option when there are no active transactions."

exec sp_inst15015msg_us_mesg 12931,10, "The total number of empty pages (with all deleted rows) in this table is %ld."

exec sp_inst15015msg_us_mesg 12932,10, "The total number of pages which could be garbage collected to free up some space is %ld."

exec sp_inst15015msg_us_mesg 12934,16, "Page %ld of object %ld, indid %ld undergoing change. Some pages of indid %ld may not be checked, retry the command later."

exec sp_inst15015msg_us_mesg 12936,10, "Failed to (re)build the st-node. Please issue the command 'dbcc rebuild_text (%ld, %d, %ld)' to (re)build the st-node. (objid=%ld, colid=%d, FTP=%ld)."

exec sp_inst15015msg_us_mesg 12946,10, "%ld allocation pages have been corrected to match database ID %d."

exec sp_inst15015msg_us_mesg 12947,16, "Syslogs free space is currently %ld pages but DBCC counted %ld pages. This descrepancy may be spurious if this count was done in multi-user mode. Please run DBCC TABLEALLOC(syslogs, full, fix) to correct it."

exec sp_inst15015msg_us_mesg 12948,10, "Syslogs free space count has been successfully recalculated. It has been corrected to %ld pages."

exec sp_inst15015msg_us_mesg 12956,10, "The reserved status was found to be improperly set in %ld pages. That status has been cleared by DBCC."

exec sp_inst15015msg_us_mesg 12959,10, "The segmap field was found to be improperly set in %ld allocation page(s) and it has been fixed by DBCC."

exec sp_inst15015msg_us_mesg 12974,16, "engine %d has outstanding ct-lib/java/messaging connections and cannot be offlined"

exec sp_inst15015msg_us_mesg 12981,16, "Error while trying to refresh syspartitions row within partition descriptor with dbid %d objid %ld indid %d and partition id %ld."

exec sp_inst15015msg_us_mesg 12999,16, "Partition id '%ld' is not found in dbid '%d'."

exec sp_inst15015msg_us_mesg 13152,10, "--Adaptive Server has expanded all '*' elements in the following statement"

exec sp_inst15015msg_us_mesg 13900,10, "Warning: a default (object id %ld) is defined on column '%.*s' being modified. Check the validity of the default value after this ALTER TABLE operation."

exec sp_inst15015msg_us_mesg 14123,21, "Updating wrong ptnrow in dbid %d. Objid for actual row updated is %ld, objid for intended row was %ld. Partition id for intended row was %d. Partition page is %ld, field updated is %d. Partition row address is %0x, row number is %d."

exec sp_inst15015msg_us_mesg 14124,20, "The to be installed PDES existed already. Dbid %d, objid %ld, partition id %ld, state %d."

exec sp_inst15015msg_us_mesg 14216,16, "Function '%.*s' not found. If this is a SQLJ function, use sp_help to check whether the object exists (sp_help may produce a large amount of output)."

exec sp_inst15015msg_us_mesg 14313,21, "Partition condition for object %ld, indid %d, ptncondid %ld was not found in database %d."

exec sp_inst15015msg_us_mesg 14505,16, "ASE cannot mount these databases. The version in the manifest file is newer than the version in the Server. Server: log version =%d upgdvers =%ld, Manifest File: log vers =%d upgd vers =%ld."

exec sp_inst15015msg_us_mesg 14506,16, "Mount database failed due to page size incompatibility. The current page size is %ld, and the manifest file shows that the databases you are trying to mount are of page size %ld."

exec sp_inst15015msg_us_mesg 14523,16, "UNMOUNT DATABASE: Database '%.*s' does not exist."

exec sp_inst15015msg_us_mesg 14534,20, "Unable to put process %ld to sleep. Aborting UNMOUNT DATABASE command."

exec sp_inst15015msg_us_mesg 14545,16, "Cannot locate the logical page %ld for database '%.*s', dbid=%d, on the device '%.*s'. The page on the device is logical page %ld for dbid %d."

exec sp_inst15015msg_us_mesg 14560,20, "Attempt to write the manifest file failed; error code is %ld."

exec sp_inst15015msg_us_mesg 14561,20, "Attempt to read the manifest file failed; error code is %ld."

exec sp_inst15015msg_us_mesg 14600,16, "Failed to read page '%ld' from sysanchors."

exec sp_inst15015msg_us_mesg 14603,16, "The end-of-file marker for sysanchors is missing. Last page '%ld'."

exec sp_inst15015msg_us_mesg 14605,21, "The object id to which logical page 24 belongs to is set incorrectly as '%ld'. The expected object id is '%d'."

exec sp_inst15015msg_us_mesg 15007,16, "Table Corrupt: Object '%.*s' is not a user table but it has trigger (id %ld) bound to it."

exec sp_inst15015msg_us_mesg 15009,16, "Table Corrupt: Trigger (id %ld) for table '%.*s' was not found in sysobjects."

exec sp_inst15015msg_us_mesg 15010,16, "Table Corrupt: Target user table (id %ld) for trigger '%.*s' was not found in sysobjects."

exec sp_inst15015msg_us_mesg 15012,16, "Table Corrupt: Trigger '%.*s' has a target table '%ld' which does not match one of the triggers on the target table. Target table '%.*s' has a insert trigger '%ld', update trigger '%ld' and delete trigger '%ld'."

exec sp_inst15015msg_us_mesg 15018,16, "Table Corrupt: The %.*s entry for object ID '%ld', index ID '%d', does not have a matching entry in %.*s."

exec sp_inst15015msg_us_mesg 15019,16, "Table Corrupt: The %.*s for object ID '%ld', index ID '%d', does not match between %.*s and %.*s."

exec sp_inst15015msg_us_mesg 15056,16, "The root page %ld of index ID %d for empty table '%.*s can have at most one entry pointing to the first page %ld. However, it has either an incorrect entry, or more than one entries."

exec sp_inst15015msg_us_mesg 15071,16, "Table Corrupt: The %.*s entry for object ID '%ld', index ID '%d', partition ID '%d', does not have a matching entry in %.*s."

exec sp_inst15015msg_us_mesg 15077,10, "Warning: Definition time object ID %ld (object name = %.*s) has been detected. This may have been left behind due to an improper rollback. Drop the object and re-run the command."

exec sp_inst15015msg_us_mesg 15078,16, "The root page %ld of index ID %d for empty sliced table %.*s has too many entries, or one or more child entries pointing to incorrect or deallocated pages."

exec sp_inst15015msg_us_mesg 15080,16, "The root page %ld of index id %d for table '%.*s' has inconsistent rootkeys information. Drop and recreate the index. Use DBCC REINDEX to rebuild indexes on system catalogs with this form of inconsistency."

exec sp_inst15015msg_us_mesg 15101,17, "There is insufficient memory to allocate %ld bytes. Please increase configuration parameter 'messaging memory', or try again when there is less activity on the server."

exec sp_inst15015msg_us_mesg 15150,16, "Cannot retrieve SYBASE_JRE environment variable."

exec sp_inst15015msg_us_mesg 15400,16, "Adaptive Server is unable to reset the system encryption password because the old password was either incorrectly specified or missing."

exec sp_inst15015msg_us_mesg 15405,18, "Adaptive Server failed to %s the system encryption password. This is an internal error."

exec sp_inst15015msg_us_mesg 15421,11, "The '%.*s' command cannot be executed because the encryption password does not exist in database '%S_DBID'."

exec sp_inst15015msg_us_mesg 15424,16, "Adaptive Server cannot access the encryption key with object id '%ld' in database '%.*s'."

return

end     -- }
go

/*
** SP_INST15015MSG_ALL_OTH_MESGS
**
** Description:
**
**
*/
create procedure sp_inst15015msg_all_oth_mesgs
as
begin   -- {

exec sp_inst15015msg_oth_mesg 180, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 217, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 280, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 540, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 713, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 863, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 872, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 913, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 942, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 952, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 1031, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 1043, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 1265, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 1548, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 1805, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 1945, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2235, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2525, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2592, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2805, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2811, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2813, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2814, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2815, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2816, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2817, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2823, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2824, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2825, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2826, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 2827, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3019, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3020, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3021, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3121, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3123, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3124, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3125, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3127, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3136, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3146, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3165, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3166, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3214, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3216, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3221, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3222, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3223, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3225, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3227, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3237, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3238, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3244, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3248, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3250, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3305, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3306, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3307, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3308, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3309, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3310, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3311, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3312, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3318, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3403, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3412, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3413, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3424, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3425, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3474, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3478, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3508, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3513, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3612, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3613, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3614, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3615, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3616, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3625, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3630, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3650, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3663, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3703, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3741, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3904, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3905, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3931, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 3941, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4205, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4211, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4212, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4213, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4214, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4215, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4216, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4218, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4219, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4222, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4234, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4313, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4314, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4317, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4318, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4321, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4322, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4408, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4430, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4905, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4916, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4942, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4943, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4944, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4946, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 4974, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5005, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5115, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5120, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5135, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5143, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5146, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5147, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5164, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5839, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5840, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5843, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5846, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5848, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5853, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5858, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5861, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5881, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5883, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5887, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 5899, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6008, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6009, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6010, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6011, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6229, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6234, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6239, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6253, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6254, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6255, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6271, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6701, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6702, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6902, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 6908, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7112, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7114, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7120, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7121, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7123, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7124, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7125, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7126, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7127, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7128, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7134, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7137, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7155, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7156, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7164, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7165, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7401, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7402, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7403, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7404, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7405, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7407, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7414, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7717, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7735, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7736, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7743, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7757, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7777, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7783, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7791, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7905, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7906, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7907, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7910, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7911, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7912, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7913, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7914, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7915, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7916, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7917, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7918, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7920, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7921, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7923, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7924, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7925, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7926, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7927, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7928, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7938, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7939, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7948, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7949, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7953, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7967, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7969, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7972, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7977, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7978, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7979, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7980, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 7989, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8005, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8015, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8201, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8211, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8215, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8401, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8402, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8415, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8438, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8608, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8701, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8702, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8703, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8704, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8706, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8801, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8802, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8806, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8901, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8902, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8903, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 8904, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9004, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9142, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9147, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9211, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9283, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9513, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9817, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9819, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9820, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9904, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9905, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9911, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9912, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9922, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9923, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9924, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9931, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9935, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9936, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9996, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9997, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9998, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 9999, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10218, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10219, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10220, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10221, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10225, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10231, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10232, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10236, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10237, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10257, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10258, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10355, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10472, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10697, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10698, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10762, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10818, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10819, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10823, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10824, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10825, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10826, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10841, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10846, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10864, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 10879, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11001, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11002, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11003, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11004, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11005, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11031, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11056, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11080, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11236, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11238, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11249, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11250, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11265, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11284, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11294, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11718, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 11719, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12034, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12203, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12205, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12207, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12307, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12308, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12309, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12310, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12311, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12312, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12313, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12314, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12315, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12317, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12318, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12321, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12323, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12326, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12327, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12328, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12332, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12334, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12504, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12505, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12506, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12507, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12508, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12519, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12531, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12540, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12541, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12546, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12586, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12717, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12718, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12721, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12722, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12723, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12724, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12732, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12736, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12747, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12748, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12761, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12767, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12768, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12770, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12802, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12827, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12829, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12830, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12844, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12845, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12856, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12905, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12906, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12908, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12909, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12910, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12931, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12932, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12934, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12936, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12946, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12947, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12948, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12956, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12959, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12974, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12981, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 12999, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 13152, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 13900, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14123, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14124, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14216, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14313, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14505, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14506, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14523, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14534, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14545, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14560, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14561, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14600, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14603, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 14605, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15007, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15009, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15010, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15012, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15018, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15019, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15056, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15071, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15077, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15078, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15080, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15101, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15150, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15400, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15405, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15421, "delete", "ANY"

exec sp_inst15015msg_oth_mesg 15424, "delete", "ANY"

return

end     -- }
go


/*
** SP_INST15015MSG
**
** Description:
**
*/
create procedure sp_inst15015msg
as
begin   -- {

exec sp_inst15015msg_config

dump tran master with truncate_only

exec sp_inst15015msg_all_us_mesgs

dump tran master with truncate_only

exec sp_inst15015msg_all_oth_mesgs

dump tran master with truncate_only

return

end     -- }
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_downgrade_durability')
begin
	drop procedure sp_downgrade_durability
end
go
print "Installing sp_downgrade_durability"
go


/*
** SP_DOWNGRADE_DURABILITY
**
** Description
**      Satellite proc of sp_downgrade. It will change the durability
**      of any database with reduced durability to full before
**      removing the durability column from sysdatabases.
**
** Parameters
**      @action, "exec" or "display"
**
** Returns
**      0 - success
**      1 - error
*/
create procedure sp_downgrade_durability @action sysname = "display"
as
begin
        declare @dbname sysname,
                @tempdb_mask int,
                @inmemorydb_mask int,
		@durability int,
		@durability_str sysname,
		@baddbstat int,
		@baddbstat2 int,
		@baddbstat3 int

	set nocount on

        if (proc_role('sa_role') < 1 )
                return 1

	if (@action not in ("display", "exec"))
	begin
		print "Usage: sp_downgrade_durability [display | exec]"
		return 1
	end

        /*
        ** Change the durability only on those databases that are writable
        **
        ** sysdatabases.status not in 0x20 (in load), 0x40 (not rec),
        ** 0x80 (bypass), 0x100 (suspect), 0x400 (rdonly), 0x8000 (emergency)
        **
        ** sysdatabases.status2 not in 0x10 (offline), 0x400 (online for
        ** standby access)
        **
        ** sysdatabases.status3 not in 0x1 (user proxy), 0x2 (ha proxy),
        ** 0x8 (shutdown), 0x10 (failedover), 0x80 (quiesced), 0x400000
        ** (archive)
        */
        select  @baddbstat  = 34272 , @baddbstat2 = 1040,
                @baddbstat3 = 4194459

	create table #durability(id int, name sysname)
	insert #durability values(0, "undefined")
	insert #durability values(1, "full")
	insert #durability values(2, "delayed_commit")
	insert #durability values(3, "periodic")
	insert #durability values(4, "at_checkpoint")
	insert #durability values(5, "at_shutdown")
	insert #durability values(6, "no_recovery")
	
        select @tempdb_mask = number
        from master..spt_values
        where type = "D3" and name = "TEMPDB STATUS MASK"

        select @inmemorydb_mask = number
        from  master..spt_values
        where type = "D4" and name = "in-memory database"

	select name, status, status2, status3, durability
	into #baddb
	from master..sysdatabases
	where (durability > 2)
	and (((status  & @baddbstat)  != 0)
	  or ((status2 & @baddbstat2) != 0)
	  or ((status3 & @baddbstat3) != 0))

	if (@@rowcount > 0)
	begin
		/*
		** This is not considered an error to abort the downgrade.
		** Downgrade has to run in 'override' mode to work with
		** these databases in the server. We don't have to include
		** any error in the sp_downgrade 'prepare' phase.
		*/
		print "The following databases will be skipped because they don't have the right status."
		select b.name, status, status2, status3, d.name as durability
		into #baddb1
		from #baddb b, #durability d
		where d.id = b.durability 

		exec sp_autoformat #baddb1
		print ""
	end
		
        /*
        ** Open a cursor for all databases with durability
        ** greater than DELAYED_COMMIT (2) that are
        ** not temporary nor in-memory databases nor
	** unaccessible.
        */
        declare c cursor for
        select name, durability from master..sysdatabases
        where (durability > 2)
        and ((status  & @baddbstat)  = 0)
        and ((status2 & @baddbstat2) = 0)
        and ((status3 & (@baddbstat3 | @tempdb_mask)) = 0)
        and ((status4 & @inmemorydb_mask) = 0)
        and (dbid != 2)
        order by dbid

        open c

        fetch c into @dbname, @durability
        while (@@sqlstatus = 0)
        begin
		select @durability_str = name
		from #durability
		where id = @durability

		print  "Altering database '%1!' durability from '%2!' to 'full'",
			@dbname,@durability_str

		if (@action = "exec")
                	alter database @dbname set durability=full
                fetch c into @dbname, @durability
        end

        close c
        deallocate cursor c

        /*
        ** Get rid of durability in sysdatabases and remove
        ** the DURABLE bit (0x400).

	** While doing this, also remove column 'spare', which was needed
	** for compatibility between Clusters and SMP.

        */
	if (@action = "exec")
	begin
        	update master..sysdatabases set durability = null,
        	status4 = status4 & ~2048
        	where durability is not null
        	delete syscolumns where id = 30
        	and name = 'durability'

        	update master..sysdatabases set spare = null
        	where spare is not null
        	delete syscolumns where id = 30
        	and name = 'spare'

		/*
		** Delete the upgrade item 1620 which initializes
		** durability column during such that it won't be
		** skipped if another minor upgrade happens after
		** downgrade.
		*/
		delete master..sysattributes where class = 1
		and attribute = 1620
	end
end

go
exec sp_procxmode 'sp_downgrade_durability', 'anymode'
go
grant execute on sp_downgrade_durability to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_downgrade_sysobjects')
begin
	drop procedure sp_downgrade_sysobjects
end
go
print "Installing sp_downgrade_sysobjects"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_downgrade')
begin
	drop procedure sp_downgrade
end
go
print "Installing sp_downgrade"
go


/*
** raiserror Messages for downgrade
**
** 17428 "You must be in the 'master' database in order to change database options."   
** 19779 "ERROR: Cannot downgrade to '%1!' server, which does not support server's current default sortorder '%2!'."
** 19891, "ERROR: Unable to downgrade this server from ASE version '%1!' to ASE version '%2!'. Please reconfigure the remote servers that are using SSL to avoid specification of common name and to ensure that the remote server names are less than 32 characters:"
** 19954 "ERROR: Cannot downgrade to '%1!' server, which does not support the current charset '%2!'."
** 19985 "ERROR: Cannot downgrade to '%1!' server, which does not support bigdatetime and bigtime datatypes."
*/

/*
** SP_DOWNGRADE_SYSOBJECTS
**
** Description
**	sproc to reset the sysobjects schema back to it's original form.
**
** Parameter:
**	@action	-	"display" to display all objects whose sysstat3
**			column has non-zero value.
**			"exec" to restore sysobjects back to original version.
**
** Returns
**	0 - success
**	1 - error
**
*/
create procedure sp_downgrade_sysobjects @action sysname = "display"
as
begin   -- {

	declare @dbname sysname,
		@objname sysname,
		@objstat3 unsigned smallint,
		@retval int,
		@dbid int,
		@sqlcmd varchar(1024),
		@baddbstat int,
		@baddbstat2 int,
		@baddbstat3 int,
		@warnings int

	if (@action not in ("display", "exec"))
	begin
		print "Usage: sp_downgrade_sysobjects [display | exec]"
		return 1
	end

	print "Checking sysobjects in preparation for downgrade"

	/*
	** COPY from sp_downgrade.
	** Downgrade only those databases that are writable 
	**
	** sysdatabases.status not in 0x20 (in load), 0x40 (not rec), 
	** 0x80 (bypass), 0x100 (suspect), 0x400 (rdonly), 0x8000 (emergency)
	**
	** sysdatabases.status2 not in 0x10 (offline), 0x400 (online for 
	** standby access)
	**
	** sysdatabases.status3 not in 0x1 (user proxy), 0x2 (ha proxy),
	** 0x8 (shutdown), 0x10 (failedover), 0x80 (quiesced), 0x400000 
	** (archive)
	*/
	select 	@baddbstat  = 34272 , @baddbstat2 = 1040, 
		@baddbstat3 = 4194459

	select dbid
	into #sysdatabases1
	from master.dbo.sysdatabases
	where status  & @baddbstat  = 0
	and   status2 & @baddbstat2 = 0
	and   status3 & @baddbstat3 = 0
	order by dbid

	/*
	** Temp table is created to hold object name whose sysstat3
	** is not zero, as cursor cannot be created based on a select
	** statement containing variable "@dbname" and composing cursor
	** declaration and "@dbname" into immediate statement doesn't
	** work either.
	*/
	create table #stat3obj
	(
		name sysname,
		sysstat3 unsigned smallint
	)

	set @warnings = 0

	/* A cursor to traverse sysdatabases */
	declare sysdbc2 cursor for
		select dbid from #sysdatabases1

	open sysdbc2
	fetch sysdbc2 into @dbid
	
	while (@@sqlstatus = 0)
	begin -- {
		
		select @dbname = db_name(@dbid)
		set @retval = 0
		select @sqlcmd = 'select @retval = count(1) from ' + @dbname +
				'..sysobjects where sysstat3 != 0 ' +
				'and type = ''U'' '
		exec (@sqlcmd)

		/*
		** If rows having non-zero sysstat3 are found, print
		** them out as warnings in "display" mode or return as
		** errors in "exec" mode.
		*/
		if @retval != 0
		begin
			/* Report warnings of these tables */
			select @sqlcmd = 'insert #stat3obj ' +
				'select name, sysstat3 from ' + @dbname
				+ '..sysobjects where sysstat3 != 0 ' +
				'and type = ''U'' '
			exec (@sqlcmd)

			declare sysdbc3 cursor for
				select name, sysstat3 from #stat3obj

			open sysdbc3
			fetch sysdbc3 into @objname, @objstat3
			while (@@sqlstatus = 0)
			begin -- {
				/*
				** Check status3 of sysobjects row,
				** 0x0001 - FULL logging mode.
				** 0x0002 - MINIMAL logging mode.
				** 0x8000 - Incremental transfer eligible.
				*/
				if (@objstat3 & 1 = 1)
				begin
					print "Error: Table '%1!..%2!' with FULL logging mode should be altered back to default logging mode before downgrade.", @dbname, @objname
					select @warnings = @warnings + 1
				end
				if (@objstat3 & 2 = 2)
				begin
					print "Error: Table '%1!..%2!' with MINIMAL logging mode should be altered back to default logging mode before downgrade.", @dbname, @objname
					select @warnings = @warnings + 1
				end
				if (@objstat3 & 32768 = 32768)
				begin
					print "Error: Table '%1!..%2!' eligible for incremental transfer should be altered to turn off incremental transfer before downgrade.", @dbname, @objname
					select @warnings = @warnings + 1
				end
				fetch sysdbc3 into @objname, @objstat3
			end	--}
			close sysdbc3
			deallocate cursor sysdbc3
			delete from #stat3obj
		end
		
		/*
		** User must have altered the tables having non-zero
		** sysstat3 column. Remove sysstat3 for sysobjects
		** and restore objspare in "exec" mode. 
		*/
		if ((@action = "exec") and (@warnings = 0))
		begin
			select @sqlcmd = 'delete ' + @dbname +
					'..syscolumns where id = 1 ' +
					'and name = ''sysstat3'' ' +
					'update ' + @dbname +
					'..syscolumns set type = 56,' +
					'length = 4, usertype = 7 ' +
					'where id = 1 and name = ''objspare'' '
			exec (@sqlcmd)
		end

		fetch sysdbc2 into @dbid
	end	--}

	close sysdbc2
	deallocate cursor sysdbc2

	if (@warnings > 0)
	begin
		print "There are %1! errors during checking sysobjects.", @warnings
		print "Please run alter table to set these reported tables to normal mode before downgrade."
		return 1
	end
	
	return 0
end	-- }

go

/*
** SP_DOWNGRADE
** 
** Description
**	This stored procedure must be executed to downgrade a server
**	from version to a previous one.
** 
** Parameters
**	@cmd	- 'help', 'prepare' or 'downgrade'. If null, 'help'
**		  is the default.
**	@toversion	- Target version in char format
**	@verbose	- 0 or 1, to control verbosity
**	@override	- 0 or 1: if 1, skip databases that are not writable
** Returns
**	0 - success
**	1 - error
*/
create procedure sp_downgrade 
			@cmd varchar(10) 	= 'help',
			@toversion varchar(10) 	= null, 
			@verbose int 		= 0,
			@override int 		= 0
as
begin -- {
	declare @dbid int, 
		@dbname sysname,
		@devname sysname,
		@cachename varchar(255),
		@alldbs int,
		@allbutmasterdb int,
		@masterdb int,
		@whatdbid int, 
		@fromversion varchar(10),
		@fromversid int,
		@toversid int,
		@any15versid int,
		@actionid int,
		@baddbstat int,
		@baddbstat2 int,
		@baddbstat3 int,
		@imdbstat int,
		@cachedevstat int,
		@imcachestat int,
		@dbstat4 int,
		@retval int,
		@prepare_error_count int,
		@usage varchar(128),
		@sqlbuf varchar(1024),
		@sqlcmd varchar(1024),
		@dbnameoffset int,
		@downgrade_sysconfigures_15015_cmd varchar(1024),
		@mark_dbprocs_sql varchar(128),
		@drop_1502_sysoptions_sql varchar(512),
		@dbinfo_reset_asevers_sql varchar(100),
		@dbinfo_turnon_downgradeneed_sql varchar(512),
		@dbinfo_update_1502_master_sql varchar(128),
		@dbinfo_update_1502_userdb_sql varchar(128),
		@dbinfo_update_15015_alldbs_sql varchar(128),
		@dbinfo_update_1500_master_sql varchar(128),
		@dbinfo_update_1500_userdb_sql varchar(128),
		@errorlog_msg varchar(128),
		@downgrade_passwords_sql varchar(128),
		@downgrade_sysconfigures_15015_sql1 varchar(512),
		@downgrade_sysconfigures_15015_sql2 varchar(512),
		@downgrade_sysconfigures_15015_sql3 varchar(512),
		@downgrade_15015_config varchar(30),
		@reset_sysservers_srvnetname_len varchar(128),
		@downgrade_15015_msg varchar(30),
		@sysobjstat3_sql varchar(20),
		@durability_sql varchar(256),
		@soid int,
		@soname varchar(30),
		@objname sysname,
		@objstat3 smallint,
		@csid int,
		@v char(1),
		@c int,
		@cct int

	set nocount on
	
	select @usage = 'sp_downgrade @cmd = {''prepare'' | ''downgrade'' | ''help''}, @toversion = ''n'' [, @verbose = 0 | 1 ] [, @override = 0 | 1]'

	select @cmd = lower(isnull(@cmd, 'downgrade'))
	
	if ((@toversion is null) or (@cmd = 'help'))
	begin
		print @usage
		return 0
	end

	if (@cmd not in ('prepare', 'downgrade'))
	begin
		print @usage
		return 1
	end
	
	/*
	** Because this procedure could update security tables,
	** SSO role is required and because it is an administration
	** tool SA role is also required. The sybase_ts_role is
	** needed to execute the command dbcc markprocs.
	*/
	if (proc_role('sa_role') = 0 or 
		proc_role('sso_role') = 0 or
		proc_role('sybase_ts_role') = 0)
	begin
		return 1
	end

	if db_name() != "master"
	begin
		/* 17428, "You must be in the 'master' database in order to change database options." */
		raiserror 17428
		return 1
	end
	
	/* Initialize */
	select 	@prepare_error_count = 0, 
		@any15versid = 0

	/* Determine which version we are downgrading from */
	select @fromversid = coalesce(nullif(convert(smallint, 
				dbinfo_get('master','ASEvers')),0),
				@@version_number)
	select @fromversion = convert(varchar(2), @fromversid / 1000)
		+ '.' + convert(varchar(1), ((@fromversid / 100) % 10))
		+ '.' + convert(varchar(1), ((@fromversid / 10) % 10))
		+ '.' + convert(varchar(1), (@fromversid % 10))

	/*
	** Valid 'to' versions: any version whose major number equals
	** the @fromversid major number, and is < @fromversid.
	*/
	select @toversid = 0
	select @cct = datalength(@toversion)
	select @c = 1
	while @c <= @cct
	begin
		select @v = substring(@toversion, @c, 1)
		if (@v between '0' and '9')
		begin
			select @toversid = (@toversid * 10) + convert(int, @v)
		end
		else if (@v != '.')
		begin
			-- Not a valid version ... stop
			print "'%1!' is not a valid downgrade version.", @toversion
			return 1
		end
		select @c = @c + 1
	end
	if (@toversid = 0)
	begin
		print "'%1!' is not a valid downgrade version.", @toversion
		return 1
	end
	while (@toversid < 10000)
		select @toversid = @toversid * 10

	select @toversion = convert(varchar(2), @toversid / 1000)
		+ '.' + convert(varchar(1), ((@toversid / 100) % 10))
		+ '.' + convert(varchar(1), ((@toversid / 10) % 10))
		+ '.' + convert(varchar(1), (@toversid % 10))

	/*
	** Major-version downgrade is not allowed.
	** Cannot "downgrade" to a higher release than current.
	** Downgrade between SDC and SMP is disallowed; these are
	** denoted by SDC=5 in the subminor number, SMP=0.
	** 15035 server must only be downgraded to 15015, but
	** not existing 15005 nor 15025, there is no need
	** for an extra check.
	*/
	if (((@toversid / 1000) != (@fromversid / 1000))
	 or (@fromversid < @toversid)
	 or ((@fromversid % 10) != (@toversid % 10)))
	begin
		print "'%1!' is not a valid downgrade version from %2!.",
			@toversion, @fromversion
		return 1
	end

	print "Downgrade from %1! to %2! (command: '%3!')", @fromversion,
			@toversion, @cmd
	
	/*
	** Downgrade can only be performed when server is under single
	** user mode.
	*/
	if (is_singleusermode() = 0)
	begin
		print 'You cannot run sp_downgrade; server must be in single-user mode.'
		print 'Try restarting the server using the -m option.'
		return 1
	end

	/* 
	** Downgrade only those databases that are writable 
	**
	** sysdatabases.status not in 0x20 (in load), 0x40 (not rec), 
	** 0x80 (bypass), 0x100 (suspect), 0x400 (rdonly), 0x8000 (emergency)
	**
	** sysdatabases.status2 not in 0x10 (offline), 0x400 (online for 
	** standby access)
	**
	** sysdatabases.status3 not in 0x1 (user proxy), 0x2 (ha proxy),
	** 0x8 (shutdown), 0x10 (failedover), 0x80 (quiesced), 0x400000 
	** (archive)
	*/
	select 	@baddbstat  = 34272 , @baddbstat2 = 1040, 
		@baddbstat3 = 4194459

	select @imdbstat = number from master..spt_values
	where name = "in-memory database"

	select dbid 
	into #sysdatabases 
	from master.dbo.sysdatabases
	where status  & @baddbstat  = 0
	and   status2 & @baddbstat2 = 0
	and   status3 & @baddbstat3 = 0
	and   status4 & @imdbstat = 0
	order by dbid
		
	select a.dbid, a.name 
	into #baddb
	from master.dbo.sysdatabases a
	where not exists(select 1 from #sysdatabases b
				 where a.dbid = b.dbid)

	if (@@rowcount > 0)
	begin
		/*
		** If there is any database that we know in advance that cannot
		** be downgraded, skip it only if WITH OVERRIDE was specified.
		*/
		if (@override = 0)
		begin
			print 'sp_downgrade cannot be run because the following databases are not writable or they cannot be downgraded.'
			print 'Use sp_downgrade ... @override = 1 to skip these databases.'
		end
		else
		begin
			print 'sp_downgrade will skip the following databases because they are not writable or cannot be downgraded.'
		end

		select dbid, convert(char(30), name) as name
		from #baddb
		
		if (@override = 0)
		begin
			return 1
		end
	end

	-- If we are at the requested downgrade level, check whether all
	-- databases have been downgraded.  If so, stop with success;
	-- else declare an error.
	if (@fromversid = @toversid)
	begin
		print "This installation is already at version %1!", @toversion
		select @dbid = 2
		while @dbid is not null
		begin
			if (not exists (select dbid from #baddb where dbid = @dbid))
			and (@toversid != (select convert(smallint,
							dbinfo_get(@dbid, 'asevers'))))
			begin
				print "Database ID %1! is not at the correct version.",
					@dbid
				select @prepare_error_count = @prepare_error_count + 1
			end
			select @dbid = min(dbid)
			from master.dbo.sysdatabases
			where dbid > @dbid
		end
		if @prepare_error_count != 0
		begin
			print "sp_downgrade cannot continue. Run 'online database' for all databases to bring them back up to ASE's current release level, then retry sp_downgrade."
			return 1
		end
		return 0
	end

	select @errorlog_msg = 'Preparing ASE downgrade from ' + @fromversion 
		+ ' to ' + @toversion + '.'	
	dbcc printolog(@errorlog_msg)

	/*
	** We will verify encryption downgrade and prepare for
	** password downgrade for both prepare mode and downgrade mode.
	** If either fail, we return fail.
	** Initally set retval to 0.It will be set by sp_encryption if 
	** sp_encryption is fails or by sp_passwordpolicy if sp_passwordpolicy
	** fails.
        ** If we are downgrading to 1502 then neither are called.
	*/
	select @retval = 0

	/* 
	** verify_downgrade, 15.0.1 when @toversid is 15010 or 15015.
	** Both are at same level of the encrypted column feature.
	*/
	if (@toversid = 15010 or @toversid = 15015)
	begin
		exec @retval = sp_encryption 'verify_downgrade', '15.0.1'
	end
	else if (@toversid = 15000)
	begin
		exec @retval = sp_encryption 'verify_downgrade', '15.0'
	end

	if @retval != 0
	begin
		select @prepare_error_count = @prepare_error_count + 1
	end

	/*
	** Starting with 15.0.2, new password encryption algorithm is used to
	** encrypt login passwords.
	** On downgrade to SMP 15.0.1 or prior and SDC version 15.0.1.5,
	** the login password is reset for logins with password encrypted 
	** only using the new algorithm.
	*/
	if (@toversid <= 15015)
	begin
		exec @retval = sp_passwordpolicy 'prepare_downgrade'

		if @retval != 0
		begin
			select @prepare_error_count = @prepare_error_count + 1
		end
	end

	if (@toversid < 15500)
	begin
		-- Some datatypes don't exist before 15.5.  Assure they are unused.
		print "Checking datatypes in preparation for downgrade"

		select @retval = 0

		select @sqlbuf = 'select @c = count(1) from :DBNAME:..syscolumns ' +
			'where type in (select type from :DBNAME:..systypes ' +
			'where name in (''bigdatetime'', ''bigtime'', ' +
			'''bigdatetimen'', ''bigtimen''))'

		select @dbid=db_id('master')
		while (@dbid is not null)
		begin
			select @dbname = name
			from master..sysdatabases
			where dbid = @dbid

			select @sqlcmd = @sqlbuf
			select @dbnameoffset = patindex('%:DBNAME:%', @sqlcmd)
			while (@dbnameoffset > 0)
			begin
				select @sqlcmd = stuff(@sqlcmd,
							@dbnameoffset, 8,
							@dbname)
				select @dbnameoffset = patindex('%:DBNAME:%',
								@sqlcmd)
			end

			exec (@sqlcmd)
			if (@c > 0)
			begin
				raiserror 19985, @toversion
				select @retval = 1
			end
			else
			if @verbose = 1
			begin
				print 'Database %1! does not use new datatypes',
					@dbname
			end

			select @dbid=min(dbid)
			from master..sysdatabases
			where dbid > @dbid
		end

		/* Block downgrade unless users remove usages of new datatypes */
		if @retval != 0
		begin
			select @prepare_error_count = @prepare_error_count + 1
		end

		/*
		** Before 15.5 stored procedures cannot be created with
		** deferred name resolution. If we have procedures created
		** with deferred name resolution the downgrade machinery
		** will mark them to be recreated from text so they can
		** be executed in the downgraded server. But the text in
		** syscomments will have 'select *' not expanded, for
		** getting the 'select *' correctly expanded the procedures
		** would have to be recreated from SQL script.
		**
		** So during 'prepare' we warn if there are databases having
		** stored procedures created with deferred name resolution
		** and in 'verbose' mode we print out the names for the
		** procedures in each database.
		*/
		print "Checking procedures in preparation for downgrade"

		/* Cursor for traversing databases */
		declare sysdbc2 cursor for
			select dbid from #sysdatabases

		/* Initializations */
		set @retval = 0
		set @c = 0

		select Name=name, Owner=user_name(uid)
		into #sprocDNR
		from sysobjects
		where 1 = 2

		select @sqlbuf = " truncate table #sprocDNR
				   insert #sprocDNR
				   select Name=o.name,
					  Owner=user_name(o.uid)
				   from :DBNAME:..sysobjects o
				   where exists (select 1 from
						 :DBNAME:..sysprocedures p
						 where p.id = o.id and
							p.type = 2048)
				   order by o.name"

		/* Scan sysprocedures in each database */
		open sysdbc2
		fetch sysdbc2 into @dbid

		while (@@sqlstatus = 0)
		begin -- {

			select @dbname = db_name(@dbid)
			select @sqlcmd = "select @c = count(1) from "
				+ @dbname + "..sysprocedures " +
				"where type = 2048"

			exec(@sqlcmd)

			if (@c != 0)
			begin
				set @retval = 1
				print "Warning: There are procedures in database: %1! (dbid: %2!) created with deferred name resolution", @dbname, @dbid

				if (@verbose = 1)
				begin
					print "List of procedures created with deferred name resolution in database: %1! (dbid: %2!)", @dbname, @dbid

					select @sqlcmd = @sqlbuf
					select @dbnameoffset =
						patindex('%:DBNAME:%', @sqlcmd)

					while (@dbnameoffset > 0)
					begin
						select @sqlcmd =
							stuff(@sqlcmd,
							      @dbnameoffset,
							      8, @dbname)

						select @dbnameoffset =
							patindex('%:DBNAME:%',
								 @sqlcmd)
					end

					exec (@sqlcmd)

					exec sp_autoformat #sprocDNR

					print ""
				end
			end

			fetch sysdbc2 into @dbid

		end -- }

		if (@retval = 1)
		begin
			/*
			** At least one database has procedures created with
			** deferred name resolution. Print a warning with
			** the advice for recreating manually those procedures
			** for getting the right "select *" expanded text in
			** syscomments.
			*/
			print ""
			print "Warning: Procedures created with deferred name resolution that contain statements with 'select *' syntax would need to be recreated manually from text. If they are not recreated they will still execute but the text in syscomments will remain with 'select *' unexpanded."
			print ""
		end
		else if (@verbose = 1)
		begin
			/*
			** We didn't find any procedure created with deferred
			** name resolution.
			*/
			print "There are no procedures created with deferred name resolution in any database"
		end

		close sysdbc2
		deallocate cursor sysdbc2
	end

	if ( @toversid < 15030 and @toversid != 15015) 
	begin -- {
		/*
		** Starting at 15.0.3, the size of sysservers.srvnetname
		** changed from 32 bytes to 255 bytes.  If any srvnetname
		** is greater than 32 bytes do not let downgrade happen.
		** (exception: 15015 was original version for ssl=CN changes
		** and increase of srvnetname column.)
		*/
		print "Checking sysservers in preparation for downgrade"
	        if exists (select 1 from master.dbo.sysservers
       	         where
       			lower(srvnetname) like "%ssl=%"
                        or  datalength(srvnetname) > 32 )
        	begin
			raiserror 19891, @fromversion, @toversion
			select srvname, srvnetname into #newformat
			from master.dbo.sysservers
				where
				lower(srvnetname) like "%ssl=%"
				or  datalength(srvnetname) > 32

			exec sp_autoformat
				@fulltabname = "#newformat",
				@selectlist = "'Server Name' = srvname,
				'Server Net Name' = srvnetname"

			select @prepare_error_count = @prepare_error_count + 1
		end
		else
		begin
			print "There were no errors which involve the sysservers table."
		end

		/*
		** Starting at 15.0.3, the directory service entry may contain
		** CN=<common name>. If any row in syslisteners has such a
		** string, ssl was configured for this listener.  State that
		** ssl needs to be disabled and list the listeners.
		*/
		print "Checking syslisteners in preparation for downgrade"
	        if exists (select 1 from master.dbo.syslisteners
      	        where
			lower(net_type) like "%ssl%"
       			or lower(address_info) like "%cn=%" )
        	begin
			raiserror 19943, @fromversion, @toversion
			select net_type, address_info into #newformat1
			from master.dbo.syslisteners
				where
				lower(net_type) like "%ssl%"
				or lower(address_info) like "%cn=%"

			exec sp_autoformat
				@fulltabname = "#newformat1",
				@selectlist = "'Net Type' = net_type, 
				'Address Info' = address_info"

			select @prepare_error_count = @prepare_error_count + 1
		end
		else
		begin
			print "There were no errors which involve the syslisteners table."
		end

		/*
		** Starting at 15.0.3, sysprocedures has additional 
		** qp_setting column that is used to associate optimization 
		** goal and criteria with stored procedures. If the 
		** qp_setting column is not null, print an warning to user. 
		*/
		print "Checking sysprocedures in preparation for downgrade"

		/* A cursor to traverse sysdatabases */
		declare sysdbc1 cursor for
		select dbid from #sysdatabases

		set @retval = 0
		open sysdbc1
		fetch sysdbc1 into @dbid
		while (@@sqlstatus = 0)
		begin -- {
			select @dbname = db_name(@dbid)
	    		select @sqlcmd = 'select @retval = count(1) from '
				+ @dbname + '..sysprocedures ' +
		                'where qp_setting is not null'
			exec (@sqlcmd)
			if @retval != 0
			begin 
				print "Warning: There are non-NULL qp_setting rows in sysprocedures of database: %1! (dbid: %2!).", @dbname, @dbid 
				print "The qp_setting column in sysprocedures will be set to NULL and dropped during downgrade."
			end
			fetch sysdbc1 into @dbid
		end	--}
		close sysdbc1	
		deallocate cursor sysdbc1


		/*
		** Starting at 15.0.3, sysqueryplans has additional columns:
		** dbid, qpdate, sprocid, hashkey2, key1, key2, key3, key4.
		** If anyone of them is not null, print a warning message.
		*/
		print "Preparing sysqueryplans for downgrade"

		/* A cursor to traverse sysdatabases */
		declare sysdbc1 cursor for
			select dbid from #sysdatabases

		set @retval = 0
		open sysdbc1
		fetch sysdbc1 into @dbid
		while (@@sqlstatus = 0)
		begin -- {
				select @dbname = db_name(@dbid)
				select @sqlcmd = 'select @retval = count(1) from '
					+ @dbname + '..sysqueryplans ' +
					'where dbid is not null ' +
					'or qpdate is not null ' +
					'or sprocid is not null ' +
					'or hashkey2 is not null ' +
					'or key1 is not null ' +
					'or key2 is not null ' +
					'or key3 is not null ' +
					'or key4 is not null'
				exec (@sqlcmd)
				if @retval != 0
				begin
					print "Warning: There are non-NULL rows for dbid or qpdate or sprocid or hashkey2 or key1 or key2 or key3 or key4 in sysqueryplans of database: %1! (dbid: %2!).", @dbname, @dbid
					print "The respective column in sysqueryplans will be set to NULL and dropped during downgrade."
				end
				fetch sysdbc1 into @dbid
		end     --}
		close sysdbc1
		deallocate cursor sysdbc1

		/*
		** In 15.0.3 ESD#1, a new charset KZ1048 is added. Do not allow
		** downgrade to happen if server is using this charset.
		*/
		select @csid = value
		from master.dbo.syscurconfigs
		where config = 131
		if (@csid = 87)
		begin
			print ""
			raiserror 19954, @toversion, 'kz1048'
			select @prepare_error_count = @prepare_error_count + 1
		end

	end     --}

	/*
	** In 15.0.2, new nocase sortorders (id 52) are added for
	** Chinese and Japanese character sets: eucgb, gb18030, cp936,
	** eucjis, sjis and deckanji. If server is using these sortorder
	** as default, do not allow downgrade to happen.
	*/
	if (@toversid < 15020)
	begin -- {
		select @soid = value
		from master.dbo.syscurconfigs 
		where config = 123

		select @csid = value
		from master.dbo.syscurconfigs
		where config = 131

		select @soname = name
		from master.dbo.syscharsets
		where id = @soid and csid = @csid and type between 2000 and 2999

		if (@soid = 52) and (@csid in (170, 171, 173, 140, 141, 142))
		begin
			print ""
			raiserror 19779, @toversion, @soname
			select @prepare_error_count = @prepare_error_count + 1
		end
	end -- }

	/*
	** In 15.5, status4 column of sysdatabases has new values indicating
	** MINIMAL logging mode and in-memory database. Downgrade will report
	** those databases which are using these values.
	*/
	if ( @toversid < 15500 )
	begin
		print "Checking sysdatabases in preparation for downgrade"

		set @retval = 0

		select @imdbstat = 4096

		select @retval = count(1)
		from master..sysdatabases
		where (status4 & (@imdbstat | 256)) != 0

		if @retval != 0
		begin
			declare sysdbc0 cursor for
				select dbid, status4 from master..sysdatabases
				where (status4 & (@imdbstat | 256)) != 0

			open sysdbc0
			fetch sysdbc0 into @dbid, @dbstat4

			while (@@sqlstatus = 0)
			begin
				select @dbname = db_name(@dbid)
				if (@dbstat4 & 256 = 256)
				begin
					print "Error: Database '%1!' with MINIMAL logging mode should be altered back to FULL logging mode before downgrade.", @dbname
				end
				if (@dbstat4 & @imdbstat = @imdbstat)
				begin
					print "Error: In-memory database '%1!' should be dropped before downgrade.", @dbname
				end
				fetch sysdbc0 into @dbid, @dbstat4
			end

			close sysdbc0
			deallocate cursor sysdbc0

			select @prepare_error_count = @prepare_error_count + 1
		end

		/*
		** In 15.5, a new kind of device "cache device" is introduced.
		** Downgrade will advise users to drop these cache devices.
		*/
		print "Checking sysdevices in preparation for downgrade"

		set @retval = 0

		select @cachedevstat = 8

		select @retval = count(1)
		from master..sysdevices
		where status2 & @cachedevstat = @cachedevstat

		if @retval != 0
		begin
			declare sysdevc cursor for
			select name from master..sysdevices
			where status2 & @cachedevstat = @cachedevstat

			open sysdevc
			fetch sysdevc into @devname

			while (@@sqlstatus = 0)
			begin
				print "Error: Device '%1!' is a cache device, which should be dropped via sp_dropdevice before downgrade.", @devname
				fetch sysdevc into @devname
			end

			close sysdevc
			deallocate cursor sysdevc

			select @prepare_error_count = @prepare_error_count + 1
		end

		/*
		** In 15.5, a new cache type "inmemory_storage" is introduced.
		** Downgrade will advise users to drop the user-defined caches
		** whose type is "inmemory_storage".
		*/
		print "Checking user-defined caches in preparation for downgrade"

		set @retval = 0

		select @imcachestat = 65536

		select @retval = count(1)
		from master..sysconfigures
		where (parent = 19) and (status & @imcachestat = @imcachestat)
		
		if @retval != 0
		begin
			declare usercachec cursor for
			select name from master..sysconfigures
			where (parent = 19) and (status & @imcachestat = @imcachestat)

			open usercachec
			fetch usercachec into @cachename

			while (@@sqlstatus = 0)
			begin
				print "Error: Cache '%1!' is a inmemory_storage cache, which should be dropped via sp_cacheconfig before downgrade.", @cachename
				fetch usercachec into @cachename
			end

			close usercachec
			deallocate cursor usercachec

			select @prepare_error_count = @prepare_error_count + 1
		end
			
		/*
		** In 15.5, sysstat3 column of sysobjects is introduced.
		** Downgrade will clear the values of the column, and remove
		** it from syscolumns.
		*/
		set @retval = 0
		exec @retval = sp_downgrade_sysobjects "display"
		if @retval != 0
		begin
			select @prepare_error_count = @prepare_error_count + 1
		end
	end
	
	if @prepare_error_count != 0
	begin
		print " "
		print "sp_downgrade %1! failed.", @cmd
		print "Re-run sp_downgrade after addressing the items listed above."
		return @prepare_error_count
	end	

	if (@cmd = 'prepare')
	begin
		/*
		** In prepare mode the rest of non password/encryption
		** processing is done, as there is nothing else to verify. 
		*/
		print 'sp_downgrade ''prepare'' completed.'
		return 0
	end 

	select 	@alldbs = 0,
		@allbutmasterdb = -1,
		@masterdb = db_id('master'),
		@downgrade_passwords_sql = 'sp_passwordpolicy ''downgrade''',
		@mark_dbprocs_sql = 
			'dbcc markprocs(@dbid)',
		@drop_1502_sysoptions_sql = 
			'declare @d int ' +
			'delete syscolumns where id = 57 ' +
			'delete sysindexes where id = 57 ' +
			'delete sysobjects where id = 57 ' +
			'delete syspartitions where id = 57 ' +
			'delete systabstats where id = 57 ' +
			'select @d=rm_anchor(''master'',''table'', 57)',
		@dbinfo_reset_asevers_sql =
			'declare @d int ' +
			'select @d=dbinfo_update(@dbid, ''ASEvers'', ' +
			convert(varchar(10), @toversid) + ')',
		/* 32 as 0x00000002 indicates downgrade is needed */
		@dbinfo_turnon_downgradeneed_sql =
			'declare @d int, ' +
			'@stat4 int ' +
			'select @stat4=convert(int, dbinfo_get(''master'',''status4'')) ' +
			'select @d=dbinfo_update(1, ''status4'', 32 | @stat4)',
		@dbinfo_update_1502_master_sql = 
			'declare @d int ' +
			'select @d=dbinfo_update(1, ''upgd_minor'', 1560)',
		@dbinfo_update_15015_alldbs_sql =
			'declare @d int ' +
			'select @d=dbinfo_update(@dbid, ''upgd_minor'', 1700)',
		@downgrade_sysconfigures_15015_sql1 =
			'delete sysconfigures where name in ('+
			'''config file version'',''max query parallel degree'','+
			'''cost of a logical io'',''cost of a physical io'','+
			'''cost of a cpu unit'',''auto query tuning'','+
			'''enable query tuning mem limit'','+
			'''query tuning plan executions'','+
			'''enable query tuning time limit'','+
			'''max buffers per lava operator'','+
			'''enable merge join'',''mnc_full_index_filter'')',
		@downgrade_sysconfigures_15015_sql2 =
			'delete sysconfigures where name in ('+
			'''engine memory log size'',''compression memory size'','+
			'''enable sql debugger'',''identity reservation size'','+
			'''session tempdb log cache size'',''max nesting level'','+
			'''enable pci'',''max pci slots'','+
			'''pci memory size'','+
			'''restricted decrypt permission'',''net password encryption reqd'')',
		@downgrade_sysconfigures_15015_sql3 =
			'delete sysconfigures where name in ('+
			'''start xp server during boot'',''enable stmt cache monitoring'')',
		@downgrade_sysconfigures_15015_cmd =
			'if not exists (select 1 from sysconfigures where config = 392) ' +
			'begin '+
			'insert sysconfigures(config,value,comment,status,name,parent) values('+
			'392,0,''enable enterprise java beans'',262153,''enable enterprise java beans'',39) '+
			'delete master..sysattributes where class = 1 and attribute = 1560 ' +
			'end',
		/* 1502 upgd_minor for user tables is still 1554 */
		@dbinfo_update_1502_userdb_sql = 
			'declare @d int ' +
			'select @d=dbinfo_update(@dbid, ''upgd_minor'', 1554)',
		@dbinfo_update_1500_master_sql = 
			'declare @d int ' +
			'select @d=dbinfo_update(1, ''upgd_minor'', 1550)',
		@dbinfo_update_1500_userdb_sql = 
			'declare @d int ' +
			'select @d=dbinfo_update(@dbid, ''upgd_minor'', 1554)',
		@reset_sysservers_srvnetname_len =
			'update syscolumns ' +
			'set length=32 ' +
			'where id=40 and colid=4 and length>32',
		@downgrade_15015_config = "downgrade_15015_config",
		@downgrade_15015_msg = "@downgrade_15015_msg",
		@sysobjstat3_sql = "sysobjstat3_sql",
		@durability_sql = "UNUSED"

	/*
	** The following is a table which will contain various actions
	** to perform on downgrade.  The 'toversion' is either "any
	** version" or the highest ASE version at which the given action
	** is needed during downgrade.
	*/
	create table #actions 
	(
		actionid int,
		dbid int,
		toversion int,
		action varchar(1024),
		errorlog_msg varchar(128)
	)
	
	-- Downgrade login passwords if going to SMP version <= 15.0.1 or SDC version 15.0.1.5
	insert #actions values(1, @masterdb, 15015,
		@downgrade_passwords_sql, 
		'Downgrade : Downgrading login passwords.')

	-- Mark stored procs for recompile on any downgrade
	insert #actions values(2, @alldbs, @any15versid, 
		@mark_dbprocs_sql,
		'Downgrade : Marking stored procedures to be recreated from text.')

	-- Remove sysoptions if going to <= 15.0.1
	insert #actions values(3, @masterdb, 15010,
		@drop_1502_sysoptions_sql,
		'Downgrade : Dropping Sysoptions system table.')

	-- Downgrade systabstats if going to <= 15.0.1
	insert #actions values(4, @alldbs, 15010,
		'if exists (select 1 from :DBNAME:..syscolumns ' +
			'where id = 23 and name = ''pioclmdata'') ' +
			'begin ' +
        	        'delete :DBNAME:..syscolumns ' +
                	'where id = 23 ' +
	                '  and name in (''pioclmdata'', ''pioclmindex'', ' +
        	                        '''piocsmdata'', ''piocsmindex'') ' +
                	'plan ''(delete(i_scan csyscolumns '
                        	        + ':DBNAME:..syscolumns))'' ' +
	                'insert into :DBNAME:..syscolumns ' +
        	        '(id, number, colid, status, type, length, offset, ' +
                	        'usertype, cdefault, domain, name, status3) ' +
	                'values(23, 0, 19, 0, 62, 8, 112, ' +
        	                '8, 0, 0, ''spare2'', 0) ' +
	                'insert into :DBNAME:..syscolumns ' +
        	        '(id, number, colid, status, type, length, offset, ' +
                	        'usertype, cdefault, domain, name, status3) ' +
	                'values(23, 0, 27, 0, 62, 8, 144, ' +
        	                '8, 0, 0, ''spare4'', 0) ' +

	                'update :DBNAME:..syscolumns ' +
        	        'set name = ''spare5'' ' +
                	'where id = 23 and name = ''warmcachepgcnt'' ' +
			'end',
		'Downgrade : Downgrading Systabstats system table.')

	-- Downgrade sysconfigures if going to 15.0.1.5
	insert #actions values(5, @masterdb, 15015, @downgrade_15015_config,
		'Downgrade : Updating 15.0.1.5 configuration parameters.')

	-- Downgrade sysmessages if going to 15.0.1.5
	insert #actions values(6, @masterdb, 15015, @downgrade_15015_msg,
		'Downgrade : Updating 15.0.1.5 sysmessages.')
		
	-- Revert the length of sysservers.srvnetname from 255 to 32
	insert #actions values(7, @masterdb, 15020,
		@reset_sysservers_srvnetname_len,
		'Downgrade : Resetting max length of sysservers.srvnetname')

	-- Downgrade sysprocedures if going to < 15.0.3
	insert #actions values(8, @alldbs, 15020, 
		'update :DBNAME:..sysprocedures ' + 
			'set qp_setting = null ' +
			'where qp_setting is not null ' +
			'delete :DBNAME:..syscolumns ' +
			'where id = 5 and ' + 
			'name = ''qp_setting''',
		'Downgrade : Downgrading Sysprocedures system table.')

	-- Downgrade sysqueryplans if going to < 15.0.3
	insert #actions values(9, @alldbs, 15020,
		'update :DBNAME:..sysqueryplans ' +
			'set dbid = null, qpdate = null, sprocid = null, ' +
			'hashkey2 = null, key1 = null, key2 = null, ' +
			'key3 = null, key4 = null ' +
			'where dbid is not null ' +
			'or qpdate is not null ' +
			'or sprocid is not null ' +
			'or hashkey2 is not null ' +
			'or key1 is not null ' +
			'or key2 is not null ' +
			'or key3 is not null ' +
			'or key4 is not null ' +
			'delete :DBNAME:..syscolumns ' +
			'where id = 27 and name in (''dbid'', ''qpdate'', ' +
			'''sprocid'', ''hashkey2'', ' +
			'''key1'', ''key2'', ''key3'', ''key4'')',
		'Downgrade : Downgrade Sysqueryplans system table.')

	-- Remove some config params if going to < 15.0.3
	insert #actions values(10, @masterdb, 15020, 
		'delete from master.dbo.sysconfigures where config > 500',
		'Downgrade : Removing pre-15.0.3 configuration parameters.')

	-- Remove some config params if going to < 15.5
	insert #actions values(11, @masterdb, 15035, 
		'delete from sysconfigures where config > 508',
		'Downgrade : Removing pre-15.5 configuration parameters.')

	insert #actions values(12, @masterdb, 15035,
		@durability_sql,
		'Downgrade : Removing durability column in sysdatabases.')

	-- Remove types 'bigdatetime', 'bigtime' if goint to < 15.5
	insert #actions values(13, @alldbs, 15035,
		'delete :DBNAME:..systypes where name in ' +
			'(''bigdatetime'',''bigtime'', ''bigdatetimen'', ''bigtimen'')',
		'Downgrade : Removing types ''bigdatetime'' and ''bigtime''')

	-- Downgrade sysobjects if going to < 15.5
	insert #actions values(14, @masterdb, 15035,
		@sysobjstat3_sql,
		'Downgrade : Downgrade Sysobjects system table.')

	-- Remove index sysdevices.ncsysdevices on sysdevices if going to any SMP < 15.5
	-- Exception: 15015 is the only SDC version which is below 15030.
	if ( @toversid != 15015 )
	begin --{
		insert #actions values(15, @masterdb, 15030,
			'set switch on drop_system_index  with override ' +
			'drop index sysdevices.ncsysdevices ' +
			'set switch off drop_system_index ',
			'Downgrade : Removing index sysdevices.ncsysdevices on sysdevices.')
	end --}		
	
	/*
	** MAINTAINERS:  add downgrade tasks in this area.
	**
	** Place individual tasks above this comment, incrementing the
	** action ID.
	**
	** Place changes to upgrade IDs below this comment, decrementing
	** the action ID.  These changes must be in _descending order_ by
	** target version, since the last one processed will be the ultimate
	** value retained.  These must be the highest-numbered items in the
	** list, since we want them to execute last.  The minor ID and
	** ASEvers together act as indicators showing that the database
	** is exactly at the target downgrade version.
	*/
	-- Reset minor upgrade ID as appropriate to the target version
	insert #actions values(993, @masterdb, 15020,
		@dbinfo_update_1502_master_sql,
		'Downgrade : Setting master database minor upgrade version.')
	insert #actions values(994, @allbutmasterdb, 15020,
		@dbinfo_update_1502_userdb_sql,
		'Downgrade : Setting user databases minor upgrade version.')
	insert #actions values(995, @alldbs, 15015,
		@dbinfo_update_15015_alldbs_sql,
		'Downgrade : Setting user databases minor upgrade version.')
	insert #actions values(996, @masterdb, 15010,
		@dbinfo_update_1500_master_sql,
		'Downgrade : Setting master database minor upgrade version.')
	insert #actions values(997, @allbutmasterdb, 15010,
		@dbinfo_update_1500_userdb_sql,
		'Downgrade : Setting user databases minor upgrade version.')

	-- Turn on 0x00000020 for dbi_status4 to indicate downgrade happened
	insert #actions values(998, @masterdb, @any15versid,
		@dbinfo_turnon_downgradeneed_sql,
		'Downgrade : Turning on database downgrade indicator.')
	
	-- Reset ASEvers to a value appropriate to the target version
	insert #actions values(999, @alldbs, @any15versid,
		@dbinfo_reset_asevers_sql,
		'Downgrade : Resetting database version indicator.')

	/*
	** MAINTAINERS:  as you add tasks, add them above or below the
	** "Reset minor upgrade ID" items, as appropriate.  Add no items
	** beyond value 999.
	*/


	/* A cursor to traverse sysdatabases */
	declare sysdbc cursor for 
	select dbid from #sysdatabases
	
	/* 
	** This cursor will traverse the #actions database and the
	** actions will be performed based on the from and to versions:
	** perform the action if [toversion is "any"] or [toversion
	** less than current AND greater or equal to target].
	*/
	declare actc cursor for 
	select actionid, dbid, action, errorlog_msg
	from #actions
	where (toversion = @any15versid)
	   or ((toversion < @fromversid) and (toversion >= @toversid))
	order by actionid

	dbcc printolog('Starting downgrading ASE.')

	open actc
	fetch actc into @actionid, @whatdbid, @sqlbuf, @errorlog_msg
	while (@@sqlstatus = 0)
	begin
		if (@verbose = 1)
		begin
			print ''
			print 'Executing downgrade step %1! [%2!] for :', 
			      @actionid, @sqlbuf
		end
		
		/* 
		** Write related downgrade step informational message in 
		** the errorlog.
		*/
		dbcc printolog(@errorlog_msg)

		/* 
		** Loop for each writable database and execute 
		** the command if it is authorized. 
		*/
		open sysdbc
		fetch sysdbc into @dbid
		while (@@sqlstatus = 0)
		begin -- {
			if ((@whatdbid in (@alldbs, @dbid)) or
			    (@whatdbid = @allbutmasterdb and @dbid != @masterdb))
			begin -- {
				select @dbname = db_name(@dbid)
				select @sqlcmd = @sqlbuf
				select @dbnameoffset = patindex('%:DBNAME:%', @sqlcmd)
				while (@dbnameoffset > 0)
				begin
					select @sqlcmd =
						  stuff(@sqlcmd,
							@dbnameoffset, 8,
							@dbname)
					select @dbnameoffset = patindex('%:DBNAME:%',
									@sqlcmd)
				end
				if (@verbose = 1)
				begin
					print '- Database: %1! (dbid: %2!)', 
					      @dbname, @dbid
				end
			
				if (@mark_dbprocs_sql = @sqlcmd)
				begin
					/* 
					** Temporary workaround until DBCC 
					** can be run in exec. 
					*/
					dbcc markprocs(@dbid)
				end
				else
				if (@durability_sql = @sqlcmd)
				begin
					/* 
					** sp_downgrade_durability cannot
					** be run in execute immediate.
					*/
					exec sp_downgrade_durability 'exec'
				end
				else
				if (@sysobjstat3_sql = @sqlcmd)
				begin
					/*
					** sp_downgrade_sysobjects cannot
					** be run in execute immediate.
					*/
					exec sp_downgrade_sysobjects 'exec'
				end
				else
				if (@downgrade_15015_config = @sqlcmd)
				begin
					if (@toversid = 15015)
					begin
						exec (@downgrade_sysconfigures_15015_sql1)
						exec (@downgrade_sysconfigures_15015_sql2)
						exec (@downgrade_sysconfigures_15015_sql3)
						exec (@downgrade_sysconfigures_15015_cmd)
					end
				end
				else
				if (@downgrade_15015_msg = @sqlcmd)
				begin
					if (@toversid = 15015)
					begin
						set nocount on
						exec sp_inst15015msg
						set nocount off
						update master..syslanguages set upgrade = 1501
					end
				end
				else
				if ((@reset_sysservers_srvnetname_len = @sqlcmd) and (@toversid = 15015))
				begin
					/*
					** Skip this downgrade item, as len of sysservers.srvnetname is
					** still 255 in 15.0.1.5.
					*/
					if (@verbose = 1)
					begin
						print ''
						print "  Skip downgrade step %1! for database %2! on downgrading to version %3!", 
							@actionid, @dbname, @toversid
					end
				end
				else
				begin
					exec (@sqlcmd)
				end
			end -- }
			fetch sysdbc into @dbid
		end -- }
		close sysdbc
		
		/* Pick up next downgrade step. */
		fetch actc into @actionid, @whatdbid, @sqlbuf, @errorlog_msg
	end
	close actc

	deallocate cursor actc
	deallocate cursor sysdbc

	dbcc printolog('ASE downgrade completed.')

	return 0
end -- }
go
exec sp_procxmode 'sp_downgrade_sysobjects', 'anymode'
go
grant execute on sp_downgrade_sysobjects to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_downgrade', 'anymode'
go
grant execute on sp_downgrade to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ssladmin')
begin
	drop procedure sp_ssladmin
end
go
print "Installing sp_ssladmin"
go


/* 
** file: ssladmin 
** Administer SSL Certificates
*/

/*
** Messages for "sp_ssladmin"
**
** 17260, "Can't run %1! from within a transaction."
** 
*/
create procedure sp_ssladmin 
	@cmd 	varchar(30) = null,
	@opt1	varchar(16384) = null,
	@opt2	varchar(64) = null
as

declare	@retval	int 	/* return value from ssl_admin() built-in function */
declare @msg 	varchar(255)	/* message variable */

/*
** Establish a version to pass to built-in function.
*/
declare	@vers	int 
select @vers = 0		

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_ssladmin"
        return (1)
end
else
begin
        set chained off
end
set transaction isolation level 1

/* 
**  Check if user has sso role.  proc_role() will do auditing
**  if required and will also print error message if required.
*/
if (proc_role("sso_role") = 0)
        return (1)


/*
**  Begin command processing.
*/

if (@cmd = "addcert") or (@cmd = "dropcert") or (@cmd = "lscert") 
	or (@cmd = "lscipher") or (@cmd = "setcipher")
begin

	/* Process lscert in sproc instead of builtin */
	if (@cmd = "lscert")
	begin
		select certificate_path=comments from master.dbo.sysattributes
			where class=15 

		select @retval = @@error
	end
	else
	begin
		/* Process parts of cipher commands in sproc */
		if (@cmd = "lscipher") or (@cmd = "setcipher")
		begin

			select @retval = ssl_admin (@cmd, @opt1, @opt2, @vers)
			if (@retval = 0)
			begin
				/* 
				** attrib is the cipher id
				** object is the default order
				** int_value is the preferred order
				** char_value is the cipher name
				*/
				if (@cmd = "lscipher") 
				begin
					select 
						'Cipher Suite Name'=convert(varchar(64),char_value), 
						'Preference'=int_value 
						from sysattributes 
						where class=24 and object > 0
						order by object
				end
				else
				begin /* "setcipher" */
					/* RESOLVE: add new sproc messages */
					print "The following cipher suites and order of preference are set for SSL connections:"
					select 
						'Cipher Suite Name'=convert(varchar(64),char_value), 
						'Preference'=int_value 
						from sysattributes 
						where class=24 and int_value > 0
						order by int_value
				end
			end

		end
		else
		begin
			select @retval = ssl_admin (@cmd, @opt1, @opt2, @vers)
		end
	end

	if (@retval != 0)
	begin
       		return(1)
	end
end
else
begin
	print "sp_ssladmin Usage: sp_ssladmin command [, option1 [, option2]]"
	print "sp_ssladmin commands:"
	print "sp_ssladmin 'addcert', 'certificatepath', 'password'"
	print "sp_ssladmin 'dropcert', 'certificatepath'"
	print "sp_ssladmin 'lscert'"
	print "sp_ssladmin 'setcipher', { 'FIPS' | 'Strong' | 'Weak' | 'All' | quoted_list_of_ciphersuites "
	print "sp_ssladmin 'lscipher'"
	print "sp_ssladmin 'help'"
end



return (0)
go
go
exec sp_procxmode 'sp_ssladmin', 'anymode'
go
grant execute on sp_ssladmin to sso_role
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ldapadmin')
begin
	drop procedure sp_ldapadmin
end
go
print "Installing sp_ldapadmin"
go


/* 
** file: ldapadmin 
** Administer LDAP User Authentication
**
** Note: sp_ldapadmin uses the ssl_admin() built-in function to
** transition into ASE executable from this stored procedure. 
**
** amadsen January 2003
**
*/

/*
** Messages for "sp_ldapadmin"
**
** 17260, "Can't run %1! from within a transaction."
** 
*/
create procedure sp_ldapadmin
	@cmd 	varchar(4096) = null,
	@opt1	varchar(4096) = null,
	@opt2	varchar(4096) = null
as

/*
** Parameters are nominally allowed very large lengths here.
** However, lengths are checked in the builtin function to detect and
** report appropriate errors.  Otherwise parameters would be silently
** truncated by this stored procedure.
*/

/* return value from ssl_admin() built-in function */
declare	@retval	int 

/* local variables for URL values and access account DN */
declare @primaryURL		varchar(255)
declare @secondaryURL		varchar(255)
declare @dnlookupURL		varchar(255)
declare @secdnlookupURL         varchar(255)
declare @accessacctDN		varchar(255)
declare @secaccessacctDN        varchar(255)

declare @isLDAPSSupported	int
declare @primaryTLS		int
declare @secondaryTLS		int
declare @primarystate           int
declare @secondarystate         int
declare @primarystatus          varchar(10)
declare @secondarystatus        varchar(10)

declare @timeoutvalue	int
declare @maxldapuantvthrds	int
declare @maxntvthrds		int
declare @dumpthrds		int
declare @true			varchar(10)
declare @false			varchar(10)
declare	@abandon		int
/* Maximum LDAPUA descriptors per engine */
declare @maxldapuadesc		int 
/*
** Log interval that determines frequency of sending messages to error log.
** Expressed in minutes.
*/ 
declare @log_interval		int
/* Number of times to retry LDAPUA */
declare @numretries		int
declare @failback_interval	int

declare @valid_opt1 		varchar(4096) 


/*
** Establish a version to pass to built-in function.
*/
declare	@vers	int 
select @vers = 0		
select @timeoutvalue = NULL
select @maxldapuantvthrds = NULL
select @abandon = NULL
select @primarystate = NULL
select @secondarystate = NULL
select @maxldapuadesc = NULL
select @log_interval = NULL
select @numretries = NULL

select @valid_opt1 = @opt1


/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_ldapadmin"
        return (1)
end
else
begin
        set chained off
end
set transaction isolation level 1

/* 
**  Check if user has sso role.  proc_role() will do auditing
**  if required and will also print error message if required.
*/
if (proc_role("sso_role") = 0)
        return (1)

select @isLDAPSSupported = ssl_admin ("is_ldaps_supported", "", "", @vers)

/*
**  Begin command processing.
*/

if (@cmd = "set_primary_url") or (@cmd = "set_secondary_url") or 
	(@cmd = "set_dn_lookup_url")  or (@cmd = "set_access_acct") or
	(@cmd = "set_secondary_dn_lookup_url") or
	(@cmd = "suspend") or (@cmd = "activate") or
	(@cmd = "set_secondary_access_acct") or
	(@cmd = "list_access_acct") or
	(@cmd = "list_urls")  or (@cmd = "check_url") or 
	(@cmd = "check_login") or (@cmd is NULL) or
	(@cmd = "list") or
	(@cmd = "set_timeout") or 
	(@cmd = "set_max_ldapua_native_threads") or
	(@cmd = "set_abandon_ldapua_when_full") or
	(@cmd = "set_max_ldapua_desc") or
	(@cmd = "set_log_interval") or
	(@cmd = "set_num_retries") or
	(@cmd = "starttls_on_primary") or
	(@cmd = "starttls_on_secondary") or
	(@cmd = "set_failback_interval") or
	(@cmd = "reinit_descriptors")
begin

	/* Process list, NULL, and list_urls command in sproc instead of builtin */
	if (@cmd = "list_urls") or (@cmd = "list") or (@cmd is NULL)
	begin
		 select @primaryURL = comments, @primarystate = int_value
		 	from master.dbo.sysattributes
			 where class=17 and attribute=0

		 select @secondaryURL = comments, @secondarystate = int_value
		 	from master.dbo.sysattributes
			 where class=17 and attribute=1

		 select @dnlookupURL = comments from master.dbo.sysattributes
			 where class=17 and attribute=2

		select @secdnlookupURL = comments from master.dbo.sysattributes
			 where class=17 and attribute=7

		select @primaryTLS = int_value from master.dbo.sysattributes
			where class=17 and attribute=12

		select @secondaryTLS = int_value from master.dbo.sysattributes
			where class=17 and attribute=13

		if (@cmd = "list_urls")
		begin
			print "Primary URL:                   '%1!'", @primaryURL
			print "Secondary URL:                 '%1!'", @secondaryURL
			print "Distinguished Name Lookup URL: '%1!'", @dnlookupURL
			print "Secondary Distinguished Name Lookup URL: '%1!'", @secdnlookupURL
			return (0)
		end
		/* End Processing of list_urls , quit */

		/* Process 'list' and 'NULL' commands. Both commands produce 
		** the same output .
		*/
		select @accessacctDN = comments
			from master.dbo.sysattributes
			where class=17 and attribute=3

		select @timeoutvalue = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=4

		select @maxldapuantvthrds = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=5

		select @abandon = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=6

		select @secaccessacctDN = comments
			from master.dbo.sysattributes
			where class=17 and attribute=8

		select @maxldapuadesc = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=9

		select @log_interval = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=10

		select @numretries = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=11

		select @failback_interval = int_value from 
			master.dbo.sysattributes
		 	where class=17 and attribute=14

		
		/******* Start LDAP URL and state information *********/

		select @primarystatus =
		case @primarystate
			when 1 then "RESET"
			when 2 then "READY"
			when 3 then "ACTIVE"
			when 4 then "FAILED"
			when 5 then "SUSPENDED"
			else "NOT SET"
		end

		if (@primaryURL != NULL and @primarystate is NULL)
			select @primarystatus = "READY"

		select @secondarystatus =
		case @secondarystate
			when 1 then "RESET"
			when 2 then "READY"
			when 3 then "ACTIVE"
			when 4 then "FAILED"
			when 5 then "SUSPENDED"
			else "NOT SET"
		end

		if (@secondaryURL != NULL and @secondarystate is NULL)
			select @secondarystatus = "READY"


		print "Primary:"
		print "    URL:                 '%1!'", @primaryURL
		print "    DN Lookup URL:       '%1!'", @dnlookupURL
		print "    Access Account:      '%1!'", @accessacctDN
		if (@primarystate = 2 or @primarystate = 3)
			print "    Active:              'TRUE'"
		else
			print "    Active:              'FALSE'"
		print "    Status:              '%1!'", @primarystatus
		if (@isLDAPSSupported = 1)
		begin
			if (@primaryTLS = 1)
				print "    StartTLS on Primary LDAP URL: 'TRUE'"
			else
				print "    StartTLS on Primary LDAP URL: 'FALSE'"
		end
		print "Secondary:"
		print "    URL:                 '%1!'", @secondaryURL
		print "    DN Lookup URL:       '%1!'", @secdnlookupURL
		print "    Access Account:      '%1!'", @secaccessacctDN
		if (@secondarystate = 2 or @secondarystate = 3)
			print "    Active:              'TRUE'"
		else
			print "    Active:              'FALSE'"
		print "    Status:              '%1!'", @secondarystatus
		if (@isLDAPSSupported = 1)
		begin
			if (@secondaryTLS = 1)
				print "    StartTLS on Secondary LDAP URL: 'TRUE'"
			else
				print "    StartTLS on Secondary LDAP URL: 'FALSE'"
		end

		/******* End LDAP URL state information *********/



		/* Now print timeout and LDAPUA native thread information */

		select @retval = @@error


		if (@timeoutvalue = NULL)
		begin
			/* Default value */
			select @timeoutvalue = -1
		end

		if (@failback_interval = NULL)
		begin
			/* Use default failback time if nothing is set */
			select @failback_interval = -1
		end


		/* 
		** If there is no row for timeout in sysattributes then
		** the default -1(10000) milliseconds value is listed.
		** When the default timeout value is changed, this
		** listing also needs to be changed.
		*/
		if (@timeoutvalue = -1)
			print "Timeout value:           '%1!'(10000) milliseconds",
				@timeoutvalue
		else
			print "Timeout value:           '%1!' milliseconds", 
				@timeoutvalue

		if (@log_interval = NULL)
		begin
			select @log_interval = 3
		end
		print "Log interval:		 '%1!' minutes", 
			@log_interval

		if (@numretries = NULL)
		begin
			select @numretries = 3
		end
		print "Number of retries:	 '%1!'", 
			@numretries

		/* display default value when row not found.*/
		if (@maxldapuantvthrds = NULL)
		begin
			/* 
			** Default value: Maximum ldapua native threads per engine
			** is sum of max native threads per engine and the number
			** of dump threads.
			*/
			select @maxntvthrds = value from 
				master.dbo.sysconfigures where 
				name = 'max native threads per engine'
			select @dumpthrds = value from
				master.dbo.sysconfigures where
				name = 'number of dump threads'
			select @maxldapuantvthrds = @maxntvthrds -
					@dumpthrds
		end
		print "Maximum LDAPUA native threads per Engine: '%1!'", 
				@maxldapuantvthrds

		if (@maxldapuadesc = NULL)
		begin
			select @maxldapuadesc = 20
		end
		print "Maximum LDAPUA descriptors per Engine: '%1!'",
			@maxldapuadesc

		/* display default value when row not found.*/
		if (@abandon = NULL)
		begin
			select @abandon = 0
		end
		if (@abandon = 1)
		begin
			/* 17431, "true" */
			exec sp_getmessage 17431, @true  out
		end
		else
		begin
			/* 17432, "false" */
			exec sp_getmessage 17432, @true  out
		end
		print "Abandon LDAP user authentication when full: '%1!'", @true

		if (@failback_interval = -1)
			print "Failback interval:	 '%1!'(15) minutes", @failback_interval
		else
		begin
			if (@failback_interval = 0)
				print "Failback interval:	 '%1!'(infinite) minutes", @failback_interval
			else
				print "Failback interval:	 '%1!' minutes", @failback_interval
			end
	end
	else
	begin
		if (@cmd = "list_access_acct")
		begin
			select @accessacctDN = comments
				 from master.dbo.sysattributes
				 where class=17 and attribute=3

			select @secaccessacctDN = comments
			 	from master.dbo.sysattributes
				where class=17 and attribute=8

			 select @retval = @@error

			print "Access Account DN:     '%1!'", @accessacctDN
			print "Secondary Access Account DN:     '%1!'", @secaccessacctDN

		end
		else
		begin
			if (@cmd = "suspend") or (@cmd = "activate") or
				(@cmd = "set_timeout") or 
				(@cmd = "set_max_ldapua_native_threads") or
				(@cmd = "set_abandon_ldapua_when_full") or
				(@cmd = "set_max_ldapua_desc") or
				(@cmd = "set_log_interval") or
				(@cmd = "set_num_retries") or
				(@cmd = "starttls_on_primary") or
				(@cmd = "starttls_on_secondary") or
				(@cmd = "set_failback_interval")
			begin
				select @valid_opt1 = rtrim(ltrim(@opt1))
			end
			/* validate {true|false} valid_opt1  */  
			if (@cmd = "set_abandon_ldapua_when_full") or
			   (@cmd = "starttls_on_primary") or
			   (@cmd = "starttls_on_secondary")
			begin
				/* 17431, "true" */
				exec sp_getmessage 17431, @true  out

				/* 17432, "false" */
				exec sp_getmessage 17432, @false  out
				if ((@valid_opt1 != NULL) 
				and ((lower(@valid_opt1) not in ("true", @true))
				and (lower(@valid_opt1) not in ("false",@false))))
				begin
					/*
					** 19022, 
					**"The '%1!' parameter must be 'true' or 'false'."
					*/
					raiserror 19022, @valid_opt1
					return 1
				end
			end
			/* command actions handled in builtin */
			select @retval = ssl_admin (@cmd, @valid_opt1, @opt2, @vers)
		end
	end

	if (@retval != 0)
	begin
       		return (1)
	end
end
else
begin
	
	print "sp_ldapadmin Usage: sp_ldapadmin command [, option1 [, option2]]"
	print "sp_ldapadmin commands:"
	print "sp_ldapadmin 'set_primary_url', 'url'"
	print "sp_ldapadmin 'set_secondary_url', 'url'"
	print "sp_ldapadmin 'set_dn_lookup_url', 'url'"
	print "sp_ldapadmin 'set_secondary_dn_lookup_url', 'url'"
	print "sp_ldapadmin 'set_access_acct', 'distinguished name', 'password'"
	print "sp_ldapadmin 'set_secondary_access_acct', 'distinguished name', 'password'"
	print "sp_ldapadmin 'suspend', {'primary' | 'secondary'}"
	print "sp_ldapadmin 'activate', {'primary' | 'secondary'}"
	print "sp_ldapadmin 'list'"
	print "sp_ldapadmin 'list_urls'"
	print "sp_ldapadmin 'list_access_acct'"
	print "sp_ldapadmin 'check_url', 'url'"
	print "sp_ldapadmin 'check_login', 'name'"
	print "sp_ldapadmin 'set_timeout', timeout_in_milli_seconds"
	print "sp_ldapadmin 'set_log_interval', log_interval in minutes"
	print "sp_ldapadmin 'set_num_retries', num_retries"
	print "sp_ldapadmin 'set_max_ldapua_native_threads', max_ldapua_native_threads"
	print "sp_ldapadmin 'set_max_ldapua_desc', max_ldapua_desc"
	print "sp_ldapadmin 'set_abandon_ldapua_when_full', {true|false}"
	if (@isLDAPSSupported = 1)
	begin
		print "sp_ldapadmin 'starttls_on_primary', {true|false}"
		print "sp_ldapadmin 'starttls_on_secondary', {true|false}"
	end
	print "sp_ldapadmin 'set_failback_interval', time_in_minutes"
	print "sp_ldapadmin 'reinit_descriptors'"
	print "sp_ldapadmin 'help'"

end



return (0)
go
go
exec sp_procxmode 'sp_ldapadmin', 'anymode'
go
grant execute on sp_ldapadmin to sso_role
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_escapeliteralforlike')
begin
	drop procedure sp_ijdbc_escapeliteralforlike
end
go
print "Installing sp_ijdbc_escapeliteralforlike"
go

/*
**  sp_ijdbc_escapeliteralforlike
*/


/*
** This is a utility procedure which takes an input string
** and places the escape character '\' before any symbol
** which needs to be a literal when used in a LIKE clause.
**
*/


create procedure sp_ijdbc_escapeliteralforlike 
		@pString varchar(255) output
as
    declare @newString    varchar(255)
    declare @validEscapes varchar(255)
    declare @escapeChar   varchar(10)
    declare @pIndex       int
    declare @pLength      int
    declare @curChar      char(1)
    declare @escapeIndex  int
    declare @escapeLength int
    declare @boolEscapeIt int

    select @pLength = char_length(@pString)
    if (@pString is null) or (@pLength = 0)
    begin
        return
    end

    /*
    ** we will use the backslash as our escape 
    ** character
    */
    select @escapeChar = '\'
    
    /* 
    ** valid escape characters
    */
    select @validEscapes = '%_\[]'
    select @escapeLength = char_length(@validEscapes)

    /* start at the beginning of the string */
    select @pIndex = 1
    select @newString = ''

    while(@pIndex <= @pLength)
    begin
        /*
        ** get the next character of the string
        */
        select @curChar = substring(@pString, @pIndex, 1)
        
        /*
        ** loop through all of the escape characters and
        ** see if the character needs to be escaped
        */
        select @escapeIndex = 1
        select @boolEscapeIt = 0
        while(@escapeIndex <= @escapeLength)
        begin
            /* see if this is a match */
            if (substring(@validEscapes, @escapeIndex, 1) = 
                @curChar)
            begin
                select @boolEscapeIt = 1
                break
            end
            /* move on to the next escape character */
            select @escapeIndex = @escapeIndex + 1
        end
        
        /* build the string */
        if (@boolEscapeIt = 1)
        begin
            select @newString = @newString + @escapeChar + @curChar
        end
        else
        begin
            select @newString = @newString + @curChar
        end

        /* go on to the next character in our source string */
        select @pIndex = @pIndex + 1
    end
        
    /* return to new string to the caller */
    select @pString = ltrim(rtrim(@newString))
    return 0
go
exec sp_procxmode 'sp_ijdbc_escapeliteralforlike', 'anymode'
go
grant execute on sp_ijdbc_escapeliteralforlike to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_datatype_info')
begin
	drop procedure sp_ijdbc_datatype_info
end
go
print "Installing sp_ijdbc_datatype_info"
go


create table #tmp_datatype_info (
        TYPE_NAME          varchar(257)  null,
        DATA_TYPE          smallint     null,
        PRECISION          int          null,
        LITERAL_PREFIX     varchar(32)  null,
        LITERAL_SUFFIX     varchar(32)  null,
        CREATE_PARAMS      varchar(32)  null,
        NULLABLE           smallint     null,
        CASE_SENSITIVE     smallint     null,
        SEARCHABLE         smallint     null,
        UNSIGNED_ATTRIBUTE smallint     null,
        FIXED_PREC_SCALE   smallint     null,
        AUTO_INCREMENT     smallint     null,
        LOCAL_TYPE_NAME    varchar(128) null,
        MINIMUM_SCALE      smallint     null,
        MAXIMUM_SCALE      smallint     null,
        SQL_DATA_TYPE      smallint     null,
        SQL_DATETIME_SUB   smallint     null,
        NUM_PREC_RADIX     smallint     null,
        INTERVAL_PRECISION smallint     null
)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_datatype_info
*/

create procedure sp_ijdbc_datatype_info
as

if @@trancount = 0
begin
        set chained off
end

set transaction isolation level 1

delete #tmp_datatype_info

insert #tmp_datatype_info 
select  /* Real SQL Server data types */
      t.name as TYPE_NAME,
      d.data_type as DATA_TYPE,
      isnull(d.data_precision, convert(int,t.length)) as 'PRECISION',
      d.literal_prefix as LITERAL_PREFIX,
      d.literal_suffix as LITERAL_SUFFIX,
      e.create_params as CREATE_PARAMS,
      d.nullable as NULLABLE,
      d.case_sensitive as CASE_SENSITIVE,
      d.searchable as SEARCHABLE,
      d.unsigned_attribute as UNSIGNED_ATTRIBUTE,
      d.money as FIXED_PREC_SCALE,
      d.auto_increment as AUTO_INCREMENT,
      d.local_type_name as LOCAL_TYPE_NAME,
      d.minimum_scale as MINIMUM_SCALE,
      d.maximum_scale as MAXIMUM_SCALE,
      d.sql_data_type as SQL_DATA_TYPE,
      d.sql_datetime_sub as SQL_DATETIME_SUB,
      d.num_prec_radix as NUM_PREC_RADIX,
      d.interval_precision as INTERVAL_PRECISION
from  sybsystemprocs.dbo.spt_jdatatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type and t.usertype *= e.user_type
     /* restrict results to 'real' datatypes, exclude float*/
      and t.name not in ('nchar','nvarchar','sysname','longsysname',
		'timestamp', 'float', 'datetimn','floatn','intn','moneyn')
      and t.usertype < 100    /* No user defined types */
UNION
select  /* SQL Server user data types */
      t.name, d.data_type,
      isnull(d.data_precision, convert(int,t.length)) as 'PRECISION',
      d.literal_prefix, d.literal_suffix, e.create_params,      d.nullable,
      d.case_sensitive, d.searchable,     d.unsigned_attribute, d.money,
      d.auto_increment, t.name,           d.minimum_scale,      
      d.maximum_scale,  d.sql_data_type,  d.sql_datetime_sub,
      d.num_prec_radix, d.interval_precision
from  sybsystemprocs.dbo.spt_jdatatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type and t.usertype *= e.user_type
/* Restrict to user defined types (value > 100)  and Sybase user defined 
** types (listed)*/
      and (t.name in ('nchar','nvarchar', 'sysname','longsysname')
      or t.usertype >= 100)      /* User defined types */
UNION                                                  
select  /* ADD double precision which is floatn internally*/
      'double precision',8,                15,
      d.literal_prefix,  d.literal_suffix, e.create_params,      d.nullable,
      d.case_sensitive,  d.searchable,     d.unsigned_attribute, d.money,
      d.auto_increment, 'double precision',d.minimum_scale,      
      d.maximum_scale,   d.sql_data_type,  d.sql_datetime_sub,
      d.num_prec_radix,  d.interval_precision
from  sybsystemprocs.dbo.spt_jdatatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type   and t.usertype *= e.user_type
      and t.name = 'floatn' and t.usertype < 100 
UNION   /* ADD float now */
select  
      'float',           8,                8,
      d.literal_prefix,  d.literal_suffix, e.create_params,      d.nullable,
      d.case_sensitive,  d.searchable,     d.unsigned_attribute, d.money,
      d.auto_increment, 'float',           d.minimum_scale,      
      d.maximum_scale,   d.sql_data_type,  d.sql_datetime_sub,
      d.num_prec_radix,  d.interval_precision
from  sybsystemprocs.dbo.spt_jdatatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type   and t.usertype *= e.user_type
      and t.name = 'float' and t.usertype < 100 
order by d.data_type, t.name

return(0) 
go
exec sp_procxmode 'sp_ijdbc_datatype_info', 'anymode'
go
grant execute on sp_ijdbc_datatype_info to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_columns')
begin
	drop procedure sp_ijdbc_columns
end
go
print "Installing sp_ijdbc_columns"
go


create table #tmp_columns (TABLE_CAT varchar(30) null,
                TABLE_SCHEM varchar(30) null, TABLE_NAME varchar(255) null,
                COLUMN_NAME varchar(255) null, DATA_TYPE int null,
                TYPE_NAME varchar(255) null, COLUMN_SIZE int null,
                BUFFER_LENGTH int null, DECIMAL_DIGITS int null,
                NUM_PREC_RADIX smallint null, NULLABLE smallint null,
                REMARKS varchar(254) null, COLUMN_DEF varchar(30) null,
                SQL_DATA_TYPE int null, SQL_DATETIME_SUB int null,
                CHAR_OCTET_LENGTH int null, ORDINAL_POSITION smallint null,
                IS_NULLABLE varchar(10) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_columns
*/

/* create a 1-off version of sp_ijdbc_columns that has the additional
** columns required for ODBC 2.0 and more columns required by
** JDBC (from ODBC 3.0?).
*/

/* This is the version for servers which support UNION */

CREATE PROCEDURE sp_ijdbc_columns (
    @table_name         varchar(257),
    @table_owner        varchar(32) = null,
    @table_qualifier    varchar(32) = null,
    @column_name        varchar(257) = null )
AS
/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_COLS */
    declare @msg    		  varchar(250)
    declare @full_table_name  char(290)
    declare @table_id         int
    declare @char_bin_types   varchar(30)

    if @@trancount > 0
    begin
        /*
        ** 17260, 'Can't run %1! from within a transaction.'
        */
        exec sp_getmessage 17260, @msg output
        print @msg, 'sp_ijdbc_columns'
        return (1)
    end
    else
    begin
        set chained off
    end

    set transaction isolation level 1
    
    /* character and binary datatypes */
    select @char_bin_types =
        char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

    if @column_name is null select @column_name = '%'
    
    if @table_qualifier is not null
    begin
        if db_name() != @table_qualifier
        begin	/* 
            ** If qualifier doesn't match current database: 18039
            ** Table qualifier must be name of current database
            */
            exec sp_getmessage 18039, @msg output
            raiserror 18039 @msg
            return (1)
        end
    end
    
    if @table_name is null
    begin	/*	If table name not supplied, match all */
        select @table_name = '%'
    end
    
    if @table_owner is null
    begin	/* If unqualified table name */
        SELECT @full_table_name = @table_name
        select @table_owner = '%'
    end
    else
    begin	/* Qualified table name */
        SELECT @full_table_name = @table_owner + '.' + @table_name
    end
  

    delete #tmp_columns

    /* Get Object ID */
    SELECT @table_id = object_id(@full_table_name)
       /* If the table name parameter is valid, get the information */ 
    if ((charindex('%',@full_table_name) = 0) and
        (charindex('_',@full_table_name) = 0)  and
        (@table_id != 0))
    begin 

	INSERT #tmp_columns
	
        SELECT	/* INTn, FLOATn, DATETIMEn and MONEYn types */
            TABLE_CAT = DB_NAME(),
            TABLE_SCHEM = USER_NAME(o.uid),
            TABLE_NAME = o.name,
            COLUMN_NAME = c.name,
            DATA_TYPE = d.data_type+convert(smallint,
                        isnull(d.aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60)),
            TYPE_NAME = isnull(xtname, rtrim(substring(d.type_name,
                        1+isnull(d.aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60), 13))),
            COLUMN_SIZE = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                             convert(int, c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            BUFFER_LENGTH = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                             convert(int, c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),  
            DECIMAL_DIGITS = isnull(convert(smallint, c.scale), 
                       convert(smallint, d.numeric_scale)) +
                        convert(smallint, isnull(d.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60)),
            NUM_PREC_RADIX = d.numeric_radix,
            NULLABLE =	/* set nullability from status flag */
                convert(smallint, convert(bit, c.status&8)),
            REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
            COLUMN_DEF = NULL,
            SQL_DATA_TYPE = isnull(d.sql_data_type,
                      d.data_type+convert(smallint,
                      isnull(d.aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(d.ss_dtype%35+1)+2-8/c.length,1))
                      -60))),
            SQL_DATETIME_SUB = NULL,
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */
            CHAR_OCTET_LENGTH = 
                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, 
                    substring('0111111', 
                        charindex(convert(char, c.type), @char_bin_types)+1, 1)) * 
                /* calculate the precision */
                isnull(convert(int, c.prec),
                    isnull(convert(int, d.data_precision),
                        convert(int,c.length)))
                    +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            ORDINAL_POSITION = c.colid,
            IS_NULLABLE = rtrim(substring('NO YES', convert(smallint, convert(bit, c.status&8)*3)+1, 3))
    
        FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdatatype_info d,
            sysxtypes x,
            systypes t
        WHERE
            o.id = @table_id
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106 
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            AND t.type = d.ss_dtype
	    and c.xtype *= x.xtid 
            AND o.type != 'P'
            AND c.name like @column_name ESCAPE '\'
            AND d.ss_dtype IN (111, 109, 38, 110)	/* Just *N types */
            AND c.usertype < 100
        UNION
        SELECT /* All other types including user data types */
            TABLE_CAT = DB_NAME(),
            TABLE_SCHEM = USER_NAME(o.uid),
            TABLE_NAME = o.name,
            COLUMN_NAME = c.name,
            DATA_TYPE = d.data_type+convert(smallint,
                        isnull(d.aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60)),
            TYPE_NAME = isnull(xtname, rtrim(substring(d.type_name,
                        1+isnull(d.aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60), 13))),       
            COLUMN_SIZE = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                         convert(int,c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            BUFFER_LENGTH = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                             convert(int, c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),  
            DECIMAL_DIGITS = isnull(convert(smallint, c.scale),
                       convert(smallint, d.numeric_scale)) +
                        convert(smallint, isnull(d.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60)),
            NUM_PREC_RADIX = d.numeric_radix,
            NULLABLE =	/* set nullability from status flag */
                convert(smallint, convert(bit, c.status&8)),
            REMARKS  = convert(varchar(254),null),
            COLUMN_DEF = NULL,
            SQL_DATA_TYPE = isnull(d.sql_data_type,
                      d.data_type+convert(smallint,
                      isnull(d.aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(d.ss_dtype%35+1)+2-8/c.length,1))
                      -60))),
            SQL_DATETIME_SUB = NULL,
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */
            CHAR_OCTET_LENGTH = 
                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, substring('0111111', 
                    charindex(convert(char, c.type), @char_bin_types)+1, 1)) * 
                /* calculate the precision */
                isnull(convert(int, c.prec),
                    isnull(convert(int, d.data_precision),
                        convert(int,c.length)))
                    +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            ORDINAL_POSITION = c.colid,
            IS_NULLABLE = rtrim(substring('NO YES', convert(smallint, convert(bit, c.status&8)*3)+1, 3))
    
        FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdatatype_info d,
	    sysxtypes x,
            systypes t
        WHERE
            o.id = @table_id
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106 
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            /*
            ** We need a equality join with 
            ** sybsystemprocs.dbo.spt_jdatatype_info here so that
            ** there is only one qualified row returned from 
            ** sybsystemprocs.dbo.spt_jdatatype_info, thus avoiding
            ** duplicates.
            */
            AND t.type = d.ss_dtype
	    and c.xtype *= x.xtid 
            AND o.type != 'P'
            AND c.name like @column_name ESCAPE '\'
            AND (d.ss_dtype NOT IN (111, 109, 38, 110) /* No *N types */
                OR c.usertype >= 100) /* User defined types */
        ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION
    end
    else
    begin

	INSERT #tmp_columns

        SELECT	/* INTn, FLOATn, DATETIMEn and MONEYn types */
            TABLE_CAT = DB_NAME(),
            TABLE_SCHEM = USER_NAME(o.uid),
            TABLE_NAME = o.name,
            COLUMN_NAME = c.name,
            DATA_TYPE = d.data_type+convert(smallint,
                        isnull(d.aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60)),
            TYPE_NAME = isnull(xtname, rtrim(substring(d.type_name,
                        1+isnull(d.aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60), 13))),       
            COLUMN_SIZE = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                             convert(int, c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            BUFFER_LENGTH = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                             convert(int, c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),  
            DECIMAL_DIGITS = isnull(convert(smallint, c.scale), 
                       convert(smallint, d.numeric_scale)) +
                        convert(smallint, isnull(d.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60)),
            NUM_PREC_RADIX = d.numeric_radix,
            NULLABLE =	/* set nullability from status flag */
                convert(smallint, convert(bit, c.status&8)),
            REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
            COLUMN_DEF = NULL,
            SQL_DATA_TYPE = isnull(d.sql_data_type,
                      d.data_type+convert(smallint,
                      isnull(d.aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(d.ss_dtype%35+1)+2-8/c.length,1))
                      -60))),
            SQL_DATETIME_SUB = NULL,
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */
            CHAR_OCTET_LENGTH = 
                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, 
                    substring('0111111', 
                        charindex(convert(char, c.type), @char_bin_types)+1, 1)) * 
                /* calculate the precision */
                isnull(convert(int, c.prec),
                    isnull(convert(int, d.data_precision),
                        convert(int,c.length)))
                    +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            ORDINAL_POSITION = c.colid,
            IS_NULLABLE = rtrim(substring('NO YES', convert(smallint, convert(bit, c.status&8)*3)+1, 3))
    
        FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdatatype_info d,
	    sysxtypes x,
            systypes t
        WHERE
            o.name like @table_name ESCAPE '\'
            AND user_name(o.uid) like @table_owner ESCAPE '\'
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106 
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            AND t.type = d.ss_dtype
            AND o.type != 'P'
	    and c.xtype *= x.xtid 
            AND c.name like @column_name ESCAPE '\'
            AND d.ss_dtype IN (111, 109, 38, 110)	/* Just *N types */
            AND c.usertype < 100
        UNION
        SELECT /* All other types including user data types */
            TABLE_CAT = DB_NAME(),
            TABLE_SCHEM = USER_NAME(o.uid),
            TABLE_NAME = o.name,
            COLUMN_NAME = c.name,
            DATA_TYPE = d.data_type+convert(smallint,
                        isnull(d.aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60)),
            TYPE_NAME = isnull(xtname, rtrim(substring(d.type_name,
                        1+isnull(d.aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60), 13))),       
            COLUMN_SIZE = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                         convert(int,c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            BUFFER_LENGTH = isnull(convert(int, c.prec),
                      isnull(convert(int, d.data_precision),
                             convert(int, c.length)))
                        +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),  
            DECIMAL_DIGITS = isnull(convert(smallint, c.scale),
                       convert(smallint, d.numeric_scale)) +
                        convert(smallint, isnull(d.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(d.ss_dtype%35+1)+2-8/c.length,
                        1))-60)),
            NUM_PREC_RADIX = d.numeric_radix,
            NULLABLE =	/* set nullability from status flag */
                convert(smallint, convert(bit, c.status&8)),
            REMARKS  = convert(varchar(254),null),
            COLUMN_DEF = NULL,
            SQL_DATA_TYPE = isnull(d.sql_data_type,
                      d.data_type+convert(smallint,
                      isnull(d.aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(d.ss_dtype%35+1)+2-8/c.length,1))
                      -60))),
            SQL_DATETIME_SUB = NULL,
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */
            CHAR_OCTET_LENGTH = 
                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, 
                    substring('0111111', 
                        charindex(convert(char, c.type), @char_bin_types)+1, 1)) * 
                /* calculate the precision */
                isnull(convert(int, c.prec),
                    isnull(convert(int, d.data_precision),
                        convert(int,c.length)))
                    +isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
            ORDINAL_POSITION = c.colid,
            IS_NULLABLE = rtrim(substring('NO YES', convert(smallint, convert(bit, c.status&8)*3)+1, 3))
    
        FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdatatype_info d,
	    sysxtypes x,
            systypes t
        WHERE
            o.name like @table_name ESCAPE '\'
            AND user_name(o.uid) like @table_owner ESCAPE '\'
	    and c.xtype *= x.xtid 
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106 
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            /*
            ** We need a equality join with 
            ** sybsystemprocs.dbo.spt_jdatatype_info here so that
            ** there is only one qualified row returned from 
            ** sybsystemprocs.dbo.spt_jdatatype_info, thus avoiding
            ** duplicates.
            */
            AND t.type = d.ss_dtype
            AND o.type != 'P'
            AND c.name like @column_name ESCAPE '\'
            AND (d.ss_dtype NOT IN (111, 109, 38, 110) /* No *N types */
                OR c.usertype >= 100) /* User defined types */
        ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION
    end           
    
    return(0)
go
exec sp_procxmode 'sp_ijdbc_columns', 'anymode'
go
grant execute on sp_ijdbc_columns to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_tables')
begin
	drop procedure sp_ijdbc_tables
end
go
print "Installing sp_ijdbc_tables"
go


create table #tmp_tables ( 
        TABLE_CAT  varchar(32) null,
        TABLE_SCHEM varchar(32) null,
        TABLE_NAME varchar(257) null,
        TABLE_TYPE varchar(32) null,
        REMARKS varchar(254) null)

go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

create procedure sp_ijdbc_tables
    @table_name       varchar(257)  = null,
    @table_owner      varchar(32)  = null,
    @table_qualifier  varchar(32)  = null,
    @table_type       varchar(100) = null
as
    declare @msg varchar(90)
    declare @searchstr varchar(255)

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

    /* temp table */
    if (@table_name like '#%' and
       db_name() != db_name(tempdb_id()))
    begin
        /*
        ** Can return data about temp. tables only from your temporary db
        */
        exec sp_getmessage 17676, @msg out
        raiserror 17676 @msg
        return(1)
    end
        if @table_qualifier is not null
        begin
            if db_name() != @table_qualifier
            begin
            exec sp_getmessage 18039, @msg out
            raiserror 18039 @msg
            return 1
        end
    end

    if @table_name is null select @table_name = '%'
    if @table_owner is null select @table_owner = '%'

    select @searchstr = ''
    if (patindex('%''SYSTEM%',upper(@table_type)) > 0)
        select @searchstr = @searchstr + 'S'

    if (patindex('%''TABLE''%',upper(@table_type)) > 0)
        select @searchstr = @searchstr +'U'
    
    if (patindex('%''VIEW''%',upper(@table_type)) > 0) 
        select @searchstr = @searchstr +'V' 
    
    if @table_type is null 
        select @searchstr = 'SUV'
    if ((@table_type is not null) and (@searchstr=''))
    begin
        exec sp_getmessage 17301, @msg output
        raiserror 17301 @msg, @table_type
        return(3)
    end

  delete #tmp_tables

    /*
    ** Just return an empty result set with properly named columns
    ** if (select count(*) from sysobjects where user_name(uid) like @table_owner
    **    	            and name like @table_name
    ** 		    and charindex(substring(type,1,1),@searchstr)! = 0) = 0 
    ** begin
    ** 	exec sp_getmessage 17674, @msg output
    ** 	raiserror 17674 @msg
    ** 	return(1)
    ** end
    */

insert #tmp_tables
    select
        TABLE_CAT =  rtrim(db_name()),
        TABLE_SCHEM= rtrim(user_name(uid)),
        TABLE_NAME = rtrim(name),
        rtrim(substring('SYSTEM TABLE            TABLE       VIEW       ',
        (ascii(type)-83)*12+1,12)) as TABLE_TYPE,
        REMARKS=     convert(varchar(254),null)
    from sysobjects 
    where name like @table_name ESCAPE '\'
        and user_name(uid) like @table_owner ESCAPE '\'
        and charindex(substring(type,1,1),@searchstr)! = 0
    order by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
go
exec sp_procxmode 'sp_ijdbc_tables', 'anymode'
go
grant execute on sp_ijdbc_tables to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_mda')
begin
	drop procedure sp_ijdbc_mda
end
go
print "Installing sp_ijdbc_mda"
go


/*
** requesttype 0 == Returns the mdinfo:MDAVERSION and mdinfo:MDARELEASEID rows.
** requesttype 1 == JDBC
** requesttype 2 == JDBC - but only send back the minimal frequently used info.
** 
** mdaversion 
*/
create procedure sp_ijdbc_mda (@requesttype int, @requestversion int, @clientversion int = 0) as
begin

    declare @min_mdaversion int, @max_mdaversion int
    declare @mda_version int
    declare @srv_version int
    declare @mdaver_querytype tinyint
    declare @mdaver_query varchar(255)
    
    select @min_mdaversion = 1
    select @max_mdaversion = 7
    select @mda_version = @requestversion
    /* get the Server version */
    select @srv_version = convert(int, value) from master.dbo.sysconfigures  
                                       where config=122 
    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

    /*
    ** if the client is requesting a version too old
    ** then we return our lowest version supported
    **
    ** the client needs to be able to just handle this
    */
    if (@requestversion < @min_mdaversion)
        begin
            select @mda_version = @min_mdaversion
        end
        
    /*
    ** if the client is requesting a version too new
    ** we will return our highest version available
    */
    if (@mda_version > @max_mdaversion)
        begin
            select @mda_version = @max_mdaversion
        end
        
    /*
    ** if the client's requested version is between 1 and 3, 
    ** then the mda version returned needs to be 1.  The reason
    ** for this is the jConnect driver would pass in it's own 
    ** major version number as the @requestversion.  We need to
    ** keep older version's of the driver working ok since 
    ** they expect a '1' to be returned.
    */
    if (@mda_version < 4)
        begin
            select @mda_version = 1
            select @mdaver_querytype = 2
            select @mdaver_query = 'select 1'
        end
    else
        begin
            select @mdaver_querytype = 5
            select @mdaver_query = convert(varchar(255), @mda_version)
        end

    /*
    ** process the @requesttype
    */
    if (@requesttype = 0)
        begin
            select "mdinfo" = convert(varchar(30),'MDAVERSION'), 
                   "querytype" = @mdaver_querytype,
		   "pre_query" = '',
                   "query" = @mdaver_query,
		   "post_query" = ''
            union
            select mdinfo, querytype, isnull(pre_query, ''), query,
			isnull(post_query, '') 
            from master..spt_ijdbc_mda
    	    where mdinfo in (
                'MDARELEASEID'
    	        )
        end
    else if (@requesttype = 1)
        begin
            select "mdinfo" = convert(varchar(30),'MDAVERSION'), 
                   "querytype" = @mdaver_querytype,
		    "pre_query" = '',
                   "query" = @mdaver_query,
		    "post_query" = ''
            union
	 select mdinfo, querytype, isnull(pre_query, ''), query,
                        isnull(post_query, '') 
            from master..spt_ijdbc_mda 
            where @mda_version >= mdaver_start
              and @mda_version <= mdaver_end
              and ((@srv_version >= srvver_start) 
                      and (@srv_version < srvver_end 
                      or srvver_end = -1))
        end
    else if (@requesttype = 2)
        begin
            select "mdinfo" = convert(varchar(30),'MDAVERSION'), 
                   "querytype" = @mdaver_querytype,
		     "pre_query" = '',
                   "query" = @mdaver_query,
		   "post_query" = ''
            union
	   select mdinfo, querytype, isnull(pre_query, ''), query, 
                        isnull(post_query, '')
            from master..spt_ijdbc_mda
    	    where mdinfo in (
                'CONNECTCONFIG', 
       		'SET_CATALOG',
       		'SET_AUTOCOMMIT_ON',
       		'SET_AUTOCOMMIT_OFF',
       		'SET_ISOLATION',
       		'SET_ROWCOUNT',
                'DEFAULT_CHARSET'
    	        )
            and @mda_version >= mdaver_start
            and @mda_version <= mdaver_end
            and ((@srv_version >= srvver_start) 
                    and (@srv_version < srvver_end 
                    or srvver_end = -1))
        end
end
go
exec sp_procxmode 'sp_ijdbc_mda', 'anymode'
go
grant execute on sp_ijdbc_mda to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_convert_datatype')
begin
	drop procedure sp_ijdbc_convert_datatype
end
go
print "Installing sp_ijdbc_convert_datatype"
go


create table #tmp_convert_datatype (CONVERT_TYPE smallint null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

create procedure sp_ijdbc_convert_datatype (
					@source int,
					@destination int)
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

	/* Make source non-negative */
	select @source = @source + 7
	/* Put the strange date numbers into this area between 0-19*/
	if (@source > 90)
		select @source = @source - 82

	/*Convert destination the same way*/
	/* Put the strange date numbers into this area between 0-19*/
	if (@destination > 90)
		select @destination = @destination - 82

	/* Need 8 added instead of 7 because substring starts at 1 instead */
	/* of 0 */
	select @destination = @destination + 8

	/* Check the conversion. If the bit string in the table has a 1 
	** on the place's number of the destination's value we have to 
	** return true, else false
	*/

	delete #tmp_convert_datatype

	if ((select substring(conversion,@destination,1)
        from master.dbo.spt_ijdbc_conversion
        where datatype = @source) = '1')

	insert #tmp_convert_datatype
         	select  1   
	else 
	 insert #tmp_convert_datatype
		select  0

go
exec sp_procxmode 'sp_ijdbc_convert_datatype', 'anymode'
go
grant execute on sp_ijdbc_convert_datatype to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_function_escapes')
begin
	drop procedure sp_ijdbc_function_escapes
end
go
print "Installing sp_ijdbc_function_escapes"
go


create table #tmp_function_escapes  (escape_name varchar(40) null,
                                    map_string varchar(40) null )

go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

create procedure sp_ijdbc_function_escapes
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

   delete #tmp_function_escapes	

	insert #tmp_function_escapes
    select * 
    from master.dbo.ijdbc_function_escapes

go
exec sp_procxmode 'sp_ijdbc_function_escapes', 'anymode'
go
grant execute on sp_ijdbc_function_escapes to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_fkeys')
begin
	drop procedure sp_ijdbc_fkeys
end
go
print "Installing sp_ijdbc_fkeys"
go


create table #tmp_fkeys ( PKTABLE_CAT varchar (32) null,
           PKTABLE_SCHEM varchar (32) null,
            PKTABLE_NAME varchar(64) null ,
            PKCOLUMN_NAME varchar(32) null ,
            FKTABLE_CAT varchar(32) null,
            FKTABLE_SCHEM varchar(32) null,
            FKTABLE_NAME varchar(32) null ,
            FKCOLUMN_NAME varchar(32) null ,
            KEY_SEQ smallint null ,
            UPDATE_RULE smallint null ,
            DELETE_RULE smallint null ,
            FK_NAME varchar(32) null,
            PK_NAME varchar(32) null,
            DEFERRABILITY int null )

go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_fkeys
*/

/* The following code is taken from the ODBC handling of 
 * primary keys, and foreign keys, and modified slightly 
 * for JDBC compliance.
 * ODBC sp_fkeys --> sp_ijdbc_fkeys
 *      sp_pkeys --> sp_ijdbc_pkeys
 *      #pid     --> #jpid
 *      #fid     --> #fid
 */


/*
** parameters: @pktable_name - table name for primary key
**             @pktable_owner - (schema) a schema name pattern; "" retrieves 
**		those without a schema
**             @pktable_qualifier - (catalog name) a catalog name; "" retrieves
**              those without a catalog; null means drop catalog name from the
**                  selection criteria 
**             @fktable_name - table name for foreign key
**             @fktable_owner - (schema) a schema name pattern; "" retrieves 
**		those  without a schema
**             @fktable_qualifier - (catalog name) a catalog name; "" retrieves
**              those without a catalog; null means drop catalog name from the
**              selection criteria 
**
** note: there is one raiserror message: 18040
**
** messages for 'sp_ijdbc_fkeys'               18039, 18040
**
** 17461, 'Object does not exist in this database.'
** 18040, 'Catalog procedure %1! can not be run in a transaction.', sp_ijdbc_fkeys
** 18043 ' Primary key table name or foreign key table name or both must be
** given'
** 18044, '%1! table qualifier must be name of current database.' [Primary
** key | Foreign key]
**
*/

CREATE PROCEDURE sp_ijdbc_fkeys
    @pktable_name       varchar(512) = null,
    @pktable_owner      varchar(32) = null,
    @pktable_qualifier  varchar(32) = null,
    @fktable_name       varchar(512) = null,
    @fktable_owner      varchar(32) = null,
    @fktable_qualifier  varchar(32) = null
as
    declare @ftabid int, @ptabid int, @constrid int, @keycnt int, @primkey int
    declare @fokey1 int,  @fokey2 int,  @fokey3 int,  @fokey4 int,  @fokey5  int
    declare @fokey6 int,  @fokey7 int,  @fokey8 int,  @fokey9 int,  @fokey10 int
    declare @fokey11 int, @fokey12 int, @fokey13 int, @fokey14 int, @fokey15 int
    declare @refkey1 int, @refkey2 int, @refkey3 int, @refkey4 int, @refkey5  int
    declare @refkey6 int, @refkey7 int, @refkey8 int, @refkey9 int, @refkey10 int
    declare @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
    declare @refkey15 int, @refkey16 int, @fokey16 int, @status int, @i int
    declare @msg varchar(255)
    declare @msg2 varchar(50)
    declare @export int, @import int
    declare @notDeferrable int  
    select @notDeferrable = 7       
    select @import = 0
    select @export = 0
    
    /* if table_owner is null, include all in search */
    if (@fktable_owner is null) select @fktable_owner = '%'
    if (@pktable_owner is null) select @pktable_owner = '%'

    set nocount on
    
    if (@@trancount = 0)
    begin
        set chained off
    end
    else
    begin
        /* if inside a transaction */
        /* catalog procedure sp_jdbc_fkeys can not be run in a transaction.*/
        exec sp_getmessage 18040, @msg output
        raiserror 18040 @msg, 'sp_fkeys'
        return (1)
    end

    set transaction isolation level 1

    if (@pktable_name is null) and (@fktable_name is null)
    begin
        /* If neither primary key nor foreign key table names given */
        /*
        ** 18043 'Primary key table name or foreign key table name
        ** or both must be given'
        */
        exec  sp_getmessage 18043, @msg output
        raiserror 18043 @msg
        return (1)
    end
	else
	begin
		if (substring(@pktable_name,1,1)= '#') or			
	           (substring(@fktable_name,1,1)='#')  
		begin
			/* We won't allow temptables here
			** 
			** Error 177: cannot create a temporary object (with
			** '#' as the first character name.
			*/
			exec sp_getmessage 17676, @msg out
			raiserror 17676 @msg
			return(1)
		end
	end
    if @fktable_qualifier is not null
    begin
        if db_name() != @fktable_qualifier
        begin
            exec sp_getmessage 18039, @msg out
            raiserror 18039 @msg
            return (1)
        end
    end
    else
    begin
        /*
        ** Now make sure that foreign table qualifier is pointing to the
        ** current database in case it is not specified.
        */
        select @fktable_qualifier = db_name()
    end

    if @pktable_qualifier is not null
    begin
        if db_name() != @pktable_qualifier
        begin
            exec sp_getmessage 18039, @msg output
            raiserror 18039 @msg
            return (1)
        end
    end
    else
    begin
        /*
        ** Now make sure that primary table qualifier is pointing to the
        ** current database in case it is not specified.
        */
        select @pktable_qualifier = db_name()
    end

    create table #jpid (pid int, uid int, name varchar(255))
    create table #jfid (fid int, uid int, name varchar(255))

    delete #tmp_fkeys
	
    if @pktable_name is not null
    begin
		select @export = 1
		if ((select count(*) from sysobjects 
            where name = @pktable_name
            and user_name(uid) like @pktable_owner ESCAPE '\'
            and type in ('S', 'U')) = 0)
        begin
            exec sp_getmessage 17674, @msg output
            raiserror 17674 @msg
            return (1)
        end
        
        insert into #jpid
        select id, uid, name
        from sysobjects
        where name = @pktable_name
        and user_name(uid) like @pktable_owner ESCAPE '\'
        and type in ('S', 'U')
    end
    else
    begin
        insert into #jpid
        select id, uid, name
        from sysobjects 
        where type in ('S', 'U')
        and user_name(uid) like @pktable_owner ESCAPE '\'
    end

    if @fktable_name is not null
    begin
        select @import = 1
        if ((select count(*)
            from sysobjects
            where name = @fktable_name
            and type in ('S', 'U')
            and user_name(uid) like @fktable_owner ESCAPE '\') = 0)
        begin
            exec sp_getmessage 17674, @msg output
            raiserror 17674 @msg
            return (1)
        end
        insert into #jfid
        select id, uid, name
            from sysobjects
            where name = @fktable_name
            and type in ('S', 'U')
            and user_name(uid) like @fktable_owner ESCAPE '\'
    end
    else
    begin
        insert into #jfid
        select id, uid, name
            from sysobjects where
            type in ('S', 'U')
            and user_name(uid) like @fktable_owner ESCAPE '\'
    end

    create table #jfkey_res( 
        pktable_qualifier  varchar(32) null,
        pktable_owner      varchar(32) null,
        pktable_name       varchar(257) null,
        pkcolumn_name      varchar(257) null,
        fktable_qualifier  varchar(32) null,
        fktable_owner      varchar(32) null,
        fktable_name       varchar(257) null,
        fkcolumn_name      varchar(257) null,
        key_seq            smallint,
        update_rule        smallint,
        delete_rule        smallint,
        constrid           varchar(257),
        primkey            varchar(257) null)
    create table #jpkeys(seq int,  keys varchar(255) null)
    create table #jfkeys(seq int, keys varchar(255) null)

   
        select tableid, reftabid, constrid, keycnt,
            fokey1, fokey2, fokey3, fokey4, fokey5, fokey6, fokey7, fokey8,
            fokey9, fokey10, fokey11, fokey12, fokey13, fokey14, fokey15,
            fokey16, refkey1, refkey2, refkey3, refkey4, refkey5,
            refkey6, refkey7, refkey8, refkey9, refkey10, refkey11,
            refkey12, refkey13, refkey14, refkey15, refkey16
		into #temp_keys
            from sysreferences
            where tableid in (
                    select fid from #jfid)
            and reftabid in (
                    select pid from #jpid)
            and frgndbname is NULL and pmrydbname is NULL
            
        /*
        ** For each row of sysreferences which describes a foreign-
        ** primary key relationship, do the following.
        */
        
        /*
        ** First store the column names that belong to primary keys
        ** in table #pkeys for later retrieval.
        */
        
       
        insert #jpkeys select 1, col_name(reftabid,refkey1) from #temp_keys
        insert #jpkeys select 2, col_name(reftabid,refkey2) from #temp_keys
        insert #jpkeys select 3, col_name(reftabid,refkey3) from #temp_keys
        insert #jpkeys select 4, col_name(reftabid,refkey4) from #temp_keys
        insert #jpkeys select 5, col_name(reftabid,refkey5) from #temp_keys
        insert #jpkeys select 6, col_name(reftabid,refkey6) from #temp_keys
        insert #jpkeys select 7, col_name(reftabid,refkey7) from #temp_keys
        insert #jpkeys select 8, col_name(reftabid,refkey8) from #temp_keys
        insert #jpkeys select 9, col_name(reftabid,refkey9) from #temp_keys
        insert #jpkeys select 10, col_name(reftabid,refkey10) from #temp_keys
        insert #jpkeys select 11, col_name(reftabid,refkey11) from #temp_keys
        insert #jpkeys select 12, col_name(reftabid,refkey12) from #temp_keys
        insert #jpkeys select 13, col_name(reftabid,refkey13) from #temp_keys
        insert #jpkeys select 14, col_name(reftabid,refkey14) from #temp_keys
        insert #jpkeys select 15, col_name(reftabid,refkey15) from #temp_keys
        insert #jpkeys select 16, col_name(reftabid,refkey16) from #temp_keys
        
        /*
        ** Second store the column names that belong to foreign keys
        ** in table #jfkeys for later retrieval.
        */
        
        
        insert #jfkeys select 1, col_name(tableid,fokey1)from #temp_keys
        insert #jfkeys select 2, col_name(tableid,fokey2)from #temp_keys
        insert #jfkeys select 3, col_name(tableid,fokey3)from #temp_keys
        insert #jfkeys select 4, col_name(tableid,fokey4)from #temp_keys
        insert #jfkeys select 5, col_name(tableid,fokey5)from #temp_keys
        insert #jfkeys select 6, col_name(tableid,fokey6)from #temp_keys
        insert #jfkeys select 7, col_name(tableid,fokey7)from #temp_keys
        insert #jfkeys select 8, col_name(tableid,fokey8)from #temp_keys
        insert #jfkeys select 9, col_name(tableid,fokey9)from #temp_keys
        insert #jfkeys select 10, col_name(tableid,fokey10)from #temp_keys
        insert #jfkeys select 11, col_name(tableid,fokey11)from #temp_keys
        insert #jfkeys select 12, col_name(tableid,fokey12)from #temp_keys
        insert #jfkeys select 13, col_name(tableid,fokey13)from #temp_keys
        insert #jfkeys select 14, col_name(tableid,fokey14)from #temp_keys
        insert #jfkeys select 15, col_name(tableid,fokey15)from #temp_keys
        insert #jfkeys select 16, col_name(tableid,fokey16)from #temp_keys

        
        /*
        ** For each column of the current foreign-primary key relation,
        ** create a row into result table: #jfkey_res.
        */
        
        
            insert into #jfkey_res
                select @pktable_qualifier,
                user_name(jpd.uid),
		 object_name(tk.reftabid), 
                jpk.keys,
                    @fktable_qualifier,
                user_name(jfd.uid) ,
                object_name(tk.tableid),
                jfk.keys, 
                jfk.seq, 1, 1,
                /*Foreign key name*/ 
                object_name(tk.constrid),
                /* Primary key name */
		s.name
		from #temp_keys tk, #jfkeys jfk ,#jpid jpd,
			#jfid jfd, sysindexes s, #jpkeys jpk  
		where jfk.seq <= tk.keycnt
		       	and tk.keycnt >=1       
			and jpk.seq = jfk.seq 
			and  jpd.pid =* tk.reftabid
			and jfd.fid =* tk.tableid
			and   s.id =* tk.tableid
                    	and s.status > 2048 
			and s.status < 32768
			

    

    /*
    ** Everything is now in the result table #jfkey_res, so go ahead
    ** and select from the table now.
    */
    if (@export = 1) and (@import = 0)
    begin
	insert #tmp_fkeys
       select distinct pktable_qualifier as PKTABLE_CAT,
           pktable_owner as PKTABLE_SCHEM,
           pktable_name as PKTABLE_NAME,
           pkcolumn_name as PKCOLUMN_NAME,
           fktable_qualifier as FKTABLE_CAT, 
           fktable_owner as FKTABLE_SCHEM, 
           fktable_name as FKTABLE_NAME, 
           fkcolumn_name as FKCOLUMN_NAME,
           key_seq as KEY_SEQ, 
           update_rule as UPDATE_RULE, 
           delete_rule as DELETE_RULE,
           constrid as FK_NAME,
           primkey as PK_NAME, 
           @notDeferrable  as DEFERRABILITY
      from #jfkey_res 
      where pktable_owner like @pktable_owner ESCAPE '\'
      order by fktable_name,fktable_owner,key_seq, fktable_qualifier
    end

    if (@export = 0) and (@import = 1)
    begin
	insert #tmp_fkeys
        select distinct pktable_qualifier as PKTABLE_CAT,
            pktable_owner as PKTABLE_SCHEM,
            pktable_name as PKTABLE_NAME,
            pkcolumn_name as PKCOLUMN_NAME,
            fktable_qualifier as FKTABLE_CAT, 
            fktable_owner as FKTABLE_SCHEM, 
            fktable_name as FKTABLE_NAME, 
            fkcolumn_name as FKCOLUMN_NAME,
            key_seq as KEY_SEQ, 
            update_rule as UPDATE_RULE, 
            delete_rule as DELETE_RULE,
            constrid as FK_NAME,
            primkey as PK_NAME, 
            @notDeferrable  as DEFERRABILITY
        from #jfkey_res 
        where fktable_owner like @fktable_owner ESCAPE '\'
        order by fktable_name,fktable_owner,key_seq, fktable_qualifier
    end

    if (@export = 1) and (@import = 1)
    begin

	insert #tmp_fkeys
        select distinct pktable_qualifier as PKTABLE_CAT,
           pktable_owner as PKTABLE_SCHEM,
           pktable_name as PKTABLE_NAME,
           pkcolumn_name as PKCOLUMN_NAME,
           fktable_qualifier as FKTABLE_CAT, 
           fktable_owner as FKTABLE_SCHEM, 
           fktable_name as FKTABLE_NAME, 
           fkcolumn_name as FKCOLUMN_NAME,
           key_seq as KEY_SEQ, 
           update_rule as UPDATE_RULE, 
           delete_rule as DELETE_RULE,
           constrid as FK_NAME,
           primkey as PK_NAME, 
           @notDeferrable  as DEFERRABILITY
        from #jfkey_res 
        where pktable_owner like @pktable_owner ESCAPE '\'
        and fktable_owner like @fktable_owner ESCAPE '\'
        order by fktable_name,fktable_owner,key_seq, fktable_qualifier
    end
       
	
/*
**  End of sp_jdbc_fkeys
*/
go
exec sp_procxmode 'sp_ijdbc_fkeys', 'anymode'
go
grant execute on sp_ijdbc_fkeys to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_exportkey')
begin
	drop procedure sp_ijdbc_exportkey
end
go
print "Installing sp_ijdbc_exportkey"
go


/* 
**  sp_ijdbc_exportkey
*/

CREATE PROCEDURE sp_ijdbc_exportkey (
				 @table_qualifier	varchar(32) = null,
				 @table_owner		varchar(32) = null,
				 @table_name		varchar(257))
as
    exec sp_ijdbc_fkeys 
        @table_name, @table_owner, @table_qualifier, NULL, NULL, NULL
go
exec sp_procxmode 'sp_ijdbc_exportkey', 'anymode'
go
grant execute on sp_ijdbc_exportkey to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_importkey')
begin
	drop procedure sp_ijdbc_importkey
end
go
print "Installing sp_ijdbc_importkey"
go


/* 
** sp_ijdbc_importkey
*/


CREATE PROCEDURE sp_ijdbc_importkey (
				 @table_qualifier	varchar(32) = null,
				 @table_owner		varchar(32) = null,
				 @table_name		varchar(257))
as
    exec sp_ijdbc_fkeys
        NULL, NULL, NULL, @table_name, @table_owner, @table_qualifier
go
exec sp_procxmode 'sp_ijdbc_importkey', 'anymode'
go
grant execute on sp_ijdbc_importkey to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getcrossreferences')
begin
	drop procedure sp_ijdbc_getcrossreferences
end
go
print "Installing sp_ijdbc_getcrossreferences"
go


/*
**  sp_ijdbc_getcrossreferences
*/


CREATE PROCEDURE sp_ijdbc_getcrossreferences
			   @pktable_qualifier	varchar(32) = null,
			   @pktable_owner	varchar(32) = null,
			   @pktable_name	varchar(257),
			   @fktable_qualifier	varchar(32) = null ,
			   @fktable_owner	varchar(32) = null,
			   @fktable_name	varchar(257)
as
	exec sp_ijdbc_fkeys 
        @pktable_name, @pktable_owner, @pktable_qualifier,
        @fktable_name, @fktable_owner, @fktable_qualifier
go
exec sp_procxmode 'sp_ijdbc_getcrossreferences', 'anymode'
go
grant execute on sp_ijdbc_getcrossreferences to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getschemas')
begin
	drop procedure sp_ijdbc_getschemas
end
go
print "Installing sp_ijdbc_getschemas"
go


create table #tmp_getschemas (TABLE_SCHEM varchar(30) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/* 
**  sp_ijdbc_getschemas
*/

CREATE PROCEDURE sp_ijdbc_getschemas 
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1


	delete #tmp_getschemas

	insert #tmp_getschemas
	select TABLE_SCHEM=name  from sysusers where suid >= -2 order by name

go
exec sp_procxmode 'sp_ijdbc_getschemas', 'anymode'
go
grant execute on sp_ijdbc_getschemas to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_aux_computeprivs')
begin
	drop procedure sp_ijdbc_aux_computeprivs
end
go
print "Installing sp_ijdbc_aux_computeprivs"
go

/*
**  sp_ijdbc_aux_computeprivs
*/

/* Got this from ODBC / installmaster script
** It is needed for the following stored procs getColumnPrivileges and
** getTablePrivileges.
** The only change is the adding of 'order by' in the select statement that 
** produces the output. 
*/


create procedure sp_ijdbc_aux_computeprivs ( 
    @table_name         varchar(257),
    @table_owner        varchar(32),
    @table_qualifier    varchar(32), 
    @column_name        varchar(257),
    @calledfrom_colpriv	tinyint,
    @tab_id	            int)

as        

    declare @low 		int		/* range of userids to check */
    declare @high 		int
    declare @max_uid		int        /* max uid allowed for a user*/
    declare @grantor_name	varchar (32)    /* the ascii name of grantor. used for output */
    declare @grantee_name	varchar (32)    /* the ascii name of grantee. us/sysprotected for output */
    declare @col_count		smallint        /* number of columns in @table_name */
    declare @grantee    	int		/* id of the grantee */
    declare @action 		smallint	 	/* action refers to select, update...*/
    declare @columns		varbinary (133)	/* bit map of column privilegs */
    declare @protecttype 	tinyint		/* grant/revoke or grant with grant option */
    declare @grantor    	int	/* id of the grantor of the privilege */
    declare @grp_id		int	/* the group a user belongs to */
    declare @grant_type		tinyint		/* used as a constant */
    declare @revoke_type	tinyint		/* used as a constant */
    declare @select_action	smallint		/* used as a constant */
    declare @update_action	smallint		/* used as a constant */
    declare @reference_action	smallint		/* used as a constant */
    declare @insert_action	smallint		/* used as a constant */
    declare @delete_action	smallint		/* used as a constant */
    declare @public_select	varbinary (133)  /* stores select column bit map for public */
    declare @public_reference	varbinary (133)	/* stores reference column bit map for public */
    declare @public_update	varbinary (133)	/* stores update column bit map for public */
    declare @public_insert	tinyint		/* stores if insert has been granted to public */
    declare @public_delete	tinyint		/* store if delete has been granted to public */
    declare @grp_select		varbinary (133)  /* stores select column bit map for group */
    declare @grp_update		varbinary (133)  /* stores update column bit map for group */
    declare @grp_reference	varbinary (133)  /* stores reference column bit map for group */
    declare @grp_delete		tinyint		/* if group hs been granted delete privilege */
    declare @grp_insert		tinyint		/* if group has been granted insert privilege */
    declare @inherit_select	varbinary (133)	/* stores select column bit map for 
						   inherited privs*/
    declare @inherit_update	varbinary (133)  /* stores update column bit map for 
						   inherited privs */
    declare @inherit_reference	varbinary (133)  /* stores reference column bit map for 
						   inherited privs */
    declare @inherit_insert	tinyint		/* inherited insert priv */
    declare @inherit_delete	tinyint		/* inherited delete priv */
    declare @select_go		varbinary (133)	/* user column bit map of select with grant */
    declare @update_go		varbinary (133)	/* user column bit map of update with grant */
    declare @reference_go	varbinary (133)	/* user column bitmap of reference with grant */
    declare @insert_go		tinyint		/* user insert priv with grant option */
    declare @delete_go		tinyint		/* user delete priv with grant option  */
    declare @prev_grantor	tinyint		/* used to detact if the grantor has changed 
						   between two consecutive tuples */
    declare @col_pos		smallint		/* col_pos of the column we are interested in. It
						   is used to find the col-bit in the bitmap */
    declare @owner_id		int	/* id of the owner of the table */
    declare @dbid		smallint	/* dbid for the table */
    declare @grantable		varchar (3) 	/* 'YES' or 'NO' if the privilege is grantable or
						   not */
    declare @is_printable	tinyint		/* 1, if the privilege info is to be outputted */
    declare @curr_column	varchar (257)    /* name of the column being printed */
    declare @save_column_name   varchar(257)

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

/* 
** Initialize all constants to be used in this procedure
*/

    select @grant_type = 1

    select @revoke_type = 2
   
    select @select_action = 193

    select @reference_action = 151

    select @update_action = 197

    select @delete_action = 196

    select @insert_action = 195

    select @max_uid = @@maxuserid 

    select @low = 0, @high = 32767
    select @dbid = db_id()
    select @save_column_name = @column_name
    select @column_name = '%'
/* 
** compute the table owner id
*/

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id

/*
** create a temporary sysprotects table that only has grant/revoke tuples
** for the requested table. This is done as an optimization as the sysprotects
** table may need to be traversed several times
*/

    create table #sysprotects
	(uid		int,
	 action		smallint,
	 protecttype	tinyint,
	 columns	varbinary (133) NULL,
	 grantor	int)

/*
** This table contains all the groups including PUBLIC that users, who
** have been granted privilege on this table, belong to. Also it includes
** groups that have been explicitly granted privileges on the table object
*/
    create table #useful_groups
	(grp_id		int)

/*
** create a table that contains the list of grantors for the object requested.
** We will do a cartesian product of this table with sysusers in the
** current database to capture all grantor/grantee tuples
*/

    create table #distinct_grantors
	(grantor	int)

/*
** We need to create a table which will contain a row for every object
** privilege to be returned to the client.  
*/

    create table #column_privileges 
	(grantee_gid	int,
	 grantor	int,
	 grantee	int,
	 insertpriv	tinyint,
	 insert_go	tinyint NULL,
	 deletepriv	tinyint,
	 delete_go	tinyint NULL,
	 selectpriv	varbinary (133) NULL,
	 select_go	varbinary (133) NULL,
	 updatepriv	varbinary (133) NULL,
	 update_go	varbinary (133) NULL,
	 referencepriv	varbinary (133) NULL,
	 reference_go	varbinary (133) NULL)

/*
** Results Table
*/
    create table #results_table
	 (table_qualifier	varchar (32),
	  table_owner		varchar (32),
	  table_name		varchar (257),
	  column_name		varchar (257) NULL,
	  grantor		varchar (32),
	  grantee 		varchar (32),
	  privilege		varchar (32),
	  is_grantable		varchar (3))
/*
** this cursor scans the distinct grantor, group_id pairs
*/
    declare grp_cursor cursor for
	select distinct grp_id, grantor 
	from #useful_groups, #distinct_grantors
	order by grantor

/* 
** this cursor scans all the protection tuples that represent
** grant/revokes to users only
*/
    declare user_protect cursor for
	select uid, action, protecttype, columns, grantor
	from   #sysprotects
	where  (uid > 0) and
	       (uid <= @max_uid)


/*
** this cursor is used to scan #column_privileges table to output results
*/
    declare col_priv_cursor cursor for
	  select grantor, grantee, insertpriv, insert_go, deletepriv, delete_go,
		 selectpriv, select_go, updatepriv, update_go, referencepriv, reference_go
	  from #column_privileges



/*
** column count is needed for privilege bit-map manipulation
*/
    select @col_count = count (*) 
    from   syscolumns
    where  id = @tab_id


/* 
** populate the temporary sysprotects table #sysprotects
*/

	insert into #sysprotects 
		select uid, action, protecttype, columns, grantor
		from sysprotects		where (id = @tab_id)    	   and
		      ((action = @select_action)   or
		      (action = @update_action)    or
		      (action = @reference_action) or
		      (action = @insert_action)    or
		      (action = @delete_action))

/* 
** insert privilege tuples for the table owner. There is no explicit grants
** of these privileges to the owner. So these tuples are not there in sysprotects
** table
*/

	insert into #sysprotects
	     values (@owner_id, @select_action, 0, 0x01, @owner_id)
	insert into #sysprotects
	     values (@owner_id, @update_action, 0, 0x01, @owner_id)
	insert into #sysprotects
	     values (@owner_id, @reference_action, 0, 0x01, @owner_id)
	insert into #sysprotects
	     values (@owner_id, @insert_action, 0, 0x00, @owner_id)
	insert into #sysprotects
	     values (@owner_id, @delete_action, 0, 0x00, @owner_id)

/* 
** populate the #distinct_grantors table with all grantors that have granted
** the privilege to users or to gid or to public on the table_name
*/

    insert into #distinct_grantors 
	  select distinct grantor from #sysprotects

/* 
** Populate the #column_privilegs table as a cartesian product of the table
** #distinct_grantors and all the users, other than groups, in the current database
*/


    insert into #column_privileges
	  select gid, g.grantor, su.uid, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00,
                 0x00
	  from sysusers su, #distinct_grantors g
	  where (su.uid > 0) and
	        (su.uid <= @max_uid)

/*
** populate #useful_groups with only those groups whose members have been granted/revoked
** privilges on the @tab_id in the current database. It also contains those groups
** that have been granted/revoked privileges explicitly
*/

    insert into #useful_groups
	select distinct gid
	from   sysusers su, #sysprotects sp
	where  (su.uid = sp.uid) 


    open grp_cursor

    fetch grp_cursor into @grp_id, @grantor

    /* 
    ** This loop computes all the inherited privilegs of users due
    ** their membership in a group
    */

    while (@@sqlstatus != 2)
   
    begin

	 /* 
	 ** initialize variables 
	 */
	 select @public_select = 0x00
 	 select @public_update = 0x00
	 select @public_reference = 0x00
	 select @public_delete = 0
	 select @public_insert = 0


	 /* get the select privileges granted to PUBLIC */

	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @select_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_select = columns
	      from #sysprotects
	      where (grantor = @grantor) and 
		    (uid = 0) and
		    (action = @select_action)
         end


	 /* get the update privilege granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @update_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_update = columns
	      from #sysprotects
	      where (grantor = @grantor) and 
		    (uid = 0) and
		    (action = @update_action)
         end

	 /* get the reference privileges granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @reference_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_reference = columns
	      from #sysprotects
	      where (grantor = @grantor) and 
		    (uid = 0) and
		    (action = @reference_action)
         end


	 /* get the delete privilege granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @delete_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_delete = 1
         end

	 /* get the insert privileges granted to public */
	 if (exists (select * from #sysprotects 
 		     where (grantor = @grantor) and 
			   (uid = 0) and
			   (action = @insert_action)))
	 begin
	      /* note there can't be any revoke row for PUBLIC */
	      select @public_insert = 1
         end


	 /*
	 ** initialize group privileges 
	 */

	 select @grp_select = 0x00
	 select @grp_update = 0x00
	 select @grp_reference = 0x00
	 select @grp_insert = 0
	 select @grp_delete = 0

	 /* 
	 ** if the group id is other than PUBLIC, we need to find the grants to
	 ** the group also 
	 */

	 if (@grp_id <> 0)
	 begin
	 	/* find select privilege granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @select_action)))
	 	begin
	      		select @grp_select = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @grant_type) and 
		    	      (action = @select_action)
                end

		/* find update privileges granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @update_action)))
	 	begin
	      		select @grp_update = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @grant_type) and 
		    	      (action = @update_action)
                end

		/* find reference privileges granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @reference_action)))
	 	begin
	      		select @grp_reference = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @grant_type) and 
		    	      (action = @reference_action)
                end

		/* find delete privileges granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @delete_action)))
	 	begin

	      		select @grp_delete = 1
                end

		/* find insert privilege granted to group */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @grant_type) and
			          (action = @insert_action)))
	 	begin

	      		select @grp_insert = 1

                end
		
	 end

	 /* at this stage we have computed all the grants to PUBLIC as well as
	 ** the group by a specific grantor that we are interested in. Now we will
	 ** use this info to compute the overall inherited privilegs by the users
	 ** due to their membership to the group or to PUBLIC 
	 */


	 exec sybsystemprocs.dbo.syb_aux_privunion @public_select, @grp_select, @col_count,
					   @inherit_select output
	 exec sybsystemprocs.dbo.syb_aux_privunion @public_update, @grp_update, @col_count,
					   @inherit_update output
	 exec sybsystemprocs.dbo.syb_aux_privunion @public_reference, @grp_reference, @col_count,
					   @inherit_reference output

	 select @inherit_insert = @public_insert + @grp_insert
	 select @inherit_delete = @public_delete + @grp_delete

	 /*
	 ** initialize group privileges to store revokes
	 */

	 select @grp_select = 0x00
	 select @grp_update = 0x00
	 select @grp_reference = 0x00
	 select @grp_insert = 0
	 select @grp_delete = 0

         /* 
	 ** now we need to find if there are any revokes on the group under
 	 ** consideration. We will subtract all privileges that are revoked from the 
	 ** group from the inherited privileges
	 */

	 if (@grp_id <> 0)
	 begin
		/* check if there is a revoke row for select privilege*/
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @select_action)))
	 	begin
	      		select @grp_select = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @revoke_type) and 
		    	      (action = @select_action)
                end

		/* check if there is a revoke row for update privileges */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @update_action)))
	 	begin
	      		select @grp_update = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @revoke_type) and 
		    	      (action = @update_action)
                end

		/* check if there is a revoke row for reference privilege */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @reference_action)))
	 	begin
	      		select @grp_reference = columns
	      		from #sysprotects
	      		where (grantor = @grantor) and 
		   	      (uid = @grp_id) and
			      (protecttype = @revoke_type) and 
		    	      (action = @reference_action)
                end

		/* check if there is a revoke row for delete privilege */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @delete_action)))
	 	begin
	      		select @grp_delete = 1
                end

		/* check if there is a revoke row for insert privilege */
	 	if (exists (select * from #sysprotects 
 		            where (grantor = @grantor) and 
			          (uid = @grp_id) and
				  (protecttype = @revoke_type) and
			          (action = @insert_action)))
	 	begin
	      		select @grp_insert = 1

                end


		/* 
		** now subtract the revoked privileges from the group
		*/

		exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
					 	 @grp_select,
						 @col_count,
						 @inherit_select output

		exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
					 	 @grp_update,
						 @col_count,
						 @inherit_update output

		exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference,
					 	 @grp_reference,
						 @col_count,
						 @inherit_reference output

		if (@grp_delete = 1)
			select @inherit_delete = 0

		if (@grp_insert = 1)
			select @inherit_insert = 0

	 end

	 /*
	 ** now update all the tuples in #column_privileges table for this
	 ** grantor and group id
	 */
	
	 update #column_privileges
	 set
		insertpriv 	= @inherit_insert,
		deletepriv 	= @inherit_delete,
	        selectpriv 	= @inherit_select,
		updatepriv 	= @inherit_update,
		referencepriv 	= @inherit_reference

	 where (grantor     = @grantor) and
	       (grantee_gid = @grp_id)


	 /*
	 ** the following update updates the privileges for those users
	 ** whose groups have not been explicitly granted privileges by the
	 ** grantor. So they will all have all the privileges of the PUBLIC
	 ** that were granted by the current grantor
	 */

	 select @prev_grantor = @grantor	 
         fetch grp_cursor into @grp_id, @grantor

	 if ((@prev_grantor <> @grantor) or (@@sqlstatus = 2))

	 begin
	 /* Either we are at the end of the fetch or we are switching to
	 ** a different grantor. 
	 */

	       update #column_privileges 
	       set
			insertpriv 	= @public_insert,
			deletepriv 	= @public_delete,
	        	selectpriv 	= @public_select,
			updatepriv 	= @public_update,
			referencepriv 	= @public_reference
		from #column_privileges cp
	 	where (cp.grantor = @prev_grantor) and
	       	      (not EXISTS (select * 
			    	   from #useful_groups ug
			    	   where ug.grp_id = cp.grantee_gid))

         end
    end


    close grp_cursor


    /* 
    ** At this stage, we have populated the #column_privileges table with
    ** all the inherited privileges
    */

    
    /* 
    ** Now we will go through each user grant or revoke in table #sysprotects
    ** and update the privileges in #column_privileges table
    */
    open user_protect

    fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor

    while (@@sqlstatus != 2)
    begin
	/*
	** In this loop, we can find grant row, revoke row or grant with grant option
	** row. We use protecttype to figure that. If it is grant, then the user specific
	** privileges are added to the user's inherited privileges. If it is a revoke,
	** then the revoked privileges are subtracted from the inherited privileges. If
	** it is a grant with grant option, we just store it as is because privileges can
	** only be granted with grant option to individual users
	*/

	/* 
	** for select action
	*/
	if (@action = @select_action)
	begin
	     /* get the inherited select privilege */
	     select @inherit_select = selectpriv
	     from   #column_privileges
	     where  (grantee = @grantee) and
		    (grantor = @grantor)

	     if (@protecttype = @grant_type)
	     /* the grantee has a individual grant */
		exec sybsystemprocs.dbo.syb_aux_privunion @inherit_select, @columns, 
						  @col_count, @inherit_select output

	     else 
		if (@protecttype = @revoke_type)
		/* it is a revoke row */
		     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select, @columns, 
						      @col_count, @inherit_select output

	        else
		     /* it is a grant with grant option */

		     select @select_go = @columns

  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set selectpriv = @inherit_select
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin

	     	  update #column_privileges
	     	  set select_go = @select_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	end

	/*
	** update action
	*/
	if (@action = @update_action)
	begin
	     /* find out the inherited update privilege */
	     select @inherit_update = updatepriv
	     from   #column_privileges
	     where  (grantee = @grantee) and
		    (grantor = @grantor)

		
	     if (@protecttype = @grant_type)
	     /* user has an individual grant */
		exec sybsystemprocs.dbo.syb_aux_privunion @inherit_update, @columns, 
						  @col_count, @inherit_update output

	     else 
		if (@protecttype = @revoke_type)
		     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update, @columns, 
						      @col_count, @inherit_update output

	        else
		     /* it is a grant with grant option */
		     select @update_go = @columns


  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set updatepriv = @inherit_update
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set update_go = @update_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	end

	/* it is the reference privilege */
	if (@action = @reference_action)
	begin
	     select @inherit_reference = referencepriv
	     from   #column_privileges
	     where  (grantee = @grantee) and
		    (grantor = @grantor)


	     if (@protecttype = @grant_type)
	     /* the grantee has a individual grant */
		exec sybsystemprocs.dbo.syb_aux_privunion @inherit_reference, @columns, 
						  @col_count, @inherit_reference output

	     else 
		if (@protecttype = @revoke_type)
		/* it is a revoke row */
		     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference, @columns, 
						      @col_count, @inherit_reference output

	        else
		     /* it is a grant with grant option */
		     select @reference_go = @columns


  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set referencepriv = @inherit_reference
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set reference_go = @reference_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end

	end

	/*
	** insert action
	*/

	if (@action = @insert_action)
	begin
	     if (@protecttype = @grant_type)
		   select @inherit_insert = 1
	     else
		 if (@protecttype = @revoke_type)
		      select @inherit_insert = 0
		 else
		      select @insert_go = 1

	     
  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set insertpriv = @inherit_insert
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set insert_go = @insert_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end

	end

	/* 
	** delete action
	*/

	if (@action = @delete_action)
	begin
	     if (@protecttype = @grant_type)
		   select @inherit_delete = 1
	     else
		 if (@protecttype = @revoke_type)
		      select @inherit_delete = 0
		 else
		      select @delete_go = 1

	     
  	     /* modify the privileges for this user */
	
	     if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
	     begin
	     	  update #column_privileges
	     	  set deletepriv = @inherit_delete
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end
	     else
	     begin
	     	  update #column_privileges
	     	  set delete_go = @delete_go
	     	  where (grantor = @grantor) and
		        (grantee = @grantee)
	     end

	end

        fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor
    end

    close user_protect

open col_priv_cursor
fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
	                 @inherit_delete, @delete_go, @inherit_select, @select_go,
			 @inherit_update, @update_go, @inherit_reference, @reference_go

while (@@sqlstatus != 2)
begin

      /* 
      ** name of the grantor
      */
      select @grantor_name = name 
      from   sysusers
      where  uid = @grantor


      /*
      ** name of the grantee
      */

      select @grantee_name = name
      from   sysusers
      where  uid = @grantee


      if (@column_name = '%')
      /* 
      ** we need to print the privilege information for all columns of the table
      */
      begin
	    select @col_pos = 1

 	    while (@col_pos <= @col_count)
	    begin

		 select @curr_column = col_name (@tab_id, @col_pos)

  	         /* 
	         ** check for insert privileges
	         */
	         exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, @inherit_insert, @insert_go, 0x00, 0x00, 0, 
				@grantable output, @is_printable output

	         if (@is_printable = 1)
		 begin
		        insert into #results_table
		                values (@table_qualifier, @table_owner, @table_name, @curr_column,
				@grantor_name, @grantee_name, 'INSERT', @grantable)
		 end

	         /* 
	         ** check for select privileges
	         */
	         exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_select, @select_go, 1, 
			@grantable output, @is_printable output

	         if (@is_printable = 1)
		 begin
		        insert into #results_table
		   		values (@table_qualifier, @table_owner, @table_name, @curr_column,
				@grantor_name, @grantee_name, 'SELECT', @grantable)
		 end
	         /* 
	         ** check for update privileges
	         */
	         exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_update, @update_go, 1, 
			@grantable output, @is_printable output

	         if (@is_printable = 1)
		 begin
		 	 insert into #results_table
		   		values (@table_qualifier, @table_owner, @table_name, @curr_column,
				@grantor_name, @grantee_name, 'UPDATE', @grantable)
		 end
	         /*
	         ** check for reference privs
	   	 */

	 	exec sybsystemprocs.dbo.syb_aux_printprivs 
		        @calledfrom_colpriv, @col_pos, 0, 0, @inherit_reference, @reference_go, 1, 
				@grantable output, @is_printable output

	    	if (@is_printable = 1)
		begin
			insert into #results_table
			        values (@table_qualifier, @table_owner, @table_name, @curr_column,
				@grantor_name, @grantee_name, 'REFERENCE', @grantable)
		end

		select @col_pos = @col_pos + 1
	    end
      end
      else
      begin

      /* 
      ** At this point, we are either printing privilege information for a
      ** a specific column or for table_privileges
      */

	    select @col_pos = 0

	    if (@calledfrom_colpriv = 1)
	    begin
	    /* 
	    ** find the column position
	    */
	         select @col_pos = colid
	         from syscolumns
	         where (id = @tab_id) and
		       (name = @column_name)
	    end

	    /* 
	    ** check for insert privileges
	    */
	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, @inherit_insert, @insert_go, 0x00, 0x00, 0, 
				@grantable output, @is_printable output

	    if (@is_printable = 1)
	    begin
		  insert into #results_table
		       values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'INSERT', @grantable)
	    end

	    /* 
	    ** check for delete privileges
	    */

	    if (@calledfrom_colpriv = 0)
	    /* delete privilge need only be printed if called from sp_table_privileges */
	    begin
	 	    exec sybsystemprocs.dbo.syb_aux_printprivs 
		         @calledfrom_colpriv, @col_pos, @inherit_delete, @delete_go, 0x00, 0x00, 0, 
				@grantable output, @is_printable output

	    	    if (@is_printable = 1)
		    begin
		  	insert into #results_table
			        values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'DELETE', @grantable)
		    end
	    end

	    /* 
	    ** check for select privileges
	    */
	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_select, @select_go, 1, 
			@grantable output, @is_printable output


	    if (@is_printable = 1)
	    begin
		  insert into #results_table
		  	 values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'SELECT', @grantable)
	    end
	    /* 
	    ** check for update privileges
	    */
	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			@calledfrom_colpriv, @col_pos, 0, 0, @inherit_update, @update_go, 1, 
			@grantable output, @is_printable output

	    if (@is_printable = 1)
	    begin
		  insert into #results_table
		   	values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'UPDATE', @grantable)
	    end
	    /*
	    ** check for reference privs
	    */
	    if (@calledfrom_colpriv = 1)
	    /* reference privilge need only be printed if called from sp_column_privileges */
	    begin
	 	    exec sybsystemprocs.dbo.syb_aux_printprivs 
			 @calledfrom_colpriv, @col_pos, 0, 0, @inherit_reference, @reference_go, 1, 
				@grantable output, @is_printable output

	    	    if (@is_printable = 1)
		    begin
		  	insert into #results_table
			        values (@table_qualifier, @table_owner, @table_name, @column_name,
				@grantor_name, @grantee_name, 'REFERENCE', @grantable)
		    end
	    end

      end


      fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
	                 @inherit_delete, @delete_go, @inherit_select, @select_go,
			 @inherit_update, @update_go, @inherit_reference, @reference_go
end

    
/*
** Outputting the results table
*/

if (@calledfrom_colpriv = 1)
	/* Changed to get the requested output order*/
	exec sp_autoformat @fulltabname = #results_table,
		@selectlist = "TABLE_CAT = table_qualifier, TABLE_SCHEM = table_owner, TABLE_NAME = table_name, COLUMN_NAME = column_name, GRANTOR = grantor, GRANTEE = grantee, PRIVILEGE = privilege, IS_GRANTABLE = is_grantable",
		@whereclause = "column_name like @save_column_name ESCAPE '\'",
		@orderby = "order by column_name, privilege"  

else
	/* Changed to get the requested output order*/
	exec sp_autoformat @fulltabname = #results_table,
		@selectlist = "TABLE_CAT = table_qualifier, TABLE_SCHEM = table_owner, TABLE_NAME = table_name, GRANTOR = grantor, GRANTEE = grantee, PRIVILEGE = privilege, IS_GRANTABLE = is_grantable",
	@orderby = "order by table_qualifier, table_name, privilege"

close col_priv_cursor

    drop table #column_privileges
    drop table #distinct_grantors
    drop table #sysprotects
    drop table #useful_groups
    drop table #results_table

/*
**  End of sp_ijdbc_aux_computeprivs
*/

go
exec sp_procxmode 'sp_ijdbc_aux_computeprivs', 'anymode'
go
grant execute on sp_ijdbc_aux_computeprivs to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getcolumnprivileges')
begin
	drop procedure sp_ijdbc_getcolumnprivileges
end
go
print "Installing sp_ijdbc_getcolumnprivileges"
go


create table #tmp_getcolumnprivileges (
         TABLE_CAT varchar(32) null,
         TABLE_SCHEM varchar(32) null,
         TABLE_NAME varchar(257) null,
         COLUMN_NAME varchar(257) null,
         GRANTOR varchar(32) null,
         GRANTEE varchar(32) null,
         PRIVILEGE varchar(128) null,
         IS_GRANTABLE char(3) null
         )
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
** sp_ijdbc_getcolumnprivilege 
*/

create procedure sp_ijdbc_getcolumnprivileges (
    @table_qualifier    varchar(32) = null,
    @table_owner        varchar(32) = null,
    @table_name         varchar(257)= null,
    @column_name varchar(257) = null)
as

    declare @tablename varchar(257)
    declare @tableowner varchar(128)
    declare @privlist varchar(128)
    declare @privdef  varchar(128)
    declare @searchstr char(3)
    declare @msg    	varchar(255)

    select @searchstr = 'SUV' /* SYSTEM USER VIEW types only */

    select @privlist = '193      ' + /* SELECT    */
                       '151      ' + /* REFERENCE */
                       '197      ' + /* UPDATE    */
                       '196      ' + /* DELETE    */
                       '195      '   /* INSERT    */

    select @privdef =  'SELECT   ' +
                       'REFERENCE' +
                       'UPDATE   ' +
                       'DELETE   ' +
                       'INSERT   '


    select @tablename = @table_name
    select @tableowner = @table_owner

    if (@tableowner is null)
    begin
        select @tableowner ='%'
    end

    if (@tablename is null)
    begin
        select @tablename ='%'
    end
    
    set nocount on
    if @@trancount = 0
    begin
           set chained off
    end
    else
    begin
         /* we are inside a transaction. catalog procedure sp_column privileges
         ** can't be run inside a transaction 
         */
         exec sp_getmessage 18040, @msg  output
         raiserror 18040, @msg, 'sp_column_privileges'
         return (1)
    end
 
    set transaction isolation level 1
 
    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like '#%' and db_name() != db_name(tempdb_id()))
    begin
        /* 
        ** 17676, 'This may be a temporary object. Please execute 
        ** procedure from your temporary database.'
        */
        exec sp_getmessage 17676, @msg out
        raiserror 17676 @msg
        return (1)
    end
 
    /*
    ** The table_qualifier should be same as the database name. Do the sanity 
    ** check if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
        /* set the table qualifier name */
        select @table_qualifier = db_name ()
    else
    begin
        if db_name() != @table_qualifier
        begin
             exec sp_getmessage 18039, @msg out
             raiserror 18039 @msg
             return (1)
        end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name 
    ** prefixed by the owner id
    */
    
    /*
    ** NOTE: SQL Server allows an underscore '_' in the table owner, even 
    **       though '_' is a single character wildcard.
    */
    if (charindex('%',@table_owner) > 0)
	begin
	  exec sp_getmessage 17993, @msg output
	  raiserror 17993 @msg, @table_owner
	  return(1)
	end

    if (@table_owner is null)
    begin
        exec sp_getmessage 17993, @msg output
	raiserror 17993 @msg, 'NULL'
	return(1)
    end
    else
    begin
        exec sp_ijdbc_escapeliteralforlike @table_owner output
    end

    if (@table_name is null) 
	begin
	  exec sp_getmessage 17993, @msg output
	  raiserror 17993 @msg, 'NULL'
	  return(1)
	end
		
    if (select count(*) from sysobjects 
        where user_name(uid) like @table_owner ESCAPE '\'
        and name like @table_name ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr) != 0
        ) = 0
    begin
        exec sp_getmessage 17674, @msg output
        raiserror 17674 @msg
        return 1
    end

     if @column_name is null
            select @column_name = '%'
        else
        begin
            if not exists (select * from syscolumns c, sysobjects o
               where user_name(o.uid) like @table_owner ESCAPE '\'
	        and o.name like @table_name ESCAPE '\'
	        and (charindex(substring(o.type,1,1), @searchstr) != 0)
		and c.id = o.id and c.name like @column_name ESCAPE '\')
            begin
                exec sp_getmessage 17563, @msg output
                raiserror 17563 @msg, @column_name
                return (1)
            end
        end

	
 select uid = o.uid, user_name = user_name(o.uid),
	oid = o.id, table_name = o.name, colid = c.colid,
       col_name = c.name , type = o.type
 into #objects_id
 from syscolumns c, sysobjects o
  where user_name(o.uid) like @table_owner ESCAPE '\'
                and o.name like @table_name ESCAPE '\'
                and (charindex(substring(o.type,1,1), @searchstr) != 0)
                and c.id = o.id and c.name like @column_name ESCAPE '\'


create table #tmp_grp_getcolumnprivileges ( TABLE_CAT varchar(32) null, TABLE_SCHEM varchar(32) null, TABLE_NAME varchar(257) null, COLUMN_NAME varchar(257) null, GRANTOR varchar(32) null, UID int null, GRANTEE varchar(32) null, PRIVILEGE varchar(128) null, IS_GRANTABLE char(3) null)

delete #tmp_getcolumnprivileges 

insert #tmp_grp_getcolumnprivileges
 SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = t.user_name,
        'TABLE_NAME' = t.table_name, 'COLUMN_NAME'= t.col_name, 
	'GRANTOR' = t.user_name,
	'UID' = t.uid,
        'GRANTEE' = t.user_name, 'PRIVILEGE' = 'SELECT', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=t.oid
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 193),0)) * 3 + 1, 3)

    FROM #objects_id as t, sysprotects as p
    WHERE
         not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(t.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=193
           AND p1.protecttype = 2)
	   AND (t.colid in (select v.number 
		from  master.dbo.spt_values v
		where convert(tinyint,substring(isnull(p.columns,0x1), 
			v.low,1))&v.high !=0
		and v.type ="P" and v.number <=1024) 
               or 0 in ( select v.number
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1),
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
                )


    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = t.user_name,
        'TABLE_NAME' = t.table_name, 'COLUMN_NAME'= t.col_name,
	 'GRANTOR' = t.user_name,
	  'UID'  = t.uid,
        'GRANTEE' = t.user_name, 'PRIVILEGE' = 'INSERT', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=t.oid
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 195),0)) * 3 + 1, 3)
    FROM #objects_id as t, sysprotects as p
    WHERE
         not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(t.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=195
           AND p1.protecttype = 2)
	   AND (t.colid in (select v.number 
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1), 
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
		or 0 in ( select v.number
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1),
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
                )

    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = t.user_name,
        'TABLE_NAME' = t.table_name, 'COLUMN_NAME'= t.col_name,
	'GRANTOR' = t.user_name,
	'UID'  = t.uid,
        'GRANTEE' = t.user_name, 'PRIVILEGE' = 'DELETE', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=t.oid
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 196),0)) * 3 + 1, 3)
    FROM #objects_id as t, sysprotects as p
    WHERE
         not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(t.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=196
           AND p1.protecttype = 2)
	   AND (t.colid in (select v.number 
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1), 
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
		or 0 in ( select v.number
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1),
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
                )

    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = t.user_name,
        'TABLE_NAME' = t.table_name, 'COLUMN_NAME'= t.col_name,
	'GRANTOR' = t.user_name,
	'UID'  = t.uid,
        'GRANTEE' = t.user_name, 'PRIVILEGE' = 'UPDATE', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=t.oid
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 197),0)) * 3 + 1, 3)
    FROM #objects_id as t, sysprotects as p
    WHERE
         not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(t.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor = p1.uid
           AND p1.action = 197
           AND p1.protecttype = 2)
	   AND (t.colid in (select v.number 
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1), 
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
		or 0 in ( select v.number
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1),
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
                )

    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = t.user_name,
        'TABLE_NAME' = t.table_name, 'COLUMN_NAME'= t.col_name,
	 'GRANTOR' = t.user_name,
	 'UID'  = t.uid,
        'GRANTEE' = t.user_name, 'PRIVILEGE' = 'REFERENCE', 'IS_GRANTABLE' =

        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=t.oid
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 151),0)) * 3 + 1, 3)
    FROM #objects_id as t, sysprotects as p
    WHERE

         not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(t.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=151
           AND p1.protecttype = 2)
	   AND (t.colid in (select v.number 
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1), 
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
		or 0 in ( select v.number
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1),
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
                )


    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = t.user_name,
        'TABLE_NAME' = t.table_name, 'COLUMN_NAME'= t.col_name,
        'GRANTOR' = user_name(p.grantor),
	'UID'  = p.uid,
        'GRANTEE' = user_name(p.uid),
        'PRIVILEGE' =
            rtrim(substring( @privdef,
                    charindex(rtrim(convert(char,p.action)), @privlist), 9)),
        substring('YESNO ', (p.protecttype * 3)+1, 3)
    FROM sysprotects p, #objects_id as t
    WHERE t.oid = p.id and protecttype < 2
        AND p.action in (193, 151, 197, 196, 195)
        AND charindex(substring(t.type,1,1),@searchstr)! = 0
	AND (t.colid in (select v.number 
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1), 
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
		or 0 in ( select v.number
                from  master.dbo.spt_values v
                where convert(tinyint,substring(isnull(p.columns,0x1),
                        v.low,1))&v.high !=0
                and v.type ="P" and v.number <=1024)
                )


    ORDER BY TABLE_SCHEM, TABLE_NAME, PRIVILEGE




/** Propagate the privileges from the groups 
 ** to the groups members.
 **/


insert #tmp_getcolumnprivileges
	select  t.TABLE_CAT, t.TABLE_SCHEM, t.TABLE_NAME,
    	t.COLUMN_NAME, t.GRANTOR, 'GRANTEE' = su.name, t.PRIVILEGE,
    	t.IS_GRANTABLE

	from #tmp_grp_getcolumnprivileges t , sysusers su
	where 
		t.UID = su.uid
    		and su.gid != su.uid

	union

	select  t.TABLE_CAT, t.TABLE_SCHEM, t.TABLE_NAME,
        t.COLUMN_NAME, t.GRANTOR, 'GRANTEE' = su.name, t.PRIVILEGE,
        t.IS_GRANTABLE
	from #tmp_grp_getcolumnprivileges t , sysusers su
	where 
		t.UID = su.gid
		and su.gid != su.uid
	

	

/*
** End of sp_ijdbc_getcolumnprivileges
*/

go
exec sp_procxmode 'sp_ijdbc_getcolumnprivileges', 'anymode'
go
grant execute on sp_ijdbc_getcolumnprivileges to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_gettableprivileges')
begin
	drop procedure sp_ijdbc_gettableprivileges
end
go
print "Installing sp_ijdbc_gettableprivileges"
go


create table #tmp_gettableprivileges (
        TABLE_CAT varchar(32) null,
        TABLE_SCHEM varchar(32) null,
        TABLE_NAME varchar(257) null,
        GRANTOR varchar(32) null,
        GRANTEE varchar(32) null,
        PRIVILEGE varchar(128) null,
        IS_GRANTABLE char(3) null
        )
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_gettableprivileges
*/

create procedure sp_ijdbc_gettableprivileges (
    @table_qualifier    varchar(32),
    @table_owner        varchar(32) = null,
    @table_name         varchar(257)= null)
as

    declare @tablename varchar(257)
    declare @tableowner varchar(128)
    declare @privlist varchar(128)
    declare @privdef  varchar(128)
    declare @searchstr char(3)

    select @searchstr = 'SUV' /* SYSTEM USER VIEW types only */

    select @privlist = '193      ' + /* SELECT    */
                       '151      ' + /* REFERENCE */
                       '197      ' + /* UPDATE    */
                       '196      ' + /* DELETE    */
                       '195      '   /* INSERT    */

    select @privdef =  'SELECT   ' +
                       'REFERENCE' +
                       'UPDATE   ' +
                       'DELETE   ' +
                       'INSERT   '


    select @tablename = @table_name
    select @tableowner = @table_owner

    if (@tableowner is null)
    begin
        select @tableowner ='%'
    end

    if (@tablename is null)
    begin
        select @tablename ='%'
    end

 delete #tmp_gettableprivileges

 insert #tmp_gettableprivileges

    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = user_name(s.uid),
        'TABLE_NAME' = name, 'GRANTOR' = user_name(s.uid),
        'GRANTEE' = user_name(s.uid), 'PRIVILEGE' = 'SELECT', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=s.id
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 193),0)) * 3 + 1, 3)
    FROM sysobjects as s, sysprotects as p
    WHERE
        name LIKE @tablename ESCAPE '\'
        AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr)! = 0
        AND not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=193
           AND p1.protecttype = 2)

    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = user_name(s.uid),
        'TABLE_NAME' = name, 'GRANTOR' = user_name(s.uid),
        'GRANTEE' = user_name(s.uid), 'PRIVILEGE' = 'INSERT', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=s.id
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 195),0)) * 3 + 1, 3)
    FROM sysobjects as s, sysprotects as p
    WHERE
        name LIKE @tablename ESCAPE '\'
        AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr)! = 0
        AND not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=195
           AND p1.protecttype = 2)
    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = user_name(s.uid),
        'TABLE_NAME' = name, 'GRANTOR' = user_name(s.uid),
        'GRANTEE' = user_name(s.uid), 'PRIVILEGE' = 'DELETE', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=s.id
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 196),0)) * 3 + 1, 3)
    FROM sysobjects as s, sysprotects as p
    WHERE
        name LIKE @tablename ESCAPE '\'
        AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr)! = 0
        AND not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=196
           AND p1.protecttype = 2)
    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = user_name(s.uid),
        'TABLE_NAME' = name, 'GRANTOR' = user_name(s.uid),
        'GRANTEE' = user_name(s.uid), 'PRIVILEGE' = 'UPDATE', 'IS_GRANTABLE' =
        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=s.id
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 197),0)) * 3 + 1, 3)
    FROM sysobjects as s, sysprotects as p
    WHERE
        name LIKE @tablename ESCAPE '\'
        AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr)! = 0
        AND not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor = p1.uid
           AND p1.action = 197
           AND p1.protecttype = 2)
    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = user_name(s.uid),
        'TABLE_NAME' = name, 'GRANTOR' = user_name(s.uid),
        'GRANTEE' = user_name(s.uid), 'PRIVILEGE' = 'REFERENCE', 'IS_GRANTABLE' =

        substring('YESNO ', (select isnull ((select p.protecttype
          where p.id=s.id
          AND p.protecttype != 2
          AND p.grantor = p.uid
          AND p.action = 151),0)) * 3 + 1, 3)
    FROM sysobjects as s, sysprotects as p
    WHERE
        name LIKE @tablename ESCAPE '\'
        AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr)! = 0

        AND not exists (select * from sysobjects s1, sysprotects p1 WHERE
           name LIKE @tablename ESCAPE '\'
           AND user_name(s.uid) LIKE @tableowner ESCAPE '\'
           AND charindex(substring(type,1,1),@searchstr)! = 0
           AND s1.id=p1.id
           AND p1.grantor=p1.uid
           AND p1.action=151
           AND p1.protecttype = 2)
    UNION
    SELECT 'TABLE_CAT' = db_name(), 'TABLE_SCHEM' = user_name(o.uid),
        'TABLE_NAME' = o.name, 'GRANTOR' = user_name(p.grantor),
        'GRANTEE' = user_name(p.uid),
        'PRIVILEGE' =
            rtrim(substring( @privdef,
                    charindex(rtrim(convert(char,p.action)), @privlist), 9)),
        substring('YESNO ', (p.protecttype * 3)+1, 3)
    FROM sysprotects p, sysobjects o
    WHERE o.id = p.id and protecttype < 2
        AND o.name LIKE @tablename ESCAPE '\'
        AND user_name(o.uid) LIKE @tableowner ESCAPE '\'
        AND p.action in (193, 151, 197, 196, 195)
        AND charindex(substring(type,1,1),@searchstr)! = 0
    ORDER BY TABLE_SCHEM, TABLE_NAME, PRIVILEGE

/*
** End of sp_ijdbc_gettableprivileges
*/
go
exec sp_procxmode 'sp_ijdbc_gettableprivileges', 'anymode'
go
grant execute on sp_ijdbc_gettableprivileges to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getcatalogs')
begin
	drop procedure sp_ijdbc_getcatalogs
end
go
print "Installing sp_ijdbc_getcatalogs"
go


create table #tmp_getcatalogs ( TABLE_CAT varchar(30) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/* 
** sp_ijdbc_getcatalogs
*/

CREATE PROCEDURE sp_ijdbc_getcatalogs 
as

    if @@trancount = 0
    begin
    	set chained off
    end

  delete #tmp_getcatalogs
    
    set transaction isolation level 1

	insert #tmp_getcatalogs
	    select name from master..sysdatabases order by name
go
exec sp_procxmode 'sp_ijdbc_getcatalogs', 'anymode'
go
grant execute on sp_ijdbc_getcatalogs to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_primarykey')
begin
	drop procedure sp_ijdbc_primarykey
end
go
print "Installing sp_ijdbc_primarykey"
go

create table #tmp_primarykey (
                         TABLE_CAT varchar(32) null,
                         TABLE_SCHEM     varchar(32) null,
                         TABLE_NAME      varchar(257) null,
                         COLUMN_NAME     varchar(257) null,
                        KEY_SEQ         smallint null,
                        PK_NAME     varchar(255) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_primarykey
*/


/*
** Altered from the ODBC sp_pkeys defined in sycsp11.sql.
**
** To facilitate eventually combining scripts for ODBC and JDBC,
** only the ordering of the arguments and the final select have been modified.
*/
/*
** note: there is one raiserror message: 18040
**
** messages for 'sp_ijdbc_primarykey'               18039, 18040
**
** 17461, 'Object does not exist in this database.'
** 18039, 'table qualifier must be name of current database.'
** 18040, 'catalog procedure %1! can not be run in a transaction.', sp_ijdbc_primarykey
**
*/

create procedure sp_ijdbc_primarykey
			   @table_qualifier varchar(32),
			   @table_owner 	varchar(32),
			   @table_name		varchar(512)
as
    declare @msg varchar(255)
    declare @keycnt smallint
    declare @maxkeycnt smallint
    declare @indexid smallint
    declare @indexname varchar(30)
    declare @i int
    declare @id int
    declare @actual_table_name varchar(512)
    
    select @actual_table_name = @table_name

    select @id = NULL

	set nocount on

	if (@@trancount = 0)
	begin
		set chained off
	end
	else
	begin	
		/* if inside a transaction */
		/* catalog procedure sp_ijdbc_primarykey can not be run in a transaction.*/
		exec sp_getmessage 18040, @msg output
		raiserror 18040 @msg, 'sp_ijdbc_primarykey'
		return (1)
	end

	set transaction isolation level 1

	if @table_qualifier is not null
	begin
		if db_name() != @table_qualifier
		begin	
			/* if qualifier doesn't match current database */
			/* 'table qualifier must be name of current database'*/
			exec sp_getmessage 18039, @msg output
			raiserror 18039 @msg 
			return (2)
		end
	end

    delete #tmp_primarykey

    
    exec sp_ijdbc_escapeliteralforlike @table_name

	if @table_owner is null
	begin
        select @table_owner = '%'
	end
			
	if (select count(*) from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name) = 0
	begin	
		/* 17461, 'Object does not exist in this database.' */
		exec sp_getmessage 17674, @msg output
		raiserror 17674 @msg 
		return (3)
	end

	create table #pkeys(
			 table_qualifier varchar(32),
			 table_owner     varchar(32),
			 table_name      varchar(257),
			 column_name     varchar(257),
			 key_seq	 smallint,
             		index_name     varchar(255))


    
	select id = o.id, uid = o.uid, indid= i.indid, name = i.name, 
					keycnt = case when (i.indid>=2)
							then i.keycnt-1
							else i.keycnt 
							end
	into #tempkey
        from sysobjects o, sysindexes i
        where i.id = o.id
	and user_name(o.uid) like @table_owner ESCAPE '\'
        and o.name = @table_name
	and status2 & 2 = 2 /* make sure it is a declarative constr */
	and status & 2048 = 2048 /* make sure it is a primary key */
       
    
	select @maxkeycnt = max(keycnt) 
		from #tempkey
    	select @i = 1
    
    	while @i <= @maxkeycnt
    	begin
    		insert #pkeys select db_name(), user_name(uid), @actual_table_name,
    			index_col(@actual_table_name, indid, @i, uid), @i, name
			 from #tempkey 
			where @i<=keycnt
    		select @i = @i + 1
    	end
    
        /*
        ** Go to the next user/object
        */
       
 

    

    /*
    ** Original ODBC query:
    **
	** select table_qualifier, table_owner, table_name, column_name, key_seq
	** from #pkeys
	** order by table_qualifier, table_owner, table_name, key_seq
    */
    /*
    ** Primary keys are not explicitly named, so name is always null.
    */

	insert #tmp_primarykey
    select table_qualifier as TABLE_CAT,
        table_owner as TABLE_SCHEM,
        table_name as TABLE_NAME,
        column_name as COLUMN_NAME,
        key_seq as KEY_SEQ,
        index_name as PK_NAME
	from #pkeys
	order by column_name
    
    drop table #pkeys
    drop table #tempkey
	return (0)

/*
**  End of sp_ijdbc_primarykey
*/
go
exec sp_procxmode 'sp_ijdbc_primarykey', 'anymode'
go
grant execute on sp_ijdbc_primarykey to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_sql_type_name')
begin
	drop procedure sp_ijdbc_sql_type_name
end
go
print "Installing sp_ijdbc_sql_type_name"
go


create table #tmp_sql_type_name (name varchar(257) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_sql_type_name
*/

 
/*
**  Implements RSMDA.getColumnTypeName
**  create a procedure that will query 
**  spt_jdatatype_info for the correct jdbc mapped datatype or
**  the datasource specific systable, to retrieve the correct type
**  or user defined datatype name, based on the parameters
**  @datatype = the protocol datatype value
**  @usrtype = the data source specifc user defined datatype value
*/

create procedure sp_ijdbc_sql_type_name
        @datatype  smallint,
        @usrtype   smallint
as
BEGIN

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

/* special case for types numericn and decimaln, they do not seem
** to have the correct mapping of usertype & datatype
*/
   /* if type is decimaln(106) map to decimal(55)
    * if type is numericn(108) map to numeric(63) 
    */

  delete #tmp_sql_type_name

   if (@datatype = 108)
   begin
	select @datatype = 63
   end
   else if (@datatype = 106)
   begin
	select @datatype = 55
   end

   /* if a usertype is greater than 100 that means it is a
    * user defined datatype, and it needs to be reference in
    * the datasource specific systype table.  If they are
    * user-defined numeric/decimal, then only use the usertype
    * for the search criteria (see the note on SPECIAL CASE below)
    * This is the fix for Bug 192969.
    */
   if (@usrtype > 100) 
   begin

	insert #tmp_sql_type_name
	 select name from systypes
	    where usertype = @usrtype
   end
   /* simply check spt_jdatatype_info for 
    * the predefined jdbc mapping for the types
    */
   else
   begin
	insert #tmp_sql_type_name 
       select j.type_name as name 
       from sybsystemprocs.dbo.spt_jdatatype_info j
       where j.ss_dtype = @datatype
   end
END

go
go
exec sp_procxmode 'sp_ijdbc_sql_type_name', 'anymode'
go
grant execute on sp_ijdbc_sql_type_name to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getbestrowidentifier')
begin
	drop procedure sp_ijdbc_getbestrowidentifier
end
go
print "Installing sp_ijdbc_getbestrowidentifier"
go


create table #tmp_getbestrowidentifier (
            SCOPE smallint null, COLUMN_NAME varchar(257) null,
            DATA_TYPE smallint null, TYPE_NAME varchar(32) null ,
            COLUMN_SIZE int null, BUFFER_LENGTH varchar(255) null,
            DECIMAL_DIGITS smallint null, PSEUDO_COLUMN smallint null)

go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_getbestrowidentifier
*/


/* Get a description of a table's optimal set of columns that uniquely 
** identifies a row
** Usually it's the unique primary key index column or the identity field
*/

create procedure sp_ijdbc_getbestrowidentifier (
				 @table_qualifier	varchar(32) = null,
				 @table_owner		varchar(32) = null,
				 @table_name		varchar(257),
				 @scope			int,
				 @nullable		smallint)
as
	declare @indid              int
	declare @table_id           int
	declare @dbname             char(30)
	declare @owner             char(30)
	declare @msg                char(70)

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1


	/* get database name */
	select @dbname = db_name()

	/* we don't want a temp table unless we're in our temporary db */
	if @table_name like '#%' and @dbname != db_name(tempdb_id())
	begin	
		exec sp_getmessage 17676, @msg output
		raiserror 17676 @msg
		return (1)
	end

	if @table_qualifier is not null
	begin
		/* if qualifier doesn't match current database */
		if @dbname != @table_qualifier
		begin	
			exec sp_getmessage 18039, @msg output
			raiserror 18039 @msg
			return (1)
		end
	end

    if (@table_owner is null) 
    begin
        select @table_owner ='%'
    end
    else
    begin
        
        if (charindex('%',@table_owner) > 0)
        begin
            exec sp_getmessage 17993, @msg output
            raiserror 17993 @msg, @table_owner
            return(1)
        end
        
        /*
        ** if there is a '_' character in @table_owner, 
        ** then we need to make it work literally in the like
        ** clause.
        */
        if (charindex('_', @table_owner) > 0)
        begin
            exec sp_ijdbc_escapeliteralforlike
                @table_owner output
        end
    end
    
    
    if (@table_name is null) 
    begin
       exec sp_getmessage 17993, @msg output
       raiserror 17993 @msg, 'NULL'
       return(1)
    end

    delete #tmp_getbestrowidentifier
    
    if ((select count(*) 
        from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name) = 0)
    begin
      exec sp_getmessage 17674, @msg output
      raiserror 17674 @msg, @table_name
      return
    end

    select owner = user_name(o.uid),
             full_table_name = user_name(o.uid)+'.'+@table_name,
             table_id = object_id(user_name(o.uid)+'.'+@table_name)
    into #temp_owner
    from sysobjects o
             where o.name like @table_name ESCAPE '\'
             and user_name(o.uid) like @table_owner ESCAPE '\'
 
   select min_indid = min (s.indid) , 
	  table_id = tow.table_id
   into #temp_ind
   from  sysindexes s, #temp_owner tow
         where s.indid >0
         and s.id = tow.table_id
         group by tow.table_id

        
        /* Sybase's only PSEUDO_COLUMN is called SYB_IDENTITY_COL and */
        /* is only generated when dboption 'auto identity' is set on */


        insert #tmp_getbestrowidentifier 
	 select convert(smallint, 0), 'SYB_IDENTITY_COL', 2, 'NUMERIC', 10,
                'not used', 0, 2
	from #temp_owner
                where exists (select name from syscolumns
                              where id=#temp_owner.table_id
                              and name = 'SYB_IDENTITY_COL')

	insert #tmp_getbestrowidentifier
	    select
                convert(smallint, 0),
		index_col(tpo.full_table_name,x.indid,c.colid),
                d.data_type + convert(smallint, isnull(d.aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(d.ss_dtype%35+1)+2-8/c2.length,1))
                        -60)),
                rtrim(substring(d.type_name, 1 + isnull(d.aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
                        -60), 13)),
                isnull(d.data_precision, convert(int,c2.length))
                        + isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c2.length,1))
                        -60)),
                'not used',
                    /*isnull(d.length, convert(int,c2.length))
                        + convert(int, isnull(d.aux,
                        ascii(substring('AAA<BB<DDDHJSPP',
                        2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
                        -64)),*/
                d.numeric_scale + convert(smallint,
                        isnull(d.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
                        -60)),
                1
	    from
            sysindexes x,
            syscolumns c,
            sybsystemprocs.dbo.spt_jdatatype_info d,
            systypes t,
            syscolumns c2,	/* self-join to generate list of index
                    ** columns and to extract datatype names */
	    #temp_owner tpo,
	    #temp_ind tind
            where
            x.id = tpo.table_id
	    and c2.name = index_col(tpo.full_table_name, tind.min_indid,c.colid)
            and c2.id =x.id
	    and tind.table_id = tpo.table_id
            and c.id = x.id
            and c.colid < keycnt + (x.status & 16) / 16
	    and x.indid = tind.min_indid
            and c2.type = d.ss_dtype
            and c2.usertype *= t.usertype
	    and not exists (select name from syscolumns
                         where id=tpo.table_id
                        and name = 'SYB_IDENTITY_COL')

    return (0)
go
exec sp_procxmode 'sp_ijdbc_getbestrowidentifier', 'anymode'
go
grant execute on sp_ijdbc_getbestrowidentifier to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getisolationlevels')
begin
	drop procedure sp_ijdbc_getisolationlevels
end
go
print "Installing sp_ijdbc_getisolationlevels"
go


/**
 * sp_ijdbc_getisolationlevels
 */
 

/**
 * <P> This procedure is used to determine which transaction isolation
 * levels are supported by this ASE server.  This proc is registered
 * with the spt_mda table to be executed when the user calls:
 * <CODE> DatabaseMetaData.supportsTransactionIsolationLevel(int) </CODE>.
 * If the int specified is found in the row returned by this procedure,
 * then that level is supported.  The levels are indicated by using the
 * integer mappings found in the java.sql.Connection interface.
 * <UL> All ASE versions currently support these levels:
 *              <LI> TRANSACTION_SERIALIZABLE  (8) and
 *              <LI> TRANSACTION_READ_COMMITTED  (2)            </UL>
 * <UL> ASE versions after 10.1 added support for these levels:
 *              <LI>  TRANSACTION_READ_UNCOMMITTED (1).         </UL>
 * <P> This procedure accesses the @@version string, determines the
 * version of ASE, and returns the appropriate levels.
 * <P> WARNING:  Should future versions of ASE support more transaction
 * isolation levels (e.g., TRANSACTION_REPEATABLE_READ (4)), this proc
 * must be modified.
 */
 
create procedure sp_ijdbc_getisolationlevels as

       select 8,2,1
   
    return (0)   
go
exec sp_procxmode 'sp_ijdbc_getisolationlevels', 'anymode'
go
grant execute on sp_ijdbc_getisolationlevels to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getindexinfo')
begin
	drop procedure sp_ijdbc_getindexinfo
end
go
print "Installing sp_ijdbc_getindexinfo"
go


create table #tmp_getindexinfo (
                TABLE_CAT  varchar (32) null,
                 TABLE_SCHEM varchar (32) null,
                 TABLE_NAME varchar (257) null,
                 NON_UNIQUE varchar (5) null,
                 INDEX_QUALIFIER varchar (257) null,
                 INDEX_NAME varchar (257) null,
                 TYPE smallint null,
                 ORDINAL_POSITION smallint null,
                 COLUMN_NAME varchar (257) null,
                 ASC_OR_DESC varchar (1) null,
                 CARDINALITY int null,
                 PAGES int null,
                 FILTER_CONDITION varchar (32) null
                )
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_getindexinfo
*/



/* getindexinfo returns information on the indexes of a page
** is unique is set to TRUE only indexes on indexes where it's value's must
** be unique are returned.
** approximate is a little needless because row_count() and data_pages()
** garantee alwys accurate data
*/

create procedure sp_ijdbc_getindexinfo (
	@table_qualifier	varchar(32) = NULL,
	@table_owner		varchar(32) = NULL,
	@table_name		varchar(257),
	@unique			varchar(5) ,
	@approximate 		char(5))
as
    declare @indid              int
    declare @lastindid          int
    declare @msg                varchar(250)
    declare @tableid            int
    
    /*
    ** Verify table qualifier is name of current database.
    */
    if @table_qualifier is not null
    begin
    	if db_name() != @table_qualifier
    	begin	/* If qualifier doesn't match current database */
    		/*
    		** 18039, 'Table qualifier must be name of current database.'
    		*/
    		exec sp_getmessage 18039, @msg output
    		raiserror 18039 @msg
    		return (1)
    	end
    end
    select @table_qualifier = db_name()
    
    if @@trancount > 0
    begin
    	/*
    	** 18040, 'Catalog procedure '%1!' can not be run in a transaction.
    	*/
    	exec sp_getmessage 18040, @msg output
    	raiserror 18040 @msg, 'sp_ijdbc_getindexinfo'
    	return (1)
    end
    else
    begin
    	set chained off
    end
    
    set transaction isolation level 1
    
    
    if (@table_owner is null)
    begin
        select @table_owner ='%'
    end
    
    if (@table_name is null) 
    begin
       exec sp_getmessage 17993, @msg output
       raiserror 17993 @msg, 'NULL'
       return(1)
    end

    if ((select count(*) 
        from sysobjects 
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name) = 0)
    begin
        exec sp_getmessage 17674, @msg output
        raiserror 17674 @msg
        return
    end

    delete #tmp_getindexinfo

    create table #TmpIndex(
    	table_qualifier	varchar(32),
    	table_owner	varchar(32),
    	table_name	varchar(257),
    	index_qualifier varchar(257) null,
    	index_name	varchar(257) null,
    	non_unique	varchar(5),
    	type		smallint,
    	seq_in_index	smallint null,
    	column_name	varchar(257) null,
    	collation	char(1) null,
    	index_id	int null,
    	cardinality	int null,
    	pages		int null,
    	filter_condition varchar(32) null,
    	status		smallint,
        table_id    int)


   
  
	select id, 
		full_table_name = user_name(uid) + '.' + name
	into #tmp_id
        from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name

    

        /*
        ** Start at lowest index id, while loop through indexes. 
        ** Create a row in #TmpIndex for every column in sysindexes, each is
        ** followed by an row in #TmpIndex with table statistics for the preceding
        ** index.
        */
        select distinct id = t.id, indid = x.indid 
	into #tmp_indid 
        	from sysindexes x , #tmp_id t
        	where x.id =  t.id
       		and x.indid > 0
       		and x.indid < 255
 		and x.indid is not null

        	insert #TmpIndex	/* Add all columns that are in index */
        	select
        		db_name(),		/* table_qualifier */
        		user_name(o.uid),	/* table_owner	   */
        		o.name,			/* table_name	   */
        		o.name, 		/* index_qualifier */
        		x.name,			/* index_name	   */
        		'FALSE',		/* non_unique	   */
        		1,			/* SQL_INDEX_CLUSTERED */
        		colid,			/* seq_in_index	   */
        		INDEX_COL(t.full_table_name,x.indid,colid),/* column_name	   */
        		index_colorder(t.full_table_name,x.indid,colid),
						/* collation	   */
        		tind.indid,			/* index_id 	   */
        		row_count(db_id(), x.id), /* cardinality */
        		data_pages(db_id(), x.id, 
						case 
							when x.indid = 1
							then 0
							else x.indid
						end), /* pages */
        		null,			/* Filter condition not available */
        					/* in SQL Server*/
        		x.status, 		/* Status */	
                       t.id    /* table id, internal use for updating the non_unique field */
        	from sysindexes x, syscolumns c,
			sysobjects o , #tmp_id t, #tmp_indid tind
        	where x.id = t.id
		and tind.id=t.id
        		and x.id = o.id
        		and x.id = c.id
        		and c.colid < keycnt+(x.status&16)/16
        		and x.indid = tind.indid 
        
            /*
            ** only update the inserts for the current
            ** owner.table
            */
            update #TmpIndex
                set non_unique = 'TRUE'
		from #TmpIndex, #tmp_id
                where status&2 != 2 /* If non-unique index */
                and table_id = id 
    
        
        /* 
        ** Now add row with table statistics 
        */
        insert #TmpIndex
        	select
        		db_name(),		/* table_qualifier */
        		user_name(o.uid),	/* table_owner	   */
        		o.name, 		/* table_name	   */
        		null,			/* index_qualifier */
        		null,			/* index_name	   */
        		'FALSE',		/* non_unique	   */
        		0,			/* SQL_table_STAT  */
        		null,			/* seq_in_index	*/
        		null,			/* column_name	   */
        		null,			/* collation	   */
        		0,			/* index_id 	   */
        		row_count(db_id(), x.id),  /* cardinality */
        		data_pages(db_id(), x.id, 
						case 
							when x.indid = 1
							then 0
							else x.indid
						end), /* pages */
        		null,			/* Filter condition not available */
        					/* in SQL Server*/
        		0,			/* Status */
                 t.id   /* tableid */
        	from sysindexes x, sysobjects o, #tmp_id t
        	where o.id = t.id 
        		and x.id = o.id
        		and (x.indid = 0 or x.indid = 1)	
        	/*  
        	** If there are no indexes
        	** then table stats are in a row with indid = 0
        	*/


    update #TmpIndex
        set
            type = 3,		/* SQL_INDEX_OTHER */
            cardinality = NULL,
            pages = NULL
        where index_id > 1		/* If non-clustered index */
           
    if (@unique!='1')
    begin
    	/* If all indexes desired */
	insert #tmp_getindexinfo
    	select
    		table_qualifier TABLE_CAT,
    		table_owner TABLE_SCHEM,
    		table_name TABLE_NAME,
    		non_unique NON_UNIQUE,
    		index_qualifier INDEX_QUALIFIER,
    		index_name INDEX_NAME,
    		type TYPE,
    		seq_in_index ORDINAL_POSITION,
    		column_name COLUMN_NAME,
    		collation ASC_OR_DESC,
    		cardinality CARDINALITY,
    		pages PAGES,
    		filter_condition FILTER_CONDITION			
    	from #TmpIndex
    	order by non_unique, type, index_name, seq_in_index
    end
    else	
    begin
    	/* else only unique indexes desired */
	insert #tmp_getindexinfo
    	select
    		table_qualifier TABLE_CAT,
    		table_owner TABLE_SCHEM,
    		table_name TABLE_NAME,
    		non_unique NON_UNIQUE,
    		index_qualifier INDEX_QUALIFIER,
    		index_name INDEX_NAME,
    		type TYPE,
    		seq_in_index ORDINAL_POSITION,
    		column_name COLUMN_NAME,
    		collation ASC_OR_DESC,
    		cardinality CARDINALITY,
    		pages PAGES,
    		filter_condition FILTER_CONDITION
    	from #TmpIndex
    	where non_unique = 'FALSE' 	
    	order by non_unique, type, index_name, seq_in_index
    
    end
    
    drop table #TmpIndex
    
    return (0)

/*
**  End of sp_ijdbc_getindexinfo
*/
go
exec sp_procxmode 'sp_ijdbc_getindexinfo', 'anymode'
go
grant execute on sp_ijdbc_getindexinfo to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_stored_procedures')
begin
	drop procedure sp_ijdbc_stored_procedures
end
go
print "Installing sp_ijdbc_stored_procedures"
go


create table #tmp_stored_procedures (
        PROCEDURE_CAT varchar(32) null,
        PROCEDURE_SCHEM varchar(32) null,
        PROCEDURE_NAME varchar(257) null,
        num_input_params int null,
        num_output_params int null,
        num_result_sets int null,
        REMARKS varchar(254) null,
        PROCEDURE_TYPE int null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_stored_procedures
*/


/*
** Altered from the ODBC sp_ijdbc_procedures defined in sycsp11.sql.
**
** New column 'PROCEDURE_TYPE' was added to support JDBC spec. This
** column is to indicate if the procedure returns a result. If 0,
** column will be evalued as DatabaseMetadata.procedureResultUnknown;
** this means that the procedure MAY return a result.
*/
/*
** Messages for 'sp_ijdbc_stored_procedures'	18041
**
** 18041, 'Stored Procedure qualifier must be name of current database.'
**
*/

create procedure sp_ijdbc_stored_procedures
@sp_qualifier	varchar(32) = null,	/* stored procedure qualifier; 
					** For the SQL Server, the only valid
					** values are NULL or the current 
					** database name
					*/
@sp_owner	varchar(32) = null,	/* stored procedure owner */
@sp_name	varchar(261) = null	/* stored procedure name */
as

declare	@msg	varchar(90)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

delete #tmp_stored_procedures

/* If qualifier is specified */
if @sp_qualifier is not null
begin
	/* If qualifier doesn't match current database */
	if db_name() != @sp_qualifier
	begin
		/* If qualifier is not specified */
		if @sp_qualifier = ''
		begin
			/* in this case, we need to return an empty 
			** result set because the user has requested a 
			** database with an empty name 
			*/
			select @sp_name = ''
			select @sp_owner = ''
		end

		/* qualifier is specified and does not match current database */
		else
		begin	
			/* 
			** 18041, 'Stored Procedure qualifer must be name of
			** current database'
			*/
			exec sp_getmessage 18041, @msg out
			raiserror 18041 @msg
			return (1)
		end
	end
end

/* If procedure name not supplied, match all */
if @sp_name is null
begin  
	select @sp_name = '%'
end

/* If procedure owner not supplied, match all */
if @sp_owner is null	
	select @sp_owner = '%'

/* 
** Retrieve the stored procedures and associated info on them
*/

insert #tmp_stored_procedures
select  PROCEDURE_CAT = db_name(),
	PROCEDURE_SCHEM = user_name(o.uid),
	PROCEDURE_NAME = o.name +';'+ ltrim(str(p.number,5)),
	num_input_params = -1,		/* Constant since value unknown */
	num_output_params = -1,	        /* Constant since value unknown */
	num_result_sets = -1,		/* Constant since value unknown */
	REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
	PROCEDURE_TYPE = 0
from sysobjects o,sysprocedures p,sysusers u
where o.name like @sp_name ESCAPE '\'
	and p.sequence = 0
	and user_name(o.uid) like @sp_owner ESCAPE '\'
	and o.type = 'P'		/* Object type of Procedure */
	and p.id = o.id
	and u.uid = user_id()		/* constrain sysusers uid for use in 
					** subquery 
					*/

	and (suser_id() = 1 		/* User is the System Administrator */
	     or  o.uid = user_id()	/* User created the object */
					/* here's the magic..select the highest 
					** precedence of permissions in the 
					** order (user,group,public)  
					*/

	     /*
	     ** The value of protecttype is
	     **
	     **		0  for grant with grant
	     **		1  for grant and,
	     **		2  for revoke
	     **
	     ** As protecttype is of type tinyint, protecttype/2 is
	     ** integer division and will yield 0 for both types of
	     ** grants and will yield 1 for revoke, i.e., when
	     ** the value of protecttype is 2.  The XOR (^) operation
	     ** will reverse the bits and thus (protecttype/2)^1 will
	     ** yield a value of 1 for grants and will yield a
	     ** value of zero for revoke.
	     **
	     ** Normal uids have values upto 16383, roles have uids
	     ** from 16384 upto 16389 and uids of groups start from
	     ** 16390 onwards.
	     **
	     ** If there are several entries in the sysprotects table
	     ** with the same Object ID, then the following expression
	     ** will prefer an individual uid entry over a group entry
	     ** and prefer a group entry over a role entry.
	     **
	     ** For example, let us say there are two users u1 and u2
	     ** with uids 4 and 5 respectiveley and both u1 and u2
	     ** belong to a group g12 whose uid is 16390.  procedure p1
	     ** is owned by user u0 and user u0 performs the following
	     ** actions:
	     **
	     **		grant exec on p1 to g12
	     **		revoke grant on p1 from u1
	     **
	     ** There will be two entries in sysprotects for the object
	     ** p1, one for the group g12 where protecttype = grant (1)
	     ** and one for u1 where protecttype = revoke (2).
	     **
	     ** For the group g12, the following expression will
	     ** evaluate to:
	     **
	     **		(((+)*abs(16390-16383))*2) + ((1/2)^1))
	     **		= ((14) + (0)^1) = 14 + 1 = 15
	     **
	     ** For the user entry u1, it will evaluate to:
	     **
	     **		(((+)*abs(4-16383)*2) + ((2/2)^1))
	     **		= ((abs(-16379)*2 + (1)^1)
	     **		= 16379*2 + 0 = 32758
	     **
	     ** As the expression evaluates to a bigger number for the
	     ** user entry u1, select max() will chose 32758 which,
	     ** ANDed with 1 gives 0, i.e., sp_ijdbc_stored_procedures will
	     ** not display this particular procedure to the user.
	     **
	     ** When the user u2 invokes sp_ijdbc_stored_procedures, there is
	     ** only one entry for u2, which is the entry for the group
	     ** g12, and so this entry will be selected thus allowing
	     ** the procedure in question to be displayed.
	     **
	     ** Notice that multiplying by 2 makes the number an
	     ** even number (meaning the last digit is 0) so what
	     ** matters at the end is (protecttype/2)^1.
	     **
	     */

	     or ((select max(((sign(uid)*abs(uid-16383))*2)
			     + ((protecttype/2)^1))
		   from sysprotects p
		   where p.id = o.id		/* outer join to correlate 
						** with all rows in sysobjects 
						*/
		   /*
		   ** get rows for public, current users, user's groups
		   */
		   and (p.uid = 0  		/* get rows for public */
		        or p.uid = user_id()	/* current user */
		        or p.uid = u.gid) 	/* users group */
			     
		   /*
		   ** check for SELECT, EXECUTE privilege.
		   */
	           and (action in (193,224))	/* check for SELECT,EXECUTE 
						** privilege 
						*/
		   )&1 			/* more magic...normalize GRANT */
	    	  ) = 1	 		/* final magic...compare Grants	*/
	     /*
	     ** If one of any user defined roles or contained roles for the
	     ** user has permission, the user has the permission
	     */
	     or exists(select 1
		from	sysprotects p1,
			master.dbo.syssrvroles srvro,
			sysroles ro
		where	p1.id = o.id
			and p1.uid = ro.lrid
			and ro.id = srvro.srid
			and has_role(srvro.name, 1) > 0
			and p1.action = 224))

order by PROCEDURE_SCHEM, PROCEDURE_NAME

go
exec sp_procxmode 'sp_ijdbc_stored_procedures', 'anymode'
go
grant execute on sp_ijdbc_stored_procedures to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getprocedurecolumns')
begin
	drop procedure sp_ijdbc_getprocedurecolumns
end
go
print "Installing sp_ijdbc_getprocedurecolumns"
go


create table #tmp_getprocedurecolumns
    (PROCEDURE_CAT   varchar(32)  null,
     PROCEDURE_SCHEM varchar(32)  null,
     PROCEDURE_NAME  varchar(257)  not null,
     COLUMN_NAME     varchar(257)  not null,
     COLUMN_TYPE     smallint     not null,
     DATA_TYPE       smallint     not null,
     TYPE_NAME       varchar(32)  not null,
     PRECISION     int          not null,
     LENGTH          int          not null,
     SCALE           smallint     not null,
     RADIX           smallint     not null,
     NULLABLE        smallint     not null,
     REMARKS         varchar(255) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_getprocedurecolumns
*/


create procedure sp_ijdbc_getprocedurecolumns (
@sp_qualifier   varchar(32) = null,     /* stored procedure qualifier*/
@sp_owner       varchar(32) = null,     /* stored procedure owner */
@sp_name        varchar(257),            /* stored procedure name */
@column_name    varchar(257) = null)
as
declare @msg 			varchar(250)
declare @group_num              int
declare @semi_position          int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

if @sp_qualifier is not null
begin
	if db_name() != @sp_qualifier
	begin
		if @sp_qualifier = ''
		begin
			select @sp_name = ''
			select @sp_owner = ''
		end
		else
		begin	
			/* 
			** 18041, 'Stored Procedure qualifer must be name of
			** current database'
			*/
			exec sp_getmessage 18041, @msg out
			raiserror 18041 @msg
			return (1)
		end
	end
end
else
	select @sp_qualifier = db_name()

select @semi_position = charindex(';',@sp_name)
if (@semi_position > 0)
begin   /* If group number separator (;) found */
    select @group_num = convert(int,substring(@sp_name, @semi_position + 1, 2))
    select @sp_name = substring(@sp_name, 1, @semi_position -1)
end
else
begin   /* No group separator, so default to group number of 1 */
    select @group_num = 1
end      

if (@sp_owner is null) select @sp_owner ='%'
if (@sp_name is null) select @sp_name ='%'
if (@column_name is null) select @column_name ='%'

/*
 * build a temporary table for holding the results.
 * The following is from the JDBC specification at
 * DatabaseMetaData.getProcedureColumns
 */

delete #tmp_getprocedurecolumns

create table #jproccols_res
    (PROCEDURE_CAT   varchar(32)  null,
     PROCEDURE_SCHEM varchar(32)  null,
     PROCEDURE_NAME  varchar(257)  not null,
     COLUMN_NAME     varchar(257)  not null,
     COLUMN_TYPE     smallint     not null, 
     DATA_TYPE       smallint     not null,
     TYPE_NAME       varchar(32)  not null,
     PRECISION     int          not null,
     LENGTH          int          not null,
     SCALE           smallint     not null, 
     RADIX           smallint     not null, 
     NULLABLE        smallint     not null,
     REMARKS         varchar(255) null,
     colid           int          not null /* hidden, used for ordering */
    )

/*
 * insert defined parameters (if any)
 */
INSERT INTO #jproccols_res
SELECT DISTINCT
    PROCEDURE_CAT   = db_name(),
    PROCEDURE_SCHEM = user_name(o.uid),
    PROCEDURE_NAME  = o.name+';'+ ltrim(str(p.number,5)),
    COLUMN_NAME      = c.name,
    COLUMN_TYPE     = convert(smallint, 0), 	/*No distinction possible in SQL Server */
    DATA_TYPE       = jdt.data_type,
    TYPE_NAME       = jdt.type_name,
    PRECISION    = (isnull(convert(int, c.prec),
                      isnull(convert(int, jdt.data_precision),
                      convert(int, c.length)))
                      +isnull(jdt.aux, convert(int,
                      ascii(substring('???AAAFFFCKFOLS',
                      2*(jdt.ss_dtype%35+1)+2-8/c.length,1))-60))),    
    LENGTH          = (isnull(convert(int, c.length), 
                      convert(int, jdt.length)) +
                      convert(int, isnull(jdt.aux,
                      ascii(substring('AAA<BB<DDDHJSPP',
                      2*(jdt.ss_dtype%35+1)+2-8/c.length,
                      1))-64))),
    SCALE           = (isnull(isnull(convert(smallint, c.scale), 
                       convert(smallint, jdt.numeric_scale)), 0) +
                        convert(smallint, isnull(jdt.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(jdt.ss_dtype%35+1)+2-8/c.length,
                        1))-60))),    
    RADIX           = convert(smallint, 0), 
    NULLABLE        = convert(smallint, 2),  /* procedureNullableUnknown */
    REMARKS         = printfmt,
    colid           = c.colid /* parameter position order */
FROM syscolumns c, sysobjects o, sysusers u, sysprocedures p,
     sybsystemprocs.dbo.spt_jdatatype_info jdt
WHERE jdt.ss_dtype = c.type 
    and c.id = o.id and p.id = o.id 
    and user_name(o.uid) like @sp_owner ESCAPE '\'
    and u.uid = user_id()
    and o.type ='P'
    and o.name like @sp_name ESCAPE '\'
    and c.name like @column_name ESCAPE '\'
    and c.number = @group_num
    and p.number = @group_num


/*
 * add the 'return parameter'
 */
INSERT INTO #jproccols_res    
SELECT DISTINCT
    PROCEDURE_CAT   = db_name(),
    PROCEDURE_SCHEM = user_name(o.uid),
    PROCEDURE_NAME  = o.name+';'+ ltrim(str(p.number,5)),
    COLUMN_NAME     = 'RETURN_VALUE',
    COLUMN_TYPE     = convert(smallint, 5), /* procedureColumnReturn */
    DATA_TYPE       = jdt.data_type,
    TYPE_NAME       = jdt.type_name,
    PRECISION     = (isnull(convert(int, jdt.data_precision),
                      convert(int, jdt.length))
                      +isnull(jdt.aux, convert(int,
                      ascii(substring('???AAAFFFCKFOLS',
                      2*(jdt.ss_dtype%35+1)+2-8/jdt.length,1))-60))),    
    LENGTH          = (isnull(jdt.length, convert(int, t.length)) +
                      convert(int, isnull(jdt.aux,
                      ascii(substring('AAA<BB<DDDHJSPP',
                      2*(jdt.ss_dtype%35+1)+2-8/t.length,
                      1))-64))),
    SCALE           = (convert(smallint, jdt.numeric_scale) +
                        convert(smallint, isnull(jdt.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(jdt.ss_dtype%35+1)+2-8/jdt.length,
                        1))-60))),    
    RADIX           = convert(smallint, 0), 
    NULLABLE        = convert(smallint, 0), /* procedureNoNulls */
    REMARKS         = 'procedureColumnReturn',
    colid           = 0 /* always the first parameter */
FROM sybsystemprocs.dbo.spt_jdatatype_info jdt,
     sysobjects o, sysusers u, sysprocedures p,
     systypes t
WHERE jdt.ss_dtype = 56 /* return parameter is an int */
    and t.type = jdt.ss_dtype
    and p.id = o.id 
    and user_name(o.uid) like @sp_owner ESCAPE '\'
    and u.uid = user_id()
    and o.type ='P'
    and o.name like @sp_name ESCAPE '\'
    and 'RETURN_VALUE' like @column_name ESCAPE '\'
    and p.number = @group_num


/*
 * return the data to the client
 */
insert #tmp_getprocedurecolumns
SELECT PROCEDURE_CAT, PROCEDURE_SCHEM, PROCEDURE_NAME, COLUMN_NAME,
    COLUMN_TYPE, DATA_TYPE, TYPE_NAME, PRECISION, LENGTH, SCALE,
    RADIX, NULLABLE, REMARKS
FROM #jproccols_res
ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, colid
/*
* cleanup
*/
go
go
exec sp_procxmode 'sp_ijdbc_getprocedurecolumns', 'anymode'
go
grant execute on sp_ijdbc_getprocedurecolumns to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getversioncolumns')
begin
	drop procedure sp_ijdbc_getversioncolumns
end
go
print "Installing sp_ijdbc_getversioncolumns"
go


create table #tmp_getversioncolumns (SCOPE smallint null, 
				COLUMN_NAME varchar(257) null, 
				DATA_TYPE int null, 
				TYPE_NAME varchar(8) null, 
				COLUMN_SIZE int null, 
				BUFFER_LENGTH smallint null, 
				DECIMAL_DIGITS smallint null, 
				PSEUDO_COLUMN smallint null)


go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_getversioncolumns
*/

create procedure sp_ijdbc_getversioncolumns (
				 @table_qualifier	varchar(32) = null,
				 @table_owner		varchar(32) = null,
				 @table_name		varchar(257))
as
	declare @indid			int
	declare @table_id		int
	declare @dbname			char(30)
	declare @msg			char(70)


	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* get database name */
	select @dbname = db_name()

	/* we don't want a temp table unless we're in our temporary db */
	if @table_name like '#%' and @dbname != db_name(tempdb_id())
	begin	
		exec sp_getmessage 17676, @msg output
		raiserror 17676 @msg
		return (1)
	end

	if @table_qualifier is not null
	begin
		/* if qualifier doesn't match current database */
		if @dbname != @table_qualifier
		begin	
			exec sp_getmessage 18039, @msg output
			raiserror 18039 @msg
			return (1)
		end
	end

    if (@table_owner is null) select @table_owner = '%'
    else
    begin
        /*        
        ** NOTE: SQL Server allows an underscore '_' in the table owner, even 
        **       though it is a single character wildcard.
        */
        if (charindex('%',@table_owner) > 0)
        begin
            exec sp_getmessage 17993, @msg output
            raiserror 17993 @msg, @table_owner
            return(1)
        end
        exec sp_ijdbc_escapeliteralforlike @table_owner output
    end
    
    if (@table_name is null) 
    begin
       exec sp_getmessage 17993, @msg output
       raiserror 17993 @msg, 'NULL'
       return(1)
    end

 delete #tmp_getversioncolumns
    
    if (select count(*) 
        from sysobjects
        where user_name(uid) 
        like @table_owner ESCAPE '\'
      	and name = @table_name) = 0 
    begin
      exec sp_getmessage 17674, @msg output
      raiserror 17674 @msg
      return 1
    end
    else 
    begin
	select table_owner = user_name(uid),
		full_table_name = case when user_name(uid) is null
					then @table_name
					else
					user_name(uid)+ '.' + @table_name
					end,
		table_id = case when user_name(uid) is null
			   then object_id(@table_name)
			   else object_id(user_name(uid)+ '.' + @table_name)
			   end
	  into #tmp_owner
     	   from sysobjects 
    		where name = @table_name and user_name(uid) like @table_owner


	    insert into #tmp_getversioncolumns  select
		convert(smallint, 0),
		c.name ,
		(select data_type from 
			sybsystemprocs.dbo.spt_jdatatype_info
			where type_name = 'binary'),
		'BINARY',
		isnull(d.data_precision,
				convert(int,c.length))
				+ isnull(d.aux, convert(int,
				ascii(substring('???AAAFFFCKFOLS',
				2*(d.ss_dtype%35+1)+2-8/c.length,1))
				-60)),
		18, /* Number of chars = 2^4 byte + '0x' */
		isnull(d.numeric_scale + convert(smallint,
				isnull(d.aux,
				ascii(substring('<<<<<<<<<<<<<<?',
				2*(d.ss_dtype%35+1)+2-8/c.length, 1))
				-60)),0),
		1
 		from
			systypes t, syscolumns c, 
			sybsystemprocs.dbo.spt_jdatatype_info d,
			#tmp_owner
		where
			c.id = table_id
			and c.type = d.ss_dtype
			and c.usertype = 80	/* TIMESTAMP */
			and t.usertype = 80	/* TIMESTAMP */
    end

go
exec sp_procxmode 'sp_ijdbc_getversioncolumns', 'anymode'
go
grant execute on sp_ijdbc_getversioncolumns to public
go
dump tran master with truncate_only
go
declare @tempdbname varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_default_charset')
begin
	drop procedure sp_ijdbc_default_charset
end
go
print "Installing sp_ijdbc_default_charset"
go


create  table  #tmp_default_charset (DEFAULT_CHARSET varchar(30) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_default_charset
*/

/* 
** obtain the SQL server default charset
*/


/*
**  create a procedure that will query the datasource
**  specific syscharset, and sysconfigures tables, and do a join to 
**  determine what is the correct charset that has been set as a default
**  on the server.
*/

create procedure sp_ijdbc_default_charset
as

    delete #tmp_default_charset

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

   insert  #tmp_default_charset 
    select name
 	
	from master.dbo.syscharsets
       	where ((select value from master.dbo.sysconfigures      
               where config=131)  /* default charset id */
              = master.dbo.syscharsets.id)
go
exec sp_procxmode 'sp_ijdbc_default_charset', 'anymode'
go
grant execute on sp_ijdbc_default_charset to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_classes_in_jar')
begin
	drop procedure sp_ijdbc_classes_in_jar
end
go
print "Installing sp_ijdbc_classes_in_jar"
go


create table #tmp_classes_in_jar (xtname char(255) null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_classes_in_jar
*/

create procedure sp_ijdbc_classes_in_jar (
        @jar_name varchar(255))
as

 delete #tmp_classes_in_jar

 insert #tmp_classes_in_jar
    select 
        sjc.xtname 
    from 
        sysjars sj, sysxtypes sjc 
    where 
        sj.jid = sjc.xtcontainer and sj.jname = @jar_name
go
exec sp_procxmode 'sp_ijdbc_classes_in_jar', 'anymode'
go
grant execute on sp_ijdbc_classes_in_jar to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getudts')
begin
	drop procedure sp_ijdbc_getudts
end
go
print "Installing sp_ijdbc_getudts"
go


/* 
** JDBC 2.0
** 
** DatabaseMetaData.getUDTs(catalog, schema, typeNamePattern, int types[])
**
** NOT SUPPORTED
*/
create procedure sp_ijdbc_getudts (
        @table_qualifier        varchar(128) = NULL,
        @table_owner            varchar(128) = NULL,
        @type_name_pattern      varchar(128),
        @types                  varchar(128))
as
    declare @empty_string varchar(1)
    declare @empty_int int
    
    select @empty_string = ''
    select @empty_int = 0

    /* not supported, return an empty result set */    
    select 
        TYPE_CAT = @empty_string,
        TYPE_SCHEM = @empty_string,
        TYPE_NAME = @empty_string,
        CLASS_NAME = @empty_string,
        DATA_TYPE = @empty_int,
        REMARKS = @empty_string
    where
        1 = 2
go
exec sp_procxmode 'sp_ijdbc_getudts', 'anymode'
go
grant execute on sp_ijdbc_getudts to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_getxacoordinator')
begin
	drop procedure sp_ijdbc_getxacoordinator
end
go
print "Installing sp_ijdbc_getxacoordinator"
go


create  table #tmp_getxacoordinator (TxnStyle int null, 
			RequiredRole varchar(30) null, 
			Status int null)
go

/*
** JDBC 2.0 extensions (JTA support)
** 
** SybDatabaseMetaData.getXACoordinatorType()
** 
** It is expected that this is an interim solution, and
** a more robust implementation will be provided by ASE.
** 
** returns a resultset of the form:
** TxnStyle (indicating which transaction coordinator is being used.
** 0 means none.
**
** RequiredRoles (indicates what role the user must have to use)
** NULL means none.
**
** Status (a bitmask of capabilities that the coordinator provides)
** 0x00000001 - set if user has necessary role
** 0x00000002 - set if txns can migrate among connections
** 0x00000004 - set if multiple connections can participate in same txn simultaneously
**
*/


create procedure sp_ijdbc_getxacoordinator
as

declare @txnMode int
declare @role varchar(30)
declare @status int
declare @srv_version int

delete #tmp_getxacoordinator

select @srv_version = convert(int, value) from master.dbo.sysconfigures  
                                       where config=122

/* For 12.0 and higher, jConnect expects to use DTM001. */
/* DTM001 is defined as 2 in SybDataSource.RMTYPE_ASE_XA_DTM. */
/* Users must have dtm_tm_role to use DTM.   */
/* Lastly, determine whether or not user has */
/* dtm_tm_role when setting the status bits. */
if (@srv_version >= 12000) 
begin
   /* verify that the 12.0 server is configured for XA using DTM */
   if ((select cur.value from master.dbo.syscurconfigs cur, master.dbo.sysconfigures conf 
        where conf.comment = 'enable DTM' and cur.config = conf.config) != 0)
   begin
        select @txnMode=2, @role='dtm_tm_role'
   end
   else
   begin
        select @txnMode=0, @role='dtm_tm_role'
   end

   /* now check for role permission */
   if (charindex('dtm_tm_role', show_role()) != 0) 
   begin 
        select @status=7 
   end
   else
   begin 
        select @status=6
   end
end
else 
/* pre 12.0 is currently not supported */
begin
   select @txnMode=0, @role=NULL, @status=0
end

/* return results and name the columns */

insert #tmp_getxacoordinator
select TxnStyle=@txnMode, RequiredRole=@role, Status=@status

go
go
exec sp_procxmode 'sp_ijdbc_getxacoordinator', 'anymode'
go
grant execute on sp_ijdbc_getxacoordinator to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_jar_by_name')
begin
	drop procedure sp_ijdbc_jar_by_name
end
go
print "Installing sp_ijdbc_jar_by_name"
go


create table #tmp_jar_by_name (jbinary image null)
go

/*
**  sp_ijdbc_jar_by_name
*/

create procedure sp_ijdbc_jar_by_name (
        @jar_name varchar(255))
as

delete #tmp_jar_by_name

insert #tmp_jar_by_name
    select
        sj.jbinary
    from
        sysjars sj
    where 

        jname = @jar_name
go
go
exec sp_procxmode 'sp_ijdbc_jar_by_name', 'anymode'
go
grant execute on sp_ijdbc_jar_by_name to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_jar_for_class')
begin
	drop procedure sp_ijdbc_jar_for_class
end
go
print "Installing sp_ijdbc_jar_for_class"
go



create table #tmp_jar_for_class
        (jbinary image null)
go

/*
**  sp_ijdbc_jar_for_class
*/

create procedure sp_ijdbc_jar_for_class (
        @class_name varchar(255))
as

   delete #tmp_jar_for_class

   insert  #tmp_jar_for_class
    select
        sj.jbinary
    from
        sysjars sj, sysxtypes sjc
    where
        sjc.xtname = @class_name and sj.jid = sjc.xtcontainer


go
exec sp_procxmode 'sp_ijdbc_jar_for_class', 'anymode'
go
grant execute on sp_ijdbc_jar_for_class to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ijdbc_class_for_name')
begin
	drop procedure sp_ijdbc_class_for_name
end
go
print "Installing sp_ijdbc_class_for_name"
go


create table #tmp_class_for_name (xtbinaryoffrow image null)
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go

/*
**  sp_ijdbc_class_for_name
*/

create procedure sp_ijdbc_class_for_name (
        @class_name varchar(255))
as

  delete #tmp_class_for_name

   insert #tmp_class_for_name
    select
        xtbinaryoffrow
    from 
        sysxtypes 
    where 
        xtname = @class_name




go
exec sp_procxmode 'sp_ijdbc_class_for_name', 'anymode'
go
grant execute on sp_ijdbc_class_for_name to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

/*
** Drop all temporary tables created in jdbc* 
** procedures
*/

drop table #tmp_getschemas
go
drop table #tmp_class_for_name 
go
drop table #tmp_classes_in_jar 
go
drop table #tmp_columns 
go
drop table #tmp_convert_datatype 
go
drop table #tmp_datatype_info 
go
drop table #tmp_fkeys 
go
drop table #tmp_function_escapes  
go
drop table #tmp_getbestrowidentifier 
go
drop table #tmp_getcatalogs 
go
drop table #tmp_getcolumnprivileges
go
drop table #tmp_getindexinfo 
go
drop table #tmp_getprocedurecolumns
go
drop table #tmp_gettableprivileges 
go
drop table #tmp_getversioncolumns 
go
drop table #tmp_jar_by_name 
go
drop table #tmp_jar_for_class
go
drop table #tmp_primarykey 
go
drop table #tmp_sql_type_name 
go
drop table #tmp_stored_procedures 
go
drop table #tmp_tables 
go

declare @tempdbname	varchar(30)
select @tempdbname = db_name(@@tempdbid)
dump tran @tempdbname with truncate_only
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_volchanged')
begin
	drop procedure sp_volchanged
end
go
print "Installing sp_volchanged"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_volchanged"
** 
** 19958, "Backup Server policy is set to '%1!'."
*/

create procedure sp_volchanged
@session_id	int,			/* session identifier		*/
@devname	varchar(255),		/* device requesting vol chg	*/
@action		varchar(255)=NULL,	/* BServer action string	*/
@fname		varchar(17)=NULL,	/* file name on device		*/
@vname		varchar(6)=NULL,	/* name to init new volume with */
@bs_name        varchar(255)=NULL	/* name of backup server */
as

declare	@server	varchar(30)	/* server name, if network dump	*/
declare @blank	int		/* index to " " when parsing @devname	*/
declare @len	int		/* length of @devname, for parsing	*/
declare @pname	varchar(255)	/* translated physical device name	*/
declare @status	int		/* RPC status				*/

declare	@bs_policy	varchar(255)	/* Backup server policy */
declare @msg		varchar(1024)	/* Display BS policy */
declare @bs_rpc		varchar(255)
declare	@bs_net_name	varchar(255)

if @@trancount = 0
begin
	set chained off
end
set cis_rpc_handling off
set transaction isolation level 1

if (lower(@devname) like "% at %")
begin
	/*
	** <device_name> AT <host_name> -- parse the device and host
	** names into separate arguments for transmission
	*/
	select @len = datalength(@devname)
	select @blank = charindex(" ", @devname)
	select @server = ltrim(
			   substring(
			     ltrim(
			 	substring(@devname, @blank, @len)), 3, @len))
	select @devname = rtrim(substring(@devname, 1, @blank))
end
else
begin
	/* No host given -- select the local server */
	select @server = NULL

	/* and do logical name translation */
	select @pname = phyname
	from master..sysdevices
	where name = @devname
	  and (status & 16) = 16
	if (@pname is not NULL)
		select @devname = @pname
end

/*
** If the Multiple Backup server feature is enabled with Backup server policy
** as $dedicated or $roundrobin and parameter bs_name is not provided,
** raise error to specify particular Backup server name.
*/
if (@bs_name = NULL)
begin
	select @bs_policy = srvnetname from master..sysservers where srvname = "SYB_BACKUP"

	if ((lower(@bs_policy) = "$dedicated") or (lower(@bs_policy) = "$roundrobin"))
	begin
		/* 19958, "Backup Server policy is set to '%1!'." */
		exec sp_getmessage 19958, @msg output
		print @msg, @bs_policy
		return
	end
	else
		select @bs_name = "SYB_BACKUP"
end	
else
begin
	select @bs_net_name = @bs_name
	select @bs_name = NULL
	select @bs_name = srvname from master..sysservers where srvnetname = @bs_net_name
	
	if (@bs_name = NULL)
	begin
		select @bs_name = @bs_net_name
		select @bs_net_name = NULL
		select @bs_net_name = srvnetname from master..sysservers where srvname = @bs_name

		if (@bs_net_name = NULL)
		begin
			/* 19960, "Backup Server '%1!' is not configured in sysservers." */
			exec sp_getmessage 19960, @msg output
			print @msg, @bs_name
			return
		end
	end
	
	/* 19970, "Executing RPC as_volume_changed at Backup Server '%1!'('%2!')." */
	exec sp_getmessage 19970, @msg output
	print @msg, @bs_name, @bs_net_name
end	

select @bs_rpc = @bs_name + '...as_volume_changed'
exec @status = @bs_rpc @server, @session_id, @devname, @action, @fname, @vname
return (@status)
go
exec sp_procxmode 'sp_volchanged', 'anymode'
go
grant execute on sp_volchanged to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_checkreswords')
begin
	drop procedure sp_checkreswords
end
go
print "Installing sp_checkreswords"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

if exists (select name from sysobjects where name = "sp_checkreswords")
	drop proc sp_checkreswords
go
/*
**Messages for "sp_checkreswords"	18035
**
** 17232, "No user with the specified name exists in the current database."
** 18035, "Reserved Words Used as Database Object Names for Database, "
** 18036, " Upgrade renames sysobjects.schema to sysobjects.schemacnt."
** 18037, " Found no reserved words used as names for database-wide objects."
** 18038, " Found no reserved words used as database object names."
*/
create procedure sp_checkreswords 
@user_name_param	varchar(30) = NULL
as


declare @msg		varchar(1024)

declare @baduse_cnt	int		/* Return the count of items that */
					/* have reserved word names.	  */
declare @owner_cnt	int		/* Count of owner-based bad items */

declare @uid_param	int
declare @user_name	varchar(30)
declare @dbname		varchar(30)
declare	@uid		int

/*
** Note: do not set isolation level, because this sproc must run in
** 4.x as well as System 10.
**
** Also, do not call sp_getmessage since this sproc must run on 4.8
** which cannot support the '%1!' syntax in the print statement.
** The main side affect of this is that the messages printed out by
** this sproc are not localized.
*/

set nocount on

/*
** 18035, "Reserved Words Used as Database Object Names for Database, "
**
** NOTE:  sp_getmessage is not used for retrieving message text
** because this sproc must also run on 4.8 servers which cannot
** support the '%1!' syntax in the print statement.
*/
select @dbname = db_name()
select @msg = description from master.dbo.sysmessages
        where error = 18035
        and langid is NULL
select @msg = @msg + @dbname + "."
print @msg
print ""

select @baduse_cnt = 0

create table #uids
(
	uid		int NULL,
	catagory	char(1)
)

if (@user_name_param is NULL or @user_name_param = "dbo")
begin
	/*
	** 18036, " Upgrade renames sysobjects schema to sysobjects schemacnt."
	**
	** NOTE:  sp_getmessage is not used for retrieving message text
	** because this sproc must also run on 4.8 servers which cannot
	** support the '%1!' syntax in the print statement.
	*/
	select @msg = description from master.dbo.sysmessages
        	where error = 18036
        	and langid is NULL
	print @msg
	print ""
end

if (@user_name_param is not NULL)
begin
	select @uid_param = user_id(@user_name_param)
	if (@uid_param is NULL)
	begin
		/*
		** 17232, "No user with the specified name exists in the 
		**	   current database."
		**
		** NOTE:  sp_getmessage is not used for retrieving message text
		** because this sproc must also run on 4.8 servers which cannot
		** support the '%1!' syntax in the print statement.
		*/
		select @msg = description from master.dbo.sysmessages
        		where error = 17232
        		and langid is NULL
		print @msg
		return(0)
	end

	insert #uids 
		select o.uid, "c"
		from sysobjects o, master.dbo.spt_values v, syscolumns c
		where lower(c.name) = v.name and v.type = 'W' 
			and c.id = o.id 
			and o.uid = @uid_param
			and not (o.id  = 1 and c.name = "schema")
		group by o.uid
		order by o.uid

	insert #uids 
		select o.uid, "i"
		from sysobjects o, master.dbo.spt_values v, sysindexes i
		where lower(i.name) = v.name and v.type = 'W' 
			and i.id = o.id 
			and o.uid = @uid_param
			and i.indid != 0 and i.indid != 255
		group by o.uid
		order by o.uid

	insert #uids
		select o.uid, "o"
		from sysobjects o, master.dbo.spt_values v
		where lower(o.name) = v.name and v.type = 'W'  
			and o.uid = @uid_param
		group by o.uid
		order by o.uid

	insert #uids
		select t.uid, "t"
		from systypes t, master.dbo.spt_values v
		where lower(t.name) = v.name and v.type = 'W'  
			and t.uid = @uid_param
		group by t.uid
		order by t.uid
end
else
begin
	/*
	** Get the uids into a temp table.
	*/

	insert #uids 
		select o.uid, "c"
		from sysobjects o, master.dbo.spt_values v, syscolumns c
		where lower(c.name) = v.name and v.type = 'W' 
			and c.id = o.id 
			and not (o.id  = 1 and c.name = "schema")
		group by o.uid
		order by o.uid

	insert #uids 
		select o.uid, "i"
		from sysobjects o, master.dbo.spt_values v, sysindexes i
		where lower(i.name) = v.name and v.type = 'W' 
			and i.id = o.id 
			and i.indid != 0 and i.indid != 255
		group by o.uid
		order by o.uid

	insert #uids
		select o.uid, "o"
		from sysobjects o, master.dbo.spt_values v
		where lower(o.name) = v.name and v.type = 'W'  
		group by o.uid
		order by o.uid

	insert #uids
		select t.uid, "t"
		from systypes t, master.dbo.spt_values v
		where lower(t.name) = v.name and v.type = 'W'  
		group by t.uid
		order by t.uid
end

/* Not using cursors because this sproc must run in 4.x, in order for 
** clients to check their databases before upgrade.
*/

select @user_name = min(user_name(uid)) from #uids

while (@user_name is not NULL)
begin
	/* Print the owner-specific information:
	**    columns, indexes, objects(tables, sprocs, etc.), and datatypes
	*/

	select @uid = user_id(@user_name)
	select "Owner" = @user_name 

	if exists (select * from #uids
		where user_name(uid) = @user_name and catagory = "c")
	begin
		select "Table" = o.name,
			"Reserved Word Column Names " = c.name
		from sysobjects o, master.dbo.spt_values v, syscolumns c
		where lower(c.name) = v.name and v.type = 'W'
			and c.id = o.id
			and o.uid = @uid
			and not (o.id  = 1 and c.name = "schema")
		order by o.name, c.name

		select @baduse_cnt = @baduse_cnt + @@rowcount
	end

	if exists (select * from #uids
		where user_name(uid) = @user_name and catagory = "i")
	begin
		select "Table" = o.name,
			"Reserved Word Index Names" = i.name
		from sysobjects o, master.dbo.spt_values v, sysindexes i
		where lower(i.name) = v.name and v.type = 'W'
			and i.id = o.id
			and o.uid = @uid
			and i.indid != 0 and i.indid != 255
		order by o.name, i.name

		select @baduse_cnt = @baduse_cnt + @@rowcount
	end

	if exists (select * from #uids
		where user_name(uid) = @user_name and catagory = "o")
	begin
		select  "Object Type" = convert(char(30), x.name),
			"Reserved Word Object Names" = o.name
		from sysobjects o, master.dbo.spt_values v,
			master.dbo.spt_values x
		where lower(o.name) = v.name and v.type = 'W' 
			and o.uid = @uid
			and o.sysstat & 2063 = x.number
			and x.type = "O"
		order by x.name, o.name

		select @baduse_cnt = @baduse_cnt + @@rowcount
	end

	if exists (select * from #uids 
		where user_name(uid) = @user_name and catagory = "t")
	begin
		select "Reserved Word Datatype Names" = t.name
		from systypes t, master.dbo.spt_values v
		where lower(t.name) = v.name and v.type = 'W'
			and t.uid = @uid
		order by t.name

		select @baduse_cnt = @baduse_cnt + @@rowcount
	end

	/* Get next id  */
	select @user_name = min(user_name(uid)) from #uids
		where user_name(uid) > @user_name

	/* If there are more user names, print a dividing mark between them. */
	if (@user_name is not NULL)
	begin
		select "-------------------------------------------------------------"
	end
end


if (@user_name_param is NULL)
begin

	select @owner_cnt = @baduse_cnt

	if (@baduse_cnt != 0)
	begin
		select "-------------------------------------------------------------"
	end
	select "Database-wide Objects" = " "

	/*
	** Print the database wide objects: users and segments
	*/

	if exists (select * from sysusers u, master.dbo.spt_values v
			where lower(u.name) = v.name and v.type = 'W'
				and u.name != "public")
	begin
		select "Reserved Word User Names" = u.name
		from sysusers u, master.dbo.spt_values v
		where lower(u.name) = v.name and v.type = 'W'
			and u.name != "public"
		order by u.name

		select @baduse_cnt = @baduse_cnt + @@rowcount
	end

	if exists (select * from syssegments s, master.dbo.spt_values v
			where lower(s.name) = v.name and v.type = 'W'
				and s.name != "default")
	begin
		select "Reserved Word Segment Names" = s.name
		from syssegments s, master.dbo.spt_values v
		where lower(s.name) = v.name and v.type = 'W'
			and s.name != "default"
		order by s.name

		select @baduse_cnt = @baduse_cnt + @@rowcount
	end


	if (db_name() = "master")
	begin
		/* Print the Server-wide information:
		**	logins, charsets, databases, and languages
		*/

		if exists (select * from master.dbo.syslogins l, 
				master.dbo.spt_values v
				where lower(l.name) = v.name and v.type = 'W')
		begin
			select "Reserved Word Login Names" = l.name
			from master.dbo.syslogins l, master.dbo.spt_values v
			where lower(l.name) = v.name and v.type = 'W'
			order by l.name

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.syscharsets c, 
				master.dbo.spt_values v
				where lower(c.name) = v.name and v.type = 'W')
		begin
			select "Reserved Word Charset Names" = c.name
			from master.dbo.syscharsets c, master.dbo.spt_values v
			where lower(c.name) = v.name and v.type = 'W'
			order by c.name

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.sysdatabases d, 
				master.dbo.spt_values v
				where lower(d.name) = v.name and v.type = 'W')
		begin
			select "Reserved Word Database Names" = d.name
			from master.dbo.sysdatabases d, master.dbo.spt_values v
			where lower(d.name) = v.name and v.type = 'W'
			order by d.name

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.syslanguages l, 
				master.dbo.spt_values v
				where lower(l.name) = v.name and v.type = 'W')
		begin
			select "Reserved Word Language Names" = l.name
			from master.dbo.syslanguages l, master.dbo.spt_values v
			where lower(l.name) = v.name and v.type = 'W'
			order by l.name

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.sysdevices d, 
				master.dbo.spt_values v
				where lower(d.name) = v.name and v.type = 'W')
		begin
			select "Reserved Word Device Names" = d.name
			from master.dbo.sysdevices d, master.dbo.spt_values v
			where lower(d.name) = v.name and v.type = 'W'
			order by d.name

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.sysremotelogins r, 
							master.dbo.spt_values v
			where lower(r.remoteusername) = v.name and v.type = 'W')
		begin
			select "Reserved Word Remote Logins" = 
							r.remoteusername
			from master.dbo.sysremotelogins r, 
				master.dbo.spt_values v
			where lower(r.remoteusername) = v.name and v.type = 'W'
			order by r.remoteusername

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.sysservers s, 
				master.dbo.spt_values v
			where lower(s.srvname) = v.name and v.type = 'W')
		begin
			select "Reserved Word Server Names" = s.srvname
			from master.dbo.sysservers s, master.dbo.spt_values v
			where lower(s.srvname) = v.name and v.type = 'W'
			order by s.srvname

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end

		if exists (select * from master.dbo.sysservers s, 
				master.dbo.spt_values v
			where lower(s.srvnetname) = v.name and v.type = 'W')
		begin
			select "Reserved Word ServerNetNames" = s.srvnetname
			from master.dbo.sysservers s, master.dbo.spt_values v
			where lower(s.srvnetname) = v.name and v.type = 'W'
			order by s.srvnetname

			select @baduse_cnt = @baduse_cnt + @@rowcount
		end
	end
	if (@baduse_cnt != 0 and @owner_cnt = @baduse_cnt)
	begin
		/*
		** 18037, " Found no reserved words used as names for 
		**	    database-wide objects."
		**
		** NOTE:  sp_getmessage is not used for retrieving message text
		** because this sproc must also run on 4.8 servers which cannot
		** support the '%1!' syntax in the print statement.
		*/
		select @msg = description from master.dbo.sysmessages
        		where error = 18037
        		and langid is NULL
		print @msg
	end
end


if (@baduse_cnt = 0)
begin
	/*
	** 18038, " Found no reserved words used as database object names."
	**
	** NOTE:  sp_getmessage is not used for retrieving message text
	** because this sproc must also run on 4.8 servers which cannot
	** support the '%1!' syntax in the print statement.
	*/
	select @msg = description from master.dbo.sysmessages
        	where error = 18038
        	and langid is NULL
	print @msg
end

return(@baduse_cnt)
go
go
exec sp_procxmode 'sp_checkreswords', 'anymode'
go
grant execute on sp_checkreswords to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_tables')
begin
	drop procedure sp_tables
end
go
print "Installing sp_tables"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	10.0	1.1	06/16/93	sproc/tables */

/*
** Messages for "sp_tables"         18039
**
** 17676, "This may be a temporary object. Please execute procedure from your 
**         temporary database."
**
** 18039, "Table qualifier must be name of current database"
**
*/
create procedure sp_tables
@table_name		varchar(289)  = null,
@table_owner     	varchar(289)  = null,
@table_qualifier 	varchar(289)  = null,
@table_type		varchar(100) = null
as

declare @type1 varchar(3)
declare @tableindex int
declare @issa int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* temp table */
if (@table_name like "#%" and
   db_name() != db_name(tempdb_id()))
begin
	/*
        ** Can return data about temp. tables only in session's temporary db
        */
		raiserror 17676
	return(1)
end

/*
** Special feature #1:	enumerate databases when owner and name
** are blank but qualifier is explicitly '%'.  
*/
if @table_qualifier = '%' and
	@table_owner = '' and
	@table_name = ''
begin	

	/*
	** If enumerating databases 
	*/
	select
		table_qualifier = name,
		table_owner = null,
		table_name = null,
		table_type = 'Database',

		/*
		** Remarks are NULL 
		*/
		remarks = null
		from master..sysdatabases

		/*
		** eliminate MODEL database 
		*/
		where name != 'model'
		order by table_qualifier
end

/*
** Special feature #2:	enumerate owners when qualifier and name
** are blank but owner is explicitly '%'.
*/
else if @table_qualifier = '' and
	@table_owner = '%' and
	@table_name = ''
	begin	

		/*
		** If enumerating owners 
		*/
		select distinct
			table_qualifier = null,
			table_owner = user_name(uid),
			table_name = null,
			table_type = 'Owner',

		/*
		** Remarks are NULL 
		*/
		remarks = null
		from sysobjects
		order by table_owner
	end
	else
	begin 

		/*
		** end of special features -- do normal processing 
		*/
		if @table_qualifier is not null
		begin
			if db_name() != @table_qualifier
			begin
				if @table_qualifier = ''
				begin  	

					/*
					** If empty qualifier supplied
					** Force an empty result set 
					*/
					select @table_name = ''
					select @table_owner = ''
				end
				else
				begin

					/*
					** If qualifier doesn't match current 
					** database. 
					*/
					raiserror 18039
					return 1
				end
			end
		end
		if @table_type is null
		begin	

			/*
			** Select all ODBC supported table types 
			*/
			select @type1 = 'SUV'
		end
		else
		begin
			/*
			** TableType are case sensitive if CS server 
			*/
			select @type1 = null

			/*
			** Add System Tables 
			*/
			if (charindex("'SYSTEM TABLE'",@table_type) != 0)
				select @type1 = @type1 + 'S'

			/*
			** Add User Tables 
			*/
			if (charindex("'TABLE'",@table_type) != 0)
				select @type1 = @type1 + 'U'

			/*
			** Add Views 
			*/
			if (charindex("'VIEW'",@table_type) != 0)
				select @type1 = @type1 + 'V'
		end
		if @table_name is null
		begin	

			/*
			** If table name not supplied, match all 
			*/
			select @table_name = '%'
		end
		else
		begin
			if (@table_owner is null) and 
			   (charindex('%', @table_name) = 0)
			begin	

			/*
			** If owner not specified and table is specified 
			*/
				if exists (select * from sysobjects
					where uid = user_id()
					and id = object_id(@table_name)
					and (type = 'U' or type = 'V' 
						or type = 'S'))
				begin	

				/*
				** Override supplied owner w/owner of table 
				*/
					select @table_owner = user_name()
				end
			end
		end

		/*
		** If no owner supplied, force wildcard 
		*/
		if @table_owner is null 
			select @table_owner = '%'

		if (suser_id() = 1 or charindex('sa_role', show_role()) > 0)
			select @issa = 1
		else
			select @issa = 0

		select
			table_qualifier = db_name(),
			table_owner = user_name(o.uid),
			table_name = o.name,
			table_type = rtrim ( 
					substring('SYSTEM TABLE            TABLE       VIEW       ',
					/*
					** 'S'=0,'U'=2,'V'=3 
					*/
					(ascii(o.type)-83)*12+1,12)),

			/*
			** Remarks are NULL
			*/
			remarks = null
		from sysobjects o
		where
			/* Special case for temp. tables.  Match ids */
			(o.name like @table_name or o.id=object_id(@table_name))
			and user_name(o.uid) like @table_owner

			/*
			** Only desired types
			*/
			and charindex(substring(o.type,1,1),@type1)! = 0 
		and (
                @issa = 1          /* User is the System Administrator */
                or o.uid = user_id()    /* User created the object */
                                        /* here's the magic..select the highest
                                        ** precedence of permissions in the
                                        ** order (user,group,public)
                                        */
 
                /*
                ** The value of protecttype is
                **
                **      0  for grant with grant
                **      1  for grant and,
                **      2  for revoke
                **
                ** As protecttype is of type tinyint, protecttype/2 is
                ** integer division and will yield 0 for both types of
                ** grants and will yield 1 for revoke, i.e., when
                ** the value of protecttype is 2.  The XOR (^) operation
                ** will reverse the bits and thus (protecttype/2)^1 will
                ** yield a value of 1 for grants and will yield a
                ** value of zero for revoke.
                **
	        ** For groups, uid = gid. We shall use this to our advantage.
                **
                ** If there are several entries in the sysprotects table
                ** with the same Object ID, then the following expression
                ** will prefer an individual uid entry over a group entry
                **
                ** For example, let us say there are two users u1 and u2
                ** with uids 4 and 5 respectiveley and both u1 and u2
                ** belong to a group g12 whose uid is 16390.  table t1
                ** is owned by user u0 and user u0 performs the following
                ** actions:
                **
                **      grant select on t1 to g12
                **      revoke select on t1 from u1
                **
                ** There will be two entries in sysprotects for the object t1,
                ** one for the group g12 where protecttype = grant (1) and
                ** one for u1 where protecttype = revoke (2).
                **
                ** For the group g12, the following expression will
                ** evaluate to:
                **
                **      ((abs(16390-16390)*2) + ((1/2)^1)
                **      = ((0) + (0)^1) = 0 + 1 = 1
                **
                ** For the user entry u1, it will evaluate to:
                **
                **      (((+)*abs(4-16390)*2) + ((2/2)^1))
                **      = (abs(-16386)*2 + (1)^1)
                **      = 16386*2 + 0 = 32772
                **
                ** As the expression evaluates to a bigger number for the
                ** user entry u1, select max() will chose 32772 which,
                ** ANDed with 1 gives 0, i.e., sp_tables will not display
                ** this particular table to the user.
                **
                ** When the user u2 invokes sp_tables, there is only one
                ** entry for u2, which is the entry for the group g12, and
                ** so the group entry will be selected thus allowing the
                ** table t1 to be displayed.
                **
		** ((select max((abs(uid-u.gid)*2)
	        ** 		+ ((protecttype/2)^1))
         	**
                ** Notice that multiplying by 2 makes the number an
                ** even number (meaning the last digit is 0) so what
                ** matters at the end is (protecttype/2)^1.
                **
                **/
 
                or ((select max((abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
                        from sysprotects p, sysusers u2
                        where p.id = o.id      /* outer join to correlate
                                                ** with all rows in sysobjects
                                                */
			and u2.uid = user_id()
			/*
			** get rows for public, current users, user's groups
			*/
		      	and (p.uid = 0 or 		/* public */
			     p.uid = user_id() or	/* current user */ 
			     p.uid = u2.gid)		/* users group */ 

			/*
			** check for SELECT, EXECUTE privilege.
			*/
		 	and (p.action in (193,224)))&1

			/*
			** more magic...normalise GRANT
			** and final magic...compare
			** Grants.
			*/
			) = 1
		/*
		** If one of any user defined roles or contained roles for the
		** user has permission, the user has the permission
		*/
		or exists(select 1
			from sysprotects p1,
				master.dbo.syssrvroles srvro,
				sysroles ro
			where p1.id = o.id
			and p1.uid = ro.lrid
			and ro.id = srvro.srid
			and has_role(srvro.name, 1) > 0
			and p1.action = 193))
		order by table_type, table_qualifier, table_owner, table_name
end
go
exec sp_procxmode 'sp_tables', 'anymode'
go
grant execute on sp_tables to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_special_columns')
begin
	drop procedure sp_special_columns
end
go
print "Installing sp_special_columns"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	10.0	1.0	9 JUL 93	sproc/src/special_columns */

/* 
** Messages for "sp_special_columns"
**
** 17863, "There is no table named %1! in the current database."
** 18039, "Table qualifier must be name of current database."
** 18042, "Illegal value for 'col_type' argument. Legal values are 'V' or 'R'."
**
*/

create procedure sp_special_columns (
				 @table_name		varchar(257),
				 @table_owner		varchar(257) = null,
				 @table_qualifier	varchar(257) = null,
				 @col_type		char(1) = 'R' )
as
	declare @indid			int
	declare @table_id		int
	declare @dbname			char(255)
	declare @full_table_name	char(520)

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* get database name */
	select @dbname = db_name()

	/* we don't want a temp table unless we're in tempdb */
	if @table_name like "#%" and @dbname != db_name(tempdb_id())
	begin	
		/* 17863, "There is no table named %1! in the current database." */
		raiserror 17863, @table_name
		return (1)
	end

	if @table_qualifier is not null
	begin
		if @dbname != @table_qualifier
		begin	
			/* 18039, "Table qualifier must be name of current database." */
			raiserror 18039
			return (1)
		end
	end

	if @table_owner is null
	begin	/* if unqualified table name */
		select @full_table_name = @table_name
	end
	else
	begin	/* qualified table name */
		select @full_table_name = @table_owner + '.' + @table_name
	end

	/* get object ID */
	select @table_id = object_id(@full_table_name)

	if @col_type = 'V'
	begin /* if ROWVER, just run that query */
		select
			scope = convert(smallint, 0),
			column_name = c.name,
			data_type = d.data_type + convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
			type_name = t.name,
			"precision" = isnull(d.data_precision,
					convert(int,c.length))
					+ isnull(d.aux, convert(int,
					ascii(substring("???AAAFFFCKFOLS",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
			length = isnull(d.length, convert(int,c.length))
					+ convert(int,
					isnull(d.aux,
					ascii(substring("AAA<BB<DDDHJSPP",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-64)),
			scale = d.numeric_scale + convert(smallint,
					isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-60))
		from
			systypes t, syscolumns c, sybsystemprocs.dbo.spt_datatype_info d
		where
			c.id = @table_id
			and c.type = d.ss_dtype
			and c.usertype = 80	/* TIMESTAMP */
			and t.usertype = 80	/* TIMESTAMP */
		return (0)
	end

	if @col_type != 'R'
	begin
		/* 18042, "Illegal value for 'col_type' argument. Legal values are 'V' or 'R'." */

		raiserror 18042
		return (1)
	end

	/* An identity column is the most optimal unique identifier */
	if exists (select colid from syscolumns
		where id = @table_id and (status&128) = 128)
	begin
	    select
		scope = convert(smallint, 0),
		column_name = c.name,
		data_type = d.data_type + convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		type_name = rtrim(substring(d.type_name,
					1 + isnull(d.aux,
					ascii(substring("III<<<MMMI<<A<A",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-60), 18)),
		"precision" = isnull(d.data_precision, convert(int,c.length))
					+ isnull(d.aux, convert(int,
					ascii(substring("???AAAFFFCKFOLS",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		length = isnull(d.length, convert(int,c.length))
					+ convert(int, isnull(d.aux,
					ascii(substring("AAA<BB<DDDHJSPP",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-64)),
		scale = d.numeric_scale + convert(smallint,
					isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-60))
	    from
		syscolumns c,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	    where
		c.id = @table_id
		and (c.status&128) = 128
		and c.type = d.ss_dtype
		and c.usertype *= t.usertype
	    return (0)
	end

	/* ROWID, now find the id of the 'best' index for this table */

	select @indid = (
		select min(indid)
		from sysindexes
		where
			status & 2 = 2		/* if unique index */
			and id = @table_id
			and indid > 0)		/* eliminate table row */

	 select
		scope = convert(smallint, 0),
		column_name = index_col(@full_table_name,indid,c.colid),
		data_type = d.data_type + convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c2.length,1))
					-60)),
		type_name = rtrim(substring(d.type_name,
					1 + isnull(d.aux,
					ascii(substring("III<<<MMMI<<A<A",
					2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
					-60), 18)),
		"precision" = isnull(d.data_precision, convert(int,c2.length))
					+ isnull(d.aux, convert(int,
					ascii(substring("???AAAFFFCKFOLS",
					2*(d.ss_dtype%35+1)+2-8/c2.length,1))
					-60)),
		length = isnull(d.length, convert(int,c2.length))
					+ convert(int, isnull(d.aux,
					ascii(substring("AAA<BB<DDDHJSPP",
					2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
					-64)),
		scale = d.numeric_scale + convert(smallint,
					isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
					-60))
	from
		sysindexes x,
		syscolumns c,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		syscolumns c2	/* self-join to generate list of index
				** columns and to extract datatype names */
	where
		x.id = @table_id
		and c2.name = index_col(@full_table_name, @indid,c.colid)
		and c2.id =x.id
		and c.id = x.id
		and c.colid < keycnt + (x.status & 16) / 16
		and x.indid = @indid
		and c2.type = d.ss_dtype
		and c2.usertype *= t.usertype
	return (0)
go
go
exec sp_procxmode 'sp_special_columns', 'anymode'
go
grant execute on sp_special_columns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_columns')
begin
	drop procedure sp_columns
end
go
print "Installing sp_columns"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% " */
/*      10.0        07/20/93        sproc/columns */
 

/* This is the version for servers which support UNION */

/* This routine is intended for support of ODBC connectivity.  Under no
** circumstances should changes be made to this routine unless they are
** to fix ODBC related problems.  All other users are at there own risk!
**
** Please be aware that any changes made to this file (or any other ODBC
** support routine) will require Sybase to recertify the SQL server as
** ODBC compliant.  This process is currently being managed internally
** by the "Interoperability Engineering Technology Solutions Group" here
** within Sybase.
*/

CREATE PROCEDURE sp_columns (
				 @table_name		varchar(257),
				 @table_owner		varchar(255) = null,
				 @table_qualifier	varchar(32) = null,
				 @column_name		varchar(257) = null )
AS
    declare @msg                varchar(1024)
    declare @full_table_name  varchar(511)
    declare @table_id int
    declare @char_bin_types   varchar(30)

set transaction isolation level 1
 
/* character and binary datatypes */
	select @char_bin_types =
		char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

    if @column_name is null /*	If column name not supplied, match all */
	select @column_name = '%'

    /* Check if the current database is the same as the one provided */
    if @table_qualifier is not null
    begin
		if db_name() != @table_qualifier
		begin	/* 
			** If qualifier doesn't match current database 
			** 18039, Table qualifier must be name of current database
			*/
			raiserror 18039
			return (1)
		end
    end

    if @table_name is null
    begin	/*	If table name not supplied, match all */
		select @table_name = '%'
    end

    if @table_owner is null
    begin	/* If unqualified table name */
		SELECT @full_table_name = @table_name
    end
    else
    begin	/* Qualified table name */
		SELECT @full_table_name = @table_owner + '.' + @table_name
    end

    /* Get Object ID */
    SELECT @table_id = object_id(@full_table_name)


    /* If the table name parameter is valid, get the information */ 
    if ((charindex('%',@full_table_name) = 0) and
		(charindex('_',@full_table_name) = 0)  and
		@table_id != 0)
    begin
	SELECT	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		table_qualifier = DB_NAME(),
		table_owner = USER_NAME(o.uid),
		table_name = o.name,
		column_name = c.name,
		data_type = d.data_type+convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		type_name = rtrim(substring(isnull(stuff(d.type_name,
				(c.status&128)/128,
				char_length(d.type_name),
				"numeric identity"), d.type_name),
				1+isnull(d.aux,
				ascii(substring("III<<<MMMI<<A<A",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60), 18)),
		"precision" = isnull(convert(int, c.prec),
			         isnull(convert(int, d.data_precision),
			        convert(int,c.length)))
				+isnull(d.aux, convert(int,
				ascii(substring("???AAAFFFCKFOLS",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		length = isnull(convert(int, c.length), 
			        convert(int, d.length)) +
				   convert(int, isnull(d.aux,
				ascii(substring("AAA<BB<DDDHJSPP",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-64)),
		scale = isnull(convert(smallint, c.scale), 
			       convert(smallint, d.numeric_scale))
				+convert(smallint,
				isnull(d.aux,
				ascii(substring("<<<<<<<<<<<<<<?",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60)),
		radix = d.numeric_radix,
		nullable =	/* set nullability from status flag */
			convert(smallint, convert(bit, c.status&8)),
		remarks = convert(varchar(254),null),	/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
                                      d.data_type+convert(smallint,
                                      isnull(d.aux,
                                      ascii(substring("666AAA@@@CB??GG",
                                      2*(d.ss_dtype%35+1)+2-8/c.length,1))
                                      -60))),
                sql_datetime_sub = NULL,
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(c.type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
            	char_octet_length = 
                	/*
                	** check if in the list
                	** if so, return a 1 and multiply it by the precision 
                	** if not, return a 0 and multiply it by the precision
                	*/
                	convert(smallint, 
                    	substring('0111111', 
                       	charindex(char(c.type), 
			@char_bin_types)+1, 1)) * 
                	/* calculate the precision */
                	isnull(convert(int, c.prec),
                    	isnull(convert(int, d.data_precision),
                       	convert(int,c.length)))
                    	+isnull(d.aux, convert(int,
                       	ascii(substring('???AAAFFFCKFOLS',
                       	2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, c.status&8))*3)+1, 3))
		
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	WHERE
		o.id = @table_id
		AND c.id = o.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		AND t.type = d.ss_dtype
		AND c.name like @column_name
		AND d.ss_dtype IN (111, 109, 38, 110, 43)	/* Just *N types */
		AND c.usertype < 100		/* No user defined types */
	UNION
	SELECT	/* All other types including user data types */
		table_qualifier = DB_NAME(),
		table_owner = USER_NAME(o.uid),
		table_name = o.name,
		column_name = c.name,
		data_type = d.data_type+convert(smallint,
				isnull(d.aux,
				ascii(substring("666AAA@@@CB??GG",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))
				-60)),
		type_name = rtrim(substring(isnull(stuff(d.type_name,
				(c.status&128)/128,
				char_length(d.type_name),
				"numeric identity"), d.type_name),
				1+isnull(d.aux,
				ascii(substring("III<<<MMMI<<A<A",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60), 18)),
		"precision" = isnull(convert(int, c.prec),
				 isnull(convert(int, d.data_precision), 
				convert(int,c.length)))
				+isnull(d.aux, convert(int,
				ascii(substring("???AAAFFFCKFOLS",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		length = isnull(convert(int, c.length), 
				convert(int, d.length)) +
				   convert(int, isnull(d.aux,
				ascii(substring("AAA<BB<DDDHJSPP",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-64)),
		scale = isnull(convert(smallint, c.scale), 
			       convert(smallint, d.numeric_scale)) +
				convert(smallint, isnull(d.aux,
				ascii(substring("<<<<<<<<<<<<<<?",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60)),
		radix = d.numeric_radix,
		nullable =	/* set nullability from status flag */
			convert(smallint, convert(bit, c.status&8)),
		remarks = convert(varchar(254),null),	/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
                                     d.data_type+convert(smallint,
                                     isnull(d.aux,
                                     ascii(substring("666AAA@@@CB??GG",
                                     2*(d.ss_dtype%35+1)+2-8/c.length,1))
                                     -60))),
                sql_datetime_sub = NULL,
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(c.type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
            	char_octet_length = 
                	/*
                	** check if in the list
                	** if so, return a 1 and multiply it by the precision 
                	** if not, return a 0 and multiply it by the precision
                	*/
                	convert(smallint, 
                    	substring('0111111', 
                       	charindex(char(c.type), 
			@char_bin_types)+1, 1)) * 
                	/* calculate the precision */
                	isnull(convert(int, c.prec),
                    	isnull(convert(int, d.data_precision),
                       	convert(int,c.length)))
                    	+isnull(d.aux, convert(int,
                       	ascii(substring('???AAAFFFCKFOLS',
                       	2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, c.status&8))*3)+1, 3))

	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	WHERE
		o.id = @table_id
		AND c.id = o.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		/*
		** We need a equality join with 
		** sybsystemprocs.dbo.spt_datatype_info here so that
		** there is only one qualified row returned from 
		** sybsystemprocs.dbo.spt_datatype_info, thus avoiding
		** duplicates.
		*/
		AND t.type = d.ss_dtype
		AND c.name like @column_name
		AND (d.ss_dtype NOT IN (111, 109, 38, 110, 43) /* No *N types */

			OR c.usertype >= 100) /* User defined types */

			 ORDER BY colid
	end
	else
    begin
	/* 
	** This block is for the case where there IS pattern
	** matching done on the table name. 
	*/
	if @table_owner is null /* If owner not supplied, match all */
			select @table_owner = '%'

	SELECT	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		table_qualifier = DB_NAME(),
		table_owner = USER_NAME(o.uid),
		table_name = o.name,
		column_name = c.name,
		data_type = d.data_type+convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		type_name = rtrim(substring(isnull(stuff(d.type_name,
				(c.status&128)/128,
				char_length(d.type_name),
				"numeric identity"), d.type_name),
				1+isnull(d.aux,
				ascii(substring("III<<<MMMI<<A<A",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60), 18)),
		"precision" = isnull(convert(int, c.prec),
				isnull(convert(int, d.data_precision),
				         convert(int, c.length)))
				+isnull(d.aux, convert(int,
				ascii(substring("???AAAFFFCKFOLS",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		length = isnull(convert(int, c.length), 
				convert(int,d.length)) +
				   convert(int, isnull(d.aux,
				ascii(substring("AAA<BB<DDDHJSPP",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-64)),
		scale = isnull(convert(smallint, c.scale), 
			       convert(smallint, d.numeric_scale)) +
				convert(smallint, isnull(d.aux,
				ascii(substring("<<<<<<<<<<<<<<?",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60)),
		radix = d.numeric_radix,
		nullable =	/* set nullability from status flag */
			convert(smallint, convert(bit, c.status&8)),
		remarks = convert(varchar(254),null),	/* Remarks are NULL */
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
                                      d.data_type+convert(smallint,
                                      isnull(d.aux,
                                      ascii(substring("666AAA@@@CB??GG",
                                      2*(d.ss_dtype%35+1)+2-8/c.length,1))
                                      -60))),
                sql_datetime_sub = NULL,
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(c.type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
            	char_octet_length = 
                	/*
                	** check if in the list
                	** if so, return a 1 and multiply it by the precision 
                	** if not, return a 0 and multiply it by the precision
                	*/
                	convert(smallint, 
                    	substring('0111111', 
                       	charindex(char(c.type), 
			@char_bin_types)+1, 1)) * 
                	/* calculate the precision */
                	isnull(convert(int, c.prec),
                    	isnull(convert(int, d.data_precision),
                       	convert(int,c.length)))
                    	+isnull(d.aux, convert(int,
                       	ascii(substring('???AAAFFFCKFOLS',
                       	2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, c.status&8))*3)+1, 3))

	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	WHERE
		o.name like @table_name
		AND user_name(o.uid) like @table_owner
		AND o.id = c.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		AND t.type = d.ss_dtype
		AND o.type != 'P'
		AND c.name like @column_name
		AND d.ss_dtype IN (111, 109, 38, 110, 43)	/* Just *N types */
		AND c.usertype < 100
	UNION
	SELECT /* All other types including user data types */
		table_qualifier = DB_NAME(),
		table_owner = USER_NAME(o.uid),
		table_name = o.name,
		column_name = c.name,
		data_type = d.data_type+convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		type_name = rtrim(substring(isnull(stuff(d.type_name,
				(c.status&128)/128,
				char_length(d.type_name),
				"numeric identity"), d.type_name),
				1+isnull(d.aux,
				ascii(substring("III<<<MMMI<<A<A",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60), 18)),
		"precision" = isnull(convert(int, c.prec),
				  isnull(convert(int, d.data_precision),
					 convert(int,c.length)))
				+isnull(d.aux, convert(int,
				ascii(substring("???AAAFFFCKFOLS",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		length = isnull(convert(int, c.length), 
				convert(int, d.length)) +
				   convert(int, isnull(d.aux,
				ascii(substring("AAA<BB<DDDHJSPP",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-64)),
		scale = isnull(convert(smallint, c.scale),
			       convert(smallint, d.numeric_scale)) +
					convert(smallint, isnull(d.aux,
				ascii(substring("<<<<<<<<<<<<<<?",
				2*(d.ss_dtype%35+1)+2-8/c.length,
				1))-60)),
		radix = d.numeric_radix,
		nullable =	/* set nullability from status flag */
		convert(smallint, convert(bit, c.status&8)),
		remarks  = convert(varchar(254),null),
		ss_data_type = c.type,
		colid = c.colid,
                column_def = NULL,
                sql_data_type = isnull(d.sql_data_type,
                                     d.data_type+convert(smallint,
                                     isnull(d.aux,
                                     ascii(substring("666AAA@@@CB??GG",
                                     2*(d.ss_dtype%35+1)+2-8/c.length,1))
                                     -60))),
                sql_datetime_sub = NULL,
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(c.type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
            	char_octet_length = 
                	/*
                	** check if in the list
                	** if so, return a 1 and multiply it by the precision 
                	** if not, return a 0 and multiply it by the precision
                	*/
                	convert(smallint, 
                    	substring('0111111', 
                       	charindex(char(c.type), 
			@char_bin_types)+1, 1)) * 
                	/* calculate the precision */
                	isnull(convert(int, c.prec),
                    	isnull(convert(int, d.data_precision),
                       	convert(int,c.length)))
                    	+isnull(d.aux, convert(int,
                       	ascii(substring('???AAAFFFCKFOLS',
                       	2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
                ordinal_position = c.colid,
                is_nullable = rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, c.status&8))*3)+1, 3))
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	WHERE
		o.name like @table_name
		AND user_name(o.uid) like @table_owner
		AND o.id = c.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		/*
		** We need a equality join with 
		** sybsystemprocs.dbo.spt_datatype_info here so that
		** there is only one qualified row returned from 
		** sybsystemprocs.dbo.spt_datatype_info, thus avoiding
		** duplicates.
		*/
		AND t.type = d.ss_dtype
		AND c.name like @column_name
		AND o.type != 'P'
		AND c.name like @column_name
		AND (d.ss_dtype NOT IN (111, 109, 38, 110, 43) /* No *N types */

			OR c.usertype >= 100) /* User defined types */

	ORDER BY table_owner, table_name, colid
end
	
	return(0)
go
exec sp_procxmode 'sp_columns', 'anymode'
go
grant execute on sp_columns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_aux_parse_entity')
begin
	drop procedure sp_aux_parse_entity
end
go
print "Installing sp_aux_parse_entity"
go

/*
** Auxilliary stored procedure for parsing entities.  Entities
** may either be databases, tables, or indices.
**
** The following assumptions will be made:
**	1) If the database parameter is NULL, it is assumed that the entity
**	   being addressed belongs in the current database.
**
** Input Parameters:
**	dbname		database name (NULL if none specified)
**	tablename	NULL if no table is being specified
**				(Note that this indicates that the entity
**				 is a database.  This also requires that
**				 the indexname parameter be NULL.)
**			table name otherwise
**				(specified in the following format:
**					`[owner_name.]table_name'
**				 Note that database name is not accepted.)
**	indexname	NULL or "table only" if index not being specified
**			"text only" if specifying text/image pages only
**			name of index otherwise
** 
** Output parameters:
**	dbid		database id
**	ownerid		user id of owner of entity
**	objid		NULL if no table specified
**			object id otherwise
**	indid		NULL if no index specified
**			index id otherwise (index id 255 used to specify
**			text/image pages)
**	entitytype	`D' for databases
**			`T' for tables
**			`I' for indices
** Returns:
**	0		everything went ok
**	1		general error
**	2		syntax error - raising a usage message is
**			*REQUIRED* after one of these.
*/

/*
** Messages for "sp_aux_parse_entity"
**
** 17460, "Object must be in the current database."
** 18088, "The target database does not exist."
** 18090, "The target object does not exist."
** 18091, "The target index does not exist."
** 18154, "`%1!' is not a table."
** 18171, "The table must have a text column if `text only' is specified."
*/

create procedure sp_aux_parse_entity
@dbname		varchar(255) = NULL,
@tablename	varchar(512) = NULL,
@indexname	varchar(255) = NULL,
@dbid		int output,
@ownerid	int output,
@objid		int output,
@indid		int output,
@entitytype	char(1)	output
as

declare @tablestring	varchar(767)
declare @objecttype	char(2)

select @dbid		= NULL
select @ownerid		= NULL
select @objid		= NULL
select @indid		= NULL
select @entitytype	= NULL

/*
** Perform generic syntax checks on the arguments.
*/
if	(@dbname like "%.%")
	or (@indexname like "%.%")
	or (@tablename like ".%")
	or (@tablename like "%.")
	or (@tablename like "%.%.%")
begin
	/*
	** No need for us to raise a syntax error message here.
	** Let the caller raise an error message for us.
	*/
	return 2
end

/*
** Check for a database entity
*/
if @tablename is NULL
begin
	/*
	** Syntax error checking.
	*/
	if @dbname is NULL
	begin
		/*
		** No need for us to raise a syntax error message here.
		** Let the caller raise an error message for us.
		*/
		return 2
	end

	if @indexname is not NULL
	begin
		/*
		** No need for us to raise a syntax error message here.
		** Let the caller raise an error message for us.
		*/
		return 2
	end

	/*
	** This is a database entity.  See if the database exists.
	*/
	select @dbid = db_id(@dbname)
	if @dbid is NULL
	begin
		/* 18088, "The target database does not exist." */
		raiserror 18088
		return 1
	end

	/*
	** Set the output parameters and return
	*/
	select @ownerid		= user_id("dbo")
	select @entitytype	= 'D'
end
else
begin
	/*
	** The entity is either a table or an index.
	*/

	/*
	** In both instances we need to figure out the table id.
	** In order to do this, first, make sure we are only affecting
	** objects in the current database!
	*/
	if @dbname is not NULL
	begin
		if @dbname != db_name()
		begin
			/* 17460, "Object must be in the current database." */
			raiserror 17460
			return 1
		end
	end
	else
	begin
		select @dbname = db_name()
	end

	select @dbid = db_id()

	/*
	** Next, formulate the fully-qualified table name.
	*/
	if @tablename like "%.%"
	begin
		select @tablestring = @dbname + "." + @tablename
	end
	else
	begin
		select @tablestring = @dbname + "." + user_name() +"." +
				      @tablename
	end

	/*
	** Retrieve the id from the fully-qualified table name.
	*/
	select @objid = object_id(@tablestring)

	/*
	** Check for existence.
	*/
	if @objid is NULL
	begin
		/* 18090, "The target object does not exist."*/
		raiserror 18090
		return 1
	end

	/*
	** Retrieve the owner and type of this object.  Make sure that 
	** the object is indeed a table.
	*/
	select @ownerid = uid, @objecttype = type
	from sysobjects
	where (id = @objid)

	if (@objecttype != 'S') and (@objecttype != 'U')
	begin
		/* 18154, "`%1!' is not a table." */
		raiserror 18154, @tablestring
		return 1
	end

	/*
	** Now handle the index special case, if any.
	*/
	if (@indexname is not NULL) and (lower(@indexname) != "table only")
	begin
		/*
		** An index has been specified.  Check for the special
		** "text only" case.
		*/
		if lower(@indexname) = "text only"
		begin
			/*
			** Check if the table has a text/image column.
			*/
			if not exists (select *
				       from sysindexes
				       where	(indid = 255) and
					     	(id = @objid))
			begin
				/* 18171, "The table must have a text column if `text only' is specified." */
				raiserror 18171
				return 1
			end
			else
			begin
				select @indid = 255
			end
		end
		else
		begin
			/*
			** Grab the index id.
			*/
			select @indid = indid from sysindexes
			where (id = @objid) and (name = @indexname) and (indid > 0)

			/*
			** Check for existence.
			*/
			if @indid is NULL
			begin

				/* 18091, "The target index does not exist." */
				raiserror 18091
				return 1
			end
		end
		select @entitytype = 'I'
	end
	else
	begin
		select @entitytype = 'T'
	end
end

return 0
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_cachestrategy')
begin
	drop procedure sp_cachestrategy
end
go
print "Installing sp_cachestrategy"
go

/*
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17763, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in updating the schemacnt column in sysobjects."
** 18173, "Only the System Administrator (SA) or the Object Owner
**	   may execute this stored Procedure."
** 18176, "Usage: sp_cachestrategy dbname [, [ownername.]tablename
**	   [, indexname | `text only' | `table only'
**	   [, prefetch | mru, `on' | `off']]]"
** 18077, "Set curwrite to the level of index."
** 18079, "Set curwrite to the level of the object in sysobjects."
** 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
** 18333, "Cache configuration failed.  Your curread must dominate the sensitivity level of the object."
** 19979, "Cannot run '%1!' for in-memory database '%2!'."
*/

/* 
** This procedure sets a default prefetch strategy for a given object.
** For non-clustered index it only affects its index pages.
** For clustered indexes it affects the data pages as well.
**
** All updates to sysindexes are done by forcing the index access via
** 'csysindexes' so that it's clear that only one row is being updated.
** (Multi-row updates to sysindexes are prohibited.)
*/
CREATE PROCEDURE sp_cachestrategy
@dbname 	varchar(255),
@tablename 	varchar(255),
@indexname 	varchar(255) = NULL,
@strategy	varchar(30) = NULL,
@onoff		varchar(4)  = NULL
AS

DECLARE @stat2	 	int
DECLARE @dbid	 	int
DECLARE @ownerid 	int
DECLARE @tabid	 	int
DECLARE @indid	 	smallint
DECLARE @entitytype	char(1)
DECLARE @status		int
DECLARE @updated	int
DECLARE @indname	varchar(255)
DECLARE @largeio	varchar(8)
DECLARE @bufstr		varchar(8)




IF @@trancount = 0
BEGIN
	SET chained off
END

SET transaction isolation level 1

SELECT	@stat2 = 0

IF @dbname IS NULL
BEGIN
	/*
	** The database name is required for this stored procedure
	** 18176, "Usage: sp_cachestrategy dbname [, [ownername.]tablename
	**	   [, indexname | `text only' | `table only'
	**	   [, prefetch | mru, `on' | `off']]]"
	*/
	raiserror 18176
	RETURN	(1)
END

/*
** Retrieve the id's required to identify the object affected
*/
SELECT @status		= 0
SELECT @dbid		= NULL
SELECT @ownerid		= NULL
SELECT @tabid		= NULL
SELECT @indid		= NULL
SELECT @entitytype	= NULL
EXEC @status = sp_aux_parse_entity @dbname, @tablename, @indexname,
				   @dbid OUTPUT, @ownerid OUTPUT,
				   @tabid OUTPUT, @indid OUTPUT,
				   @entitytype OUTPUT


IF @status = 2
BEGIN
	/*
	** A syntax error was encountered.  Raise a usage message.
	** 18176, "Usage: sp_cachestrategy dbname [, [ownername.]tablename
	**	   [, indexname | `text only' | `table only'
	**	   [, prefetch | mru, `on' | `off']]]"
	*/
	raiserror 18176
	RETURN	(1)
END
ELSE IF @status != 0
BEGIN
	RETURN (@status)
END

/* Do not allow sp_cachestrategy to be run on in-memory database. */
if exists (select * from master.dbo.sysdatabases 
	   where dbid = @dbid and (status4 & 4096 = 4096)) 
begin 
	raiserror 19979, "sp_cachestrategy", @dbname 
	return (1) 
end

/*
**  Perform permission checks.  Basically, only the System Administrator
**  can change the cache strategy for objects he/she doesn't own.
*/
IF @ownerid != user_id() 
BEGIN
	/*
	** Check if the user has the SA role.
	*/
	IF proc_role("sa_role") = 0
	BEGIN
		/*
		** proc_role already raised an error message but we want
		** to supply an addendum saying that you need to be the
		** owner of the object in order to perform this operation.
		*/
		raiserror 18173
		RETURN	(1)
	END

END


/*
**  Fix the index id if the entity is a table.
*/
IF (@entitytype = 'T')
BEGIN
	/*
	** Leaf level of clustered index, if it exists,
	** contain the data pages
	*/
	SELECT @indid = 1

	IF NOT EXISTS (SELECT *
		       FROM   sysindexes
		       WHERE  id = @tabid AND indid = 1)
	BEGIN
		SELECT @indid = 0
	END
END

/*
** If @strategy is entered, but it is neither "prefetch" nor "mru"
** we should report an error. If @strategy is correct entered,
** and @onoff is entered, but @onoff is neither "on" nor "off"
** we should report an error. However, if @onoff is not entered,
** we would not report error to keep the existing behavior.
*/
IF (@strategy != NULL)
BEGIN

	IF ((lower(@strategy) NOT IN ("prefetch", "mru"))
		OR ((@onoff != NULL) AND (lower(@onoff) NOT IN ("on", "off")))) 
	BEGIN
		/*
		** A syntax error was encountered.  Raise a usage message.
		** 18176, "Usage: sp_cachestrategy dbname 
		**	 [, [ownername.]tablename
		**	   [, indexname | `text only' | `table only'
		**	   [, prefetch | mru, `on' | `off']]]"
		*/
		raiserror 18176
		RETURN	(1)
	END
END

/*
** Initialize some variables.
*/
SELECT @stat2 = status2, @indname = name
FROM   sysindexes
WHERE  id = @tabid AND indid = @indid

SELECT @updated = 0

/*
**  Check if invoking the precedure in informational mode
**  In this case the user may not specify any strategy.
*/
IF (@onoff = NULL)
BEGIN
	/* Print the SHOWPLAN messages here as well */
	IF (@stat2 & 16 = 16)
		SELECT @largeio = "OFF"
	ELSE
		SELECT @largeio = "ON"

	IF (@stat2 & 32 = 32)
		SELECT @bufstr = "OFF"
	ELSE
		SELECT @bufstr = "ON"

	SELECT  "object name" = user_name(@ownerid) + "." +
				object_name(@tabid),
		"index name"  = @indname,
		"large IO"    = @largeio,
		"MRU"         = @bufstr

	RETURN(0)
END



begin tran updatesysind

/*
** Turn the sysindexes.status2 field for IND2_NOPREFETCH
*/
IF lower(@strategy) = "prefetch"
BEGIN
	IF lower(@onoff) = "off"
	BEGIN
		IF (@stat2 & 16) = 0
		BEGIN
			UPDATE sysindexes
			SET    status2 = status2 | 16
			WHERE  id = @tabid AND indid = @indid
			plan "(update (i_scan csysindexes sysindexes))"

			/*
			** We updated a sysindexes row. We also need to update 
			** the in-core structure representing this sysindexes 
			** row as the sysindexes rows cache is not a write thru
			** cache. 
			*/ 
			dbcc refreshides(@dbid, @tabid, @indid, "cachestrategy")

			/*
			** In case of error, dbcc refreshides will
			** print the error message.
			*/
			if @@error != 0
			begin
				rollback tran updatesysind
				RETURN (1)
			end

			SELECT @updated =  1
		END
	END
	ELSE
	BEGIN
		IF (@stat2 & 16) != 0
		BEGIN
			UPDATE sysindexes
			SET    status2 = status2 & -17
			WHERE  id = @tabid AND indid = @indid
			plan "(update (i_scan csysindexes sysindexes))"

			/*
			** We updated a sysindexes row. We also need to update 
			** the in-core structure representing this sysindexes 
			** row as the sysindexes rows cache is not a write thru
			** cache. 
			*/ 
			dbcc refreshides(@dbid, @tabid, @indid, "cachestrategy")

			/*
			** In case of error, dbcc refreshides will
			** print the error message.
			*/
			if @@error != 0
			begin
				rollback tran updatesysind
				RETURN (1)
			end

			SELECT @updated = 1
		END
	END
END
ELSE	/* Already checked for all legal values, must be MRU now */
BEGIN
	IF lower(@onoff) = "off"
	BEGIN
		IF (@stat2 & 32) = 0
		BEGIN
			UPDATE sysindexes
			SET    status2 = status2 | 32
			WHERE  id = @tabid AND indid = @indid
			plan "(update (i_scan csysindexes sysindexes))"

			/*
			** We updated a sysindexes row. We also need to update 
			** the in-core structure representing this sysindexes 
			** row as the sysindexes rows cache is not a write thru
			** cache. 
			*/ 
			dbcc refreshides(@dbid, @tabid, @indid, "cachestrategy")

			/*
			** In case of error, dbcc refreshides will
			** print the error message.
			*/
			if @@error != 0
			begin
				rollback tran updatesysind
				RETURN (1)
			end

			SELECT @updated = 1
		END
	END
	ELSE
	BEGIN
		IF (@stat2 & 32) != 0
		BEGIN
			UPDATE sysindexes
			SET    status2 = status2 & -33
			WHERE  id = @tabid AND indid = @indid
			plan "(update (i_scan csysindexes sysindexes))"

			/*
			** We updated a sysindexes row. We also need to update 
			** the in-core structure representing this sysindexes 
			** row as the sysindexes rows cache is not a write thru
			** cache. 
			*/ 
			dbcc refreshides(@dbid, @tabid, @indid, "cachestrategy")

			/*
			** In case of error, dbcc refreshides will
			** print the error message.
			*/
			if @@error != 0
			begin
				rollback tran updatesysind
				RETURN (1)
			end

			SELECT @updated = 1
		END
	END
END

commit tran updatesysind

/*
** We need to increment the object's schema count if we changed
** its cache strategy.
*/
IF @updated = 1
BEGIN
	/*
	** This transaction also writes a log record for replicating the
	** invocation of this procedure. If logexec() fails, the transaction
	** is aborted.
	**
	** IMPORTANT: The name rs_logexec is significant and is used by
	** Replication Server.
	*/
	BEGIN TRANSACTION rs_logexec

	IF (schema_inc(object_id(@tablename), 0) != 1)
	BEGIN
		/*
		** 17763, "The execution of the stored procedure '%1!'
		**         in database '%2!' was aborted because there
		**         was an error in updating the column
		**         schemacnt in sysobjects."
		*/
		SELECT @dbname = db_name()
		RAISERROR 17763, "sp_cachestrategy", @dbname
		ROLLBACK TRANSACTION rs_logexec
		RETURN(1)
	END

        IF (logexec() != 1)
        BEGIN
                /*
                ** 17756, "The execution of the stored procedure '%1!'
                **         in database '%2!' was aborted because there
                **         was an error in writing the replication log
                **         record."
                */
                SELECT @dbname = db_name()
                RAISERROR 17756, "sp_bindefault", @dbname

                ROLLBACK TRANSACTION rs_logexec
                RETURN(1)
        END
        COMMIT TRANSACTION
END

RETURN(0)
go
exec sp_procxmode 'sp_cachestrategy', 'anymode'
go
grant execute on sp_cachestrategy to public
go
exec sp_procxmode 'sp_cachestrategy', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

use sybsystemprocs
go

if not exists (select *
                from sysusers
                        where name = "guest")
begin
        execute sp_adduser guest,guest
end
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_optimal_text_space')
begin
	drop procedure sp_optimal_text_space
end
go
print "Installing sp_optimal_text_space"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** 18101, "Table must be in the current database."
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo)
**         to execute this procedure."
** 18102, "Table '%1!' does not exist in this database."
** 19029, "The status for '%1!' is set to %2!."
** 19031, "Table '%1!' does not have a text or image column."
** 19032, "Due to system failure, the status for '%1!' has not been changed."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there
**         was an error in writing the replication log record."
** 18985, "The value for '%1!' attribute must be either 0 or 1."
** 18573, "Failed to update attribute '%1!' for object '%2!'."
*/

create procedure sp_optimal_text_space
@objname	varchar(767),	/* obj we want to mark */
@optname	varchar(255),
@optvalue	int
as

declare @dbname		varchar(255)
declare @db		varchar(255)
declare @owner		varchar(255)
declare @object		varchar(255)
declare @objid		int
declare @text_dealloc	int
declare @dbuid		int
declare @user_is_sa	int
declare @user_is_dbo	int
declare @dbo		int
declare @dbcc_arg_3	smallint
declare @dbcc_arg_4	int

select  @text_dealloc = hextoint("0x020000000")

select @dbname = db_name()

if (@optvalue not in (0, 1))
begin
	/*
	** 18985, "The value for attribute '%1!' must be
	** either 0 and 1"
	*/
	raiserror 18985, @optname
	return (1)
end

/*
** Crack the name into its corresponding pieces.
*/
execute sp_namecrack	@objname,
			@db = @db output, 
			@owner = @owner output,
			@object = @object output

/*
** Make sure that the object is in the current database.
*/
if (@db is not NULL and @db != db_name())
begin
	/*
	** 18101, "Table must be in the current database."
	*/
	raiserror 18101
	return (1)
end
else
begin
	select @dbuid = suid
	from master..sysdatabases
	where name = @dbname
end

if (charindex("sa_role", show_role()) > 0)
begin
	select @user_is_sa = 1
end
else
begin
	select @user_is_sa = 0
end

exec sybsystemprocs.dbo.sp_is_valid_user @dbo output, @dbname
if (@dbo = 1)
begin
	select @user_is_dbo = 1
end
else
begin
	select @user_is_dbo = 0
end

/*
** Check is the user has the correct roles to change
** this table property.
*/
if (@user_is_dbo = 0 and @user_is_sa = 0)
begin
	/*
	** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) 
	** to execute this procedure." 
	*/
	raiserror 17230
	return(1)
end

/*
**  Make sure that the object actually exists.
*/
select @objid = object_id(@objname)

if (@objid is NULL) or
	(not exists (select name from sysobjects
		     where id = @objid and
		     type = "U"))
begin
	/*
	** 18102, "Table '%1!' does not exist in this database."
	*/
	raiserror 18102, @objname
	return (1)
end

/*
** Check if the object has text/image columns in the first
** place.
*/
if not exists (select 1
		from sysindexes
		where (indid = 255) and
		      (id = @objid))
begin
	/*
	** 19031, "Table '%1!' does not have a text or image column."
	*/
	raiserror 19031, @objname
	return(1)
end

/*
** This transaction also writes a log record for replicating the
** invocation of this procedure. If logexec() fails, the transaction
** is aborted.
**
** IMPORTANT: The name rs_logexec is significant and is used by
** Replication Server.
*/
begin transaction rs_logexec

if (@optvalue = 1)
begin
	select @dbcc_arg_3 = 1

	update sysobjects
	set sysstat2 = sysstat2 | @text_dealloc
	from sysobjects
	where id = @objid
end
else
begin
	select @dbcc_arg_3 = 0

	update sysobjects
       	set sysstat2 = sysstat2 &~ @text_dealloc
	from sysobjects
	where id = @objid
end

if (@@error != 0)
begin
	/*
	** Error is already raised so just rollback.
	*/
	rollback transaction

	return(1)
end

select @dbcc_arg_4 = 0
dbcc chgindcachedvalue(@optname, @objname, @dbcc_arg_3, @dbcc_arg_4)

/* If there was an error, @@error will be non-zero */
if (@@error != 0)
begin
	rollback transaction

	/*
	** 18573, "Failed to update attribute '%1!' for object '%2!'."
	*/
	raiserror 18573, @optname, @objname
	return(1)
end


/*
** Write the log record to replicate this invocation
** of the stored procedure.
*/
if (logexec() != 1)
begin
	rollback transaction

	/*
	** 17756, "The execution of the stored procedure '%1!'
	**         in database '%2!' was aborted because there
	**         was an error in writing the replication log
	**         record."
	*/
	raiserror 17756, "sp_optimal_text_space", @dbname
	return(1)
end

commit transaction

return(0)

go
exec sp_procxmode 'sp_optimal_text_space', 'anymode'
go
grant execute on sp_optimal_text_space to public
go
exec sp_procxmode 'sp_optimal_text_space', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_chgattribute')
begin
	drop procedure sp_chgattribute
end
go
print "Installing sp_chgattribute"
go

/* Sccsid = "@(#) generic/sproc/chgattribute 1.1 4/6/95 " */
/*
** Generated by spgenmsgs.pl on Tue May 31 02:59:14 2005 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/chgattribute [Total 19]
**
** 17260, "Can't run %1! from within a transaction."
** 17460, "Object must be in the current database."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17760, "%1!' is a system table. Cannot use '%2!' on system tables."
** 17782, "You do not own a table, column or index of that name in the current database."
** 18121, "Unrecognized change attribute option."
** 18571, "The attribute '%1!' is not applicable to tables with allpages lock scheme."
** 18572, "The value for attribute '%1!' must be between %2! and %3!."
** 18573, "Failed to update attribute '%1!' for object '%2!'."
** 18612, "Invalid value specified for option '%1!'. Valid range of values is %2! to %3!."
** 18613, "The attribute '%1!' is applicable to tables only."
** 18840, "The value specified for identity gap %1! is not legal; identity gap must be greater than or equal to 0."
** 18983, "The '%1!' attribute is not applicable to tables with datarow or datapage lock schemes."
** 18985, "The value for '%1!' attribute must be either 0 or 1."
** 18987, "The '%1!' attribute could not be set to the specified value for the object."
** 19115, "A value must be specified for attribute '%1!'."
** 19116, "Table '%1!' does not have an identity column."
** 19117, "The value %1! for '%2!' attribute must be greater than or equal to the current maximum identity value %3!."
** 19118, "Object '%1!' is currently being accessed by other users. Failed to update attribute '%2!'."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/chgattribute [Total 1]
**
** 19573, "sp_chgattribute is not allowed for %1!, as it is a virtually hashed table."
** 18122, "'%1!' attribute of object '%2!' changed to %3!."
*/
/*
** End spgenmsgs.pl output.
*/

/*
** For the option dealloc_first_txtpg we use the internal procedure sp_optimal_text_space
** to perform the necessary checks/updates. This procedure could raise additional
** messages.
*/

create procedure sp_chgattribute
@objname varchar(767),                   /* table or index name */
@optname varchar(30),
@optvalue int,
@optvalue2 varchar(38) = NULL		/* Current max digits for numeric */
as

declare @objid int                      /* object id of the table */
declare @indid smallint                 /* table's index id  */
declare @msg varchar(1024)
declare @dbname varchar(255)
declare @dbid	int			/* database id */
declare @tabname varchar(255)            /* name of table */
declare @indname varchar(255)            /* name of index */
declare @varcol_count smallint		/* Number of variable length columns */
declare @sysstat2 int                   /* status bits of the table */
      , @sysstat  int	   		/* objstat from sysobjects*/
      , @objtype  varchar(2)		/* Object's type */
declare @is_table_APL int               /* flag to distinguish APL and DOl tables */
declare @dbcc_arg_3 smallint		/* third argument to dbcc command. 
					** This must be of type smallint.
					*/
declare @newoptvalue varchar(10)	/* Used for converting the optvalue */
declare @opt_ind_lock int		/* server status for optimistic index lock */
declare @ind_unique_localidx smallint   /* server status for unique local index */
declare @curlimit16 smallint		/* current value for int16 column */
declare @newlimit16 smallint		/* new value for int16 column */
declare @curlimit32 int			/* current value for int32 column */
declare @newlimit32 int			/* new value for int32 column */
declare @dbcc_arg_4 int			/* forth argument to dbcc command. 
					** This must be of type int.
					*/
declare @retstatus int
declare @curr_max_idtval numeric(38, 0)	/* current max id value in the table. */
declare @new_idtval numeric(38,0)	/* numeric number of input optvalue2 */
declare @colname varchar(255)		/* name of identity column */
declare @sqltext varchar(600)		/* tmp holder for sqltext */
declare @tmp_indid int                  /* tmp indid holder */ 
declare @upd_rowcnt int                 /* updated row count */ 
declare	@hash_bit int

/* If we're in a transaction, disallow this */
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_chgattribute"
	return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1

if @objname like "%.%.%"
begin
	/*
	** 17460, "Object must be in the current database."
	*/
	raiserror 17460
	return (1)
end

if not exists (
	select * from master.dbo.spt_values 
		 where type = "H"
		 and  name = @optname)
begin
	/*
	** 18121, "Unrecognized change attribute option."
	*/
	raiserror 18121
	return (1)
end

if @objname like "%.%"
begin
	/*
	** Attributes 'exp_row_size', 'concurrency_opt_threshold' and 
	** 'ascinserts' apply only to a table and not to an index
	*/	
	if (@optname = "concurrency_opt_threshold" or 
	    @optname = "exp_row_size" or
	    @optname = "optimistic_index_lock" or
	    @optname = "ascinserts")
	begin
		/*
		** 18613, "The attribute '%1!' is applicable to tables only."
		*/
		raiserror 18613, @optname
		return (1)
	end	
		
	/*
	**  Get the table name and index name out.
	*/
	select @tabname = substring(@objname, 1, charindex(".", @objname) - 1)
	select @indname = substring(@objname, charindex(".", @objname) + 1, 511)

	select @objid = si.id, @indid = si.indid, @objtype = so.type
		from sysobjects so, sysindexes si
		where 	si.id = so.id
			and so.name = @tabname
			and si.name = @indname
			and si.indid != 0
			and so.type in ('U', 'S')	-- user / system tables
			and so.uid = user_id()
end
else
begin
	select @tabname = @objname
	select @objid = si.id, @indid=si.indid, @objtype = so.type
		from sysobjects so, sysindexes si
		where 	so.name = @tabname
			and si.id = so.id
			and si.indid in (0,1)
			and so.type in ('U', 'S')	-- user / system tables
			and so.uid = user_id()
end
/*
**  If @objid is still NULL then that means it isn't a 
**  table/index name.  
*/
if (@objid is null)
begin
	/*
	** 17782, "You do not own a table, column or index of that name in 
	** the current database."
	*/
	raiserror 17782
	return (1)
end

/*
** Determine whether the table we are working is APL or DOL.
**
** The bits 0x2000 (8192) and 0x0 (0) represent allpages
** lock scheme. The value of 0 indicates that no lock
** scheme is specified (old style tables), so they only
** support allpages locking.
**
** The bits 0x4000 (16384) and 0x8000 (32768) represent
** DOL tables respectively datapages only and datarows
** lock schemes.
**
** The value of 57344 is 8192+16384+32768.
**
** sysstat: 0x400 (1024) is for fake tables.
*/
select @sysstat2 = (sysstat2 & 57344)
	, @sysstat = (sysstat & 1024)	-- Eliminate fake catalogs
from sysobjects
where id = @objid

if (@sysstat2  = 8192 or @sysstat2 = 0)
	select @is_table_APL = 1
else
	select @is_table_APL = 0

if (@sysstat = 1024)
begin
	/*
	** Do not allow executing this for fake system catalogs.
	** It's meaningless and might cause unnecessary side-effects.
	** 18613, "The attribute '%1!' is applicable to tables only."
	*/
	raiserror 18613, @optname
	return (2)
end

/*
** Restrict use of this interface on system catalogs to only those
** options that control space-management properties. We don't want
** users to accidentally define, say, concurrency_opt_threshold 
** and cause unforeseen locking behaviour changes for system
** catalogs.
*/
if (    (@objtype = 'S')
     and @optname NOT IN ("concurrency_opt_threshold", "exp_row_size"))
begin

	select @msg = "sp_chgattribute " + @optname
	raiserror 17760, @tabname, @msg
	return (1)
end


/* 
** In preparation for the system catalogs and in-memory cache updates
** check each option for the valid option specifications and raise 
** errors if necessary. 
**
** option			catalog		column 		size
** ------------------------------------------------------------------
** concurrency_opt_threshold	systabstats	conopt_thld	int16
** plldegree			systabstats	plldegree	int16
** identity_gap			sysindexes	identitygap	int32
** reservepagegap		sysindexes	res_page_gap	int16
** fillfactor			sysindexes	fill_factor	int16
** max_rows_per_page		sysindexes	maxrowsperpage	int16
** exp_row_size			sysindexes	exp_rowsize	int16
** optimistic_index_lock	sysobjects	sysstat2	int32
** dealloc_first_txtpg		sysobjects	sysstat2	int32
** local_unique_index           sysindexes      status3         int16
**
** option			domain validity checks made herein
**				for @optvalue
** -----------------------------------------------------------------------
** concurrency_opt_threshold	>= -1 and <= 32767
** plldegree			>= -1 and <= 32767
** identity_gap			>= 0
** reservepagegap		>= 0 and <= 255
** fillfactor			>= 0 and <= 100
** max_rows_per_page		none, instead via dbcc chgindcachedvalue()
** exp_row_size			none, instead via dbcc chgindcachedvalue()
** optimistic_index_lock	0,1 (mode off / mode on)
** dealloc_first_txtpg		0,1 (mode off / mode on) or NULL.
** identity_burn_max		none, instead via dbcc set_identity_burn_max()
** local_unique_index           0,1 (mode off / mode on) 
**
** When a domain check passes we assign @optvalue to an int16 or int32
** local variable respectively @newlimit16 or @newlimit32.  If the new
** limit and the current value (@curlimit16 or @curlimit32) are the same
** we consider this sproc invocation being a NOOP.
**
** When the above checks pass below is what we do for the options :
**
**	reservepagegap,
**	max_rows_per_page,
**	fillfactor,
**	identity_gap,
**	concurrency_opt_threshold and
**	dealloc_first_txtpg.
**
** 1)	We start transaction rs_logexec
**
** 2)	We update sysindexes catalog and the in-memory cache thru
**	dbcc chgindcachedvalue().
**
**	We do NOT update sysindexes for option exp_row_size since
**	dbcc chgindcachedvalue() will begin a xact, update sysindexes
**	and then refresh the in-memory cache.  Notice that during the
**	checks phase for this option we may need to update sysindexes
**	if the column had a null value and this MUST not be done under
**	a transaction (here rs_logexec).  See comment further down for
**	the reason.  For that same reason for this option we only want
**	to execute:
**		begin tran rs_logexec
**		dbcc chgindcachedvalue("exp_row_size",...)
**		commit tran
**
**	For concurrency_opt_threshold, we update systabstats catalog and
**	the in-memory cache in pdes thru dbcc chgindcachedvalue().
**
** 3)	We logexec() this sproc replication execution.
**
** 4)	We commit transaction rs_logexec
**
**	For the optimistic_index_lock option we update sysobjects and
**	(un)set the status 02_OPT_INDEX_LOCK in sysstat2. The command
**	dbcc tune() is used to update the in cache structures. The
**	exec of the stored procedure sp_chgattribute for this option
**	is not replicated on purpose. Doing this could seriously
**	impact performance on the replicated server if the workload on
**	the replicated server does not warrant this property.
**
**	For the dealloc_first_txtpg option we update sysobjects and
**	(un)set the status 02_DEALLOC_FIRST_TXTPG in sysstat2. To
**	handle all the additional logic for this option we call an
**	internal stored procedure sp_optimal_text_space. The return
**	status is checked. 
**
** NOTE: All updates to sysindexes are done by forcing the index access via
** 'csysindexes' so that it's clear that only one row is being updated.
** (Multi-row updates to sysindexes are prohibited.)
*/

/*
**	For virtually hashed tables only options which are
**	allowed are "optimistic_index_lock" and "identitygap".
*/
select @hash_bit = number from master.dbo.spt_values
	where name = "virtually hashed table" and type="O2"
if exists (select * from sysobjects
	where id = object_id(@tabname) and @hash_bit = sysstat2 & @hash_bit)
begin
	/*
	** 19573, "sp_chgattribute is not allowed for %1!,
		   as it is a virtually hashed table."
	*/
	raiserror 19573, @tabname
	return (1)
end

if (@optname = "dealloc_first_txtpg")
begin
	exec @retstatus = sp_optimal_text_space @objname, 
						@optname,
						@optvalue

	if (@retstatus != 0)
	begin
		/*
		** No need to raise an error, this is already
		** done by sp_optimal_text_space.
		*/
		return (@retstatus)
	end
end

if (@optname = "optimistic_index_lock")
begin
	select @dbname = db_name()

	select @dbid = dbid from master.dbo.sysdatabases
		where name = @dbname
	
	/* 
	** This option is only applicable to APL tables.
	*/
	if (@is_table_APL = 0)
	begin
		/*
		** 18983, "The attribute '%1!' is not applicable
		**         to tables with datarow or datapages lock scheme."
		*/
		raiserror 18983, @optname
		return (1)
	end

	if (@optvalue not in (0, 1))
	begin
		/*
		** 18985, "The value for attribute '%1!' must be
		**         either 0 and 1"
		*/
		raiserror 18985, @optname
		return (1)
	end

	/* server defined constant for optimistic index lock */
	select @opt_ind_lock = 268435456

	begin transaction chg_opt_ind_lock

	if (@optvalue = 1)
	begin
		update sysobjects
		set sysstat2 = sysstat2 | @opt_ind_lock
		where name = @objname
	end
	else
	begin
		update sysobjects
		set sysstat2 = sysstat2 & ~@opt_ind_lock
		where name = @objname
	end

	if (@@error != 0)
	begin
		rollback tran

		/*
        	** "The attribute specified '%1!' could 
		**  not be set for the object. "
        	*/
        	raiserror 18987, @optname

		return(1)
	end

	select @newoptvalue = convert(varchar(10), @optvalue)

	dbcc tune(@optname, @dbid, @objname, @newoptvalue)

	if (@@error != 0)
	begin
		rollback tran

		/*
        	** "The attribute specified '%1!' could 
		**  not be set for the object. "
        	*/
        	raiserror 18987, @optname
        	return (1)
	end

	commit transaction

	/*
	** We don't want the exec of sp_chgattribute to
	** be replicated for this option (see comment above
	** where we comment each option).
	*/
	goto proc_end
end

if (@optname = "local_unique_index")
begin
        select @dbname = db_name()

        select @dbid = dbid from master.dbo.sysdatabases
                where name = @dbname


        if (@optvalue not in (0, 1))
        begin
                /*
                ** 18985, "The value for attribute '%1!' must be
                **         either 0 and 1"
                */
                raiserror 18985, @optname
                return (1)
        end

        /* server defined constant for optimistic index lock */
        select @ind_unique_localidx = 64

        select @tmp_indid = indid from sysindexes
                where id = object_id(@objname) and indid < 2

        begin transaction chg_unique_ind_lock

        if (@optvalue = 1)
        begin
                select @dbcc_arg_3 = 1

                update sysindexes
                set status3 = status3 | @ind_unique_localidx
                where id = object_id(@objname) and indid = @tmp_indid
                      and (status3 & @ind_unique_localidx) = 0
		plan "(update (i_scan csysindexes sysindexes))"
        end
        else
        begin
                select @dbcc_arg_3 = 0

                update sysindexes
                set status3 = status3 & ~@ind_unique_localidx
                where id = object_id(@objname) and indid = @tmp_indid
                      and (status3 & @ind_unique_localidx) != 0
		plan "(update (i_scan csysindexes sysindexes))"
        end

        select @upd_rowcnt = @@rowcount

        if (@@error != 0)
        begin
                rollback tran

                /*
                ** "The attribute specified '%1!' could
                **  not be set for the object. "
                */
                raiserror 18987, @optname
                return(1)
        end

        if (@upd_rowcnt != 0)
        begin
                select @dbcc_arg_4 = 0

                dbcc chgindcachedvalue(@optname, @objname, @dbcc_arg_3, @dbcc_arg_4)
        end

        if (@@error != 0)
        begin
                rollback tran

                /*
                ** "The attribute specified '%1!' could
                **  not be set for the object. "
                */
                raiserror 18987, @optname

                return(1)
        end

        commit transaction
end

/* mehul - added this block for setting this option 'ascinserts' via dbcc tune()*/
if (@optname = "ascinserts")
begin
	/*
	** This option is only applicable to APL tables.
	*/
	if (@is_table_APL = 0)
	begin
		/*
		** 18983, "The attribute '%1!' is not applicable
		**         to tables with datarow or datapages lock scheme.
		*/
		raiserror 18983, @optname
		return(1)
	end

	if (@optvalue not in (0,1))
	begin
		/*
		** 18985, "The value for attribute '%1!' must be
		**         either 0 and 1"
		*/
		raiserror 18985, @optname
		return (1)
	end

	dbcc tune(@optname, @optvalue, @objname)

	if (@@error != 0)
	begin
		/*
		** "The attribute specified '%1!' could
		** not be set for the object."
		*/
		raiserror 18987, @optname
		return(1)
	end

	goto proc_end
end



/* 
** From here the third argument is set to the indexid.
*/
select @dbcc_arg_3 = @indid

if @optname = "concurrency_opt_threshold"
begin
	/* 
	** This option is only applicable to DOL tables.
	*/
	if (@is_table_APL = 1)
	begin
		/*
		** 18571, "The attribute '%1!' is not applicable
		**         to tables with allpages lock scheme."
		*/
		raiserror 18571, @optname
		return (1)
	end

	if (@optvalue < -1 or @optvalue > 32767)
	begin
		/*
		** 18612, "Invalid value specified for option '%1!'. 
		**         Valid range of values is %2! to %3!."
		*/
		raiserror 18612, @optname, -1, 32767
		return (1)
	end

	select @newlimit16 = convert(smallint, @optvalue)

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit16 = conopt_thld 
		from systabstats
 		where id = @objid and indid = 0

	if (@curlimit16 = @newlimit16)
		goto proc_end
end
else if @optname = "plldegree"
begin
	if (@optvalue < -1 or @optvalue > 32767)
	begin
		/*
		** 18612, "Invalid value specified for option '%1!'. 
		**         Valid range of values is %2! to %3!."
		*/
		raiserror 18612, @optname, -1, 32767
		return (1)
	end

	select @newlimit16 = convert(smallint, @optvalue)

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit16 = plldegree 
		from systabstats
 		where id = @objid and indid = @indid

	if (@curlimit16 = @newlimit16)
		goto proc_end
end
else if @optname = "reservepagegap"
begin
	/* 
	** Change required in the reservepagegap value of the table/index. 
	** The third argument of dbcc chgindcachedvalue() is index id.
	** The maximum value for reservepagegap set to 255. The only
	** reason for choosing this limit is that number of pages in 
	** an allocation unit is 256. 
	*/
	if (@optvalue < 0 or @optvalue > 255)
	begin
		/*
		** 18572, "The value for attribute '%1!' must be
		**         between %2! and %3!."
		*/
		raiserror 18572, @optname, 0, 255
		return (1)
	end

	select @newlimit16 = convert(smallint, @optvalue)

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit16 = res_page_gap 
		from sysindexes
 		where id = @objid and indid = @indid

	if (@curlimit16 = @newlimit16)
		goto proc_end
end
else if @optname = "identity_gap"
begin
	/* 
	** Raise error if negative value is specified for identity gap.
	*/
	if (@optvalue < 0)
	begin
		/* 
		** 18840, "The value specified for identity gap %1! is not
		**         legal; identity gap must be greater than or equal
		**         to 0."
		*/
		raiserror 18840, @optvalue
		return (1)
	end

	select @newlimit32 = @optvalue

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit32 = identitygap
		from sysindexes
		where id = @objid and indid = @indid

	if (@curlimit32 = @newlimit32)
		goto proc_end
end
else if @optname = "exp_row_size"
begin
	/*
	** Domain validity checks are done by dbcc chgindcachedvalue().
	*/
	select @newlimit16 = convert(smallint, @optvalue)

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit16 = exp_rowsize 
		from sysindexes
		where id = @objid and indid = @indid 

	if (@curlimit16 = @newlimit16)
		goto proc_end

	/* 
	** Set the exp_row_size value of the table/index. 
	**
	** The actual value set in sysindexes table for this table must
	** include the row overhead, which depends on the number of variable
	** length columns in the table. Since this attribute is applicable 
	** only for tables (not indexes) we are using the third argument 
	** of dbcc chgindcachedvalue() to pass the the number of variable 
	** length columns in the table. For this atribute, the sysindexes 
	** table will be updated by dbcc chgindcachedvalue(). This is because 
	** it is easier to calculate the overhead in the server than doing 
	** it here.
	**
	** Get the number of variable length columns the table has. 
	** This is determined by counting the number of columns that have
	** offset < 0. If a column is nullable, its offset will be < 0.
	**
	** This is required to determine the row overhead. 
	*/
	select @varcol_count = count(*)
		from syscolumns
		where id = @objid and offset < 0  

 	select @dbcc_arg_3 = @varcol_count

	/*
	** Update sysindexes and set the exp_row_size value to 0
	** if the column still has a null value. This is to facilitate
	** update to exp_row_size through sysindexes manager later
	** (thru dbcc chgindcachedvalue). This can be removed if we
	** are sure that exp_row_size can never be null. An important
	** point to note is this update is _not_ done within the scope
	** of the transaction which calls dbcc chgindcachedvalue and
	** will not rollback in the event of any failure after this
	** transaction. We don't want to call dbcc chgindcachedvalue
	** in the same transaction as this update, due to some in-memory
	** change rollback requirements (DES) for exp_rowsize.
	*/
	update sysindexes 
	set exp_rowsize = 0
	where id = @objid and indid = @indid and exp_rowsize is null
	plan "(update (i_scan csysindexes sysindexes))"
end
else if @optname = "fillfactor"
begin
	/* 
	** Change the fill_factor value of the table/index. 
	*/
	if (@optvalue < 0 or @optvalue > 100)
	begin
		/*
		** 18572, "The value for attribute '%1!' must be
		**         between %2! and %3!."
		*/
		raiserror 18572, @optname, 0, 100
		return (1)
	end

	select @newlimit16 = convert(smallint, @optvalue)

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit16 = fill_factor 
		from sysindexes
 		where id = @objid and indid = @indid

	if (@curlimit16 = @newlimit16)
		goto proc_end
end
else if (@optname = "max_rows_per_page")
begin
	/*
	** Domain validity checks are done by dbcc chgindcachedvalue().
	*/
	select @newlimit16 = convert(smallint, @optvalue)

	/*
	** Do nothing if the new specified and current values are the same.
	*/
	select @curlimit16 = maxrowsperpage 
		from sysindexes
 		where id = @objid and indid = @indid

	if (@curlimit16 = @newlimit16)
		goto proc_end
end 

/* create a temp table for use by identity_burn_max */
create table #maxid(id numeric(38,0) null)

/* 
** Now, do the actual work of updating system catalogs and the in-memory cache.
*/

/*
** IMPORTANT: The name rs_logexec is significant and is used by 
**            Replication Server
*/
begin transaction rs_logexec
 
if (@optname not in (
	"exp_row_size", 
     	"dealloc_first_txtpg",
	"identity_burn_max"))
begin
	if (@optname = "reservepagegap")
 
 		update sysindexes
 		set res_page_gap = @newlimit16
 		where id = @objid and indid = @indid
		plan "(update (i_scan csysindexes sysindexes))"
 
 	else if (@optname = "max_rows_per_page")
 
 		update sysindexes
 		set maxrowsperpage = @newlimit16
 		where id = @objid and indid = @indid
		plan "(update (i_scan csysindexes sysindexes))"
 
 	else if (@optname = "fillfactor")
 
 		update sysindexes
 		set fill_factor = @newlimit16
 		where id = @objid and indid = @indid
		plan "(update (i_scan csysindexes sysindexes))"

	else if (@optname = "concurrency_opt_threshold")

		update systabstats
			set conopt_thld = @newlimit16
			where id = @objid
			  and indid = 0
 
	else if (@optname = "plldegree")

		update systabstats
			set plldegree = @newlimit16
			where id = @objid
			  and indid = @indid
 
	else if (@optname = "identity_gap")

		update sysindexes
		set identitygap = @newlimit32
		where id = @objid and indid = @indid
		plan "(update (i_scan csysindexes sysindexes))"

 	/* else do_nothing */
 
 	/* If there was an error, @@error will be non-zero */
 	if @@error != 0
 	begin
		rollback transaction

		/*
		** 18573, "Failed to update attribute '%1!' for object '%2!'."
		*/
		raiserror 18573, @optname, @objname
 		return(1)
 	end
end

if (@optname not in 
	("dealloc_first_txtpg", 
	 "identity_burn_max",
	 "local_unique_index")) 
begin
	/*
	** Now, update the in-memory value of the parameter and check
	** whether it succeeded.
	*/
	if (@optname = "identity_gap")
		select @dbcc_arg_4 = @newlimit32
	else
		select @dbcc_arg_4 = convert(int, @newlimit16)

	dbcc chgindcachedvalue(@optname, @tabname, @dbcc_arg_3, @dbcc_arg_4)

	/* If there was an error, @@error will be non-zero */
	if @@error != 0
	begin
		rollback transaction

		/*
		** 18573, "Failed to update attribute '%1!' for object '%2!'."
		*/
		raiserror 18573, @optname, @objname
		return(1)
	end
end

if (@optname = "identity_burn_max")
begin
	if (@optvalue2 is NULL or @optvalue2 = '')
	begin
		rollback transaction

		/*
		** 19115, A value must be specified for attribute '%1!'.
		*/
		raiserror 19115, @optname 
		return (1)
	end

	/* get the name of identity colum from syscolumns */
	select @colname = name from syscolumns
		where id = object_id(@objname)
		and (status & 128 != 0)

	/* Table does not have identity column */
	if (@colname is NULL)
	begin
		rollback transaction

		/*
		** 19116, Table '%1!' does not have an identity column.
		*/
		raiserror 19116, @objname
		return(1)
	end

	/* When one user wants to set the identity value, other users
	** may have access to the same table. Possible inserts from
	** others will affect the max value of the identity column
	** we need for this option. To prevent from this, we will
	** lock the table using an exclusive lock.
	*/
	select @sqltext = "lock table " + @objname 
			  + " in exclusive mode wait 5"
	execute (@sqltext)

	if (@@error != 0)
	begin
		rollback transaction

		/* 
		** 18573, "Failed to update attribute '%1!' for object '%2!'."
		*/ 
		raiserror 18573, @optname, @objname
	end

	/* Make sure we do have EX_TAB lock acquired on the table */
	select @dbname = db_name()
	select @dbid = db_id()

	if not exists (select 1 from master..syslocks
			where id = object_id(@objname)
			and dbid = @dbid 
      			and (type & 1) != 0
			and spid = @@spid)
        begin
                rollback transaction

                /*
                ** 19118, "Object '%1!' is currently being accessed by other
                ** users. Failed to update attribute '%2!'."
                */
                raiserror 19118, @objname, @optname
                return(1)
        end
	

	select @new_idtval = convert(numeric(38,0), @optvalue2)

	/* get the current max identity value in the table */
	select @sqltext = "insert #maxid select "
			  + "max(" + @colname + ") from " + @objname
	execute (@sqltext) 

	if (@@error != 0)
	begin
		rollback transaction

		/*
		** 18573, "Failed to update attribute '%1!' for object '%2!'."
		*/
		raiserror 18573, @optname, @objname
	end

	/*
	** When a user wants to set a value less than 
	** the current max identity value, it may cause a duplicate
	** with the existing identity value in the table. This is 
	** therefore only allowed when the table has no rows.
	*/
	select @curr_max_idtval = id from #maxid
 	
	if (@curr_max_idtval > 0) and 
	    (@new_idtval < @curr_max_idtval)
	begin
		rollback transaction

		/*
		** 19117, "The value %1! for '%2!' attribute must be 
		** greater than or equal to the current max identity 
		** value %3!."
		*/
		raiserror 19117, @new_idtval, @optname, @curr_max_idtval 
		return(1)
	end

	dbcc set_identity_burn_max(@dbname, @objname, @optvalue2)

	/* If there was an error, @@error will be non-zero */
	if (@@error != 0)
	begin
		rollback transaction

		/*
		** 18573, "Failed to update attribute '%1!' for object '%2!'."
		*/
		raiserror 18573, @optname, @objname
		return(1)
	end
end

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	rollback transaction

	/*
	** 17756, "The execution of the stored procedure '%1!'
	** 	   in database '%2!' was aborted because there
	** 	   was an error in writing the replication log
	**	   record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_chgattribute", @dbname
	return(1)
end
 
/* If all was successful, now commit the changes */
commit transaction
 

proc_end:
/*
** We are done. 
** 18122, "'%1!' attribute of object '%2!' changed to %3!."
*/
exec sp_getmessage 18122, @msg output

if (@optname = "identity_burn_max")
	print @msg,@optname, @objname,@optvalue2
else
	print @msg,@optname, @objname,@optvalue

return (0)
go
exec sp_procxmode 'sp_chgattribute', 'anymode'
go
grant execute on sp_chgattribute to public
go
exec sp_procxmode 'sp_chgattribute', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_cacheconfig')
begin
	drop procedure sp_cacheconfig
end
go
print "Installing sp_cacheconfig"
go

/* This stored procedure is for configuring named caches.
**
**	Messages for sp_cacheconfig
**
** 17260, "Can't run %1! from within a transaction."
** 17325, "The length of input parameter '%1!' is longer than the 
**	  permissible %2! characters."
** 18135, "The specified named cache (%1) does not exist"
**
** 18136, "The cache type can only be specified once."
**
** 18137, "Attempt to delete the default data cache.  The default cache may not
**	   be deleted."
**
** 18140, "Cannot modify a cache type to be 'log only' when non-log objects 
**         are bound to it. Use sp_helpcache to print out bound objects 
**	   and sp_unbindcache to delete the cache bindings."
**
** 18155, "The cache type can be 'logonly', 'mixed', or 'inmemory_storage' only. 
**	   Replacement policy can be 'strict', 'relaxed' or 'none' only."
**
** 18177, "Usage: sp_cacheconfig [ cachename [, 'cache_size[K|P|M|G]' ] 
**	   [, logonly | mixed | inmemory_storage] [, strict | relaxed | none] 
**	   [, cache_partition=[1|2|4|8|16|32|64]]]"
**
** 18420, "The replacement policy can only be specified once."
**
** 18332, "You need to be able to set curwrite label to data_low.  
**	   This script will continue in spite of failure to set curwrite.
**	   Please rerun after setting your labels correctly."
**
** 18611, "The specified cache partition number is invalid. A valid cache
**	   partition number should be power of 2 and between 1 to 128."
**
** 18616, "The cache partition can only be specified once."
**
** 19817, "Can not create another configuration for the cache '%1!' due to 
**	   existing cache bindings and an instance specific configuration.
**	   Please use 'sp_unbindcache_all' to remove cache bindings for
**	   cache '%2!'  to create another configuration."
**
** 19976, "The specified cache replacement policy '%1!' for cache '%2!' is 
**	  invalid. Replacement policy 'none' is applicable to cache of type 
**	  type 'inmemory_storage' and replacement policy 'strict | relaxed'
**	  is applicable to cache of type 'logonly | mixed'."
**
** 19977, "Changing the cache type for cache '%1!' from or to type '%2!' is not 
**	  allowed."
**        
** 19978, "Changing the cache replacement policy between '%1!' and '%2!' is 
**	  not allowed."
**				
** 19595, "Instance '%1!' does not exist."
**
** 19656, "Deleting instance-specific configuration of 'default data cache' 
**	   is not dynamic; restart instance '%1!' to effect the changes."
**
** 19981, "The cache type for the 'default data cache' cannot be modified."
**
** 19982, "The cache type for '%1!' cannot be modified to '%2!' as it is 
**	   already configured as '%3!' on other instance(s). A cache can be
**	   configured to be either 'mixed', or 'logonly', but not both"
*/
create procedure sp_cacheconfig
@cachename 	varchar(255) = "%",
@parm1		varchar(133) = NULL,
@parm2		varchar(133) = NULL,
@parm3		varchar(133) = NULL,
@parm4		varchar(133) = NULL,
@parm5		varchar(255) = NULL
as
/*
**  The following variable are used to print out cache configuration 
**  information.
*/
declare @instancename		varchar(255)  
declare @instanceid		int		
declare @print_str		varchar(1024)	/* for printing error msgs */
declare	@sysconf_name		varchar(255)	/* cache name from sysconfigures */
declare @io_sz_comment		char(255)	/* io size string from sysconfigures */
declare @cache_type		char(24)	/* cache type from sysconfigures */
declare	@stat_to_print		char(10)	/* status string from sysconfigures */
declare @pool_status		char(21)	/* status of pool */
declare @config_sz_str		varchar(13)	/* configured sz from sysconfigures */
declare @run_sz_str		char(13)	/* run size from sysconfigures */
declare @io_sz_str		varchar(3)	/* pool size (in KB) */
declare @maxnamelen		int
declare @maxtypelen		int
declare @maxstatuslen		int
declare @maxlen			int
declare @operation		int		/* update, insert, or delete */
declare @config			int		/* config value from sysconfigures */
declare @size			int		/* generic size of a cache or pool */
declare @row_count		int		/* # cache/pool rows in sysconfigures */
declare @cache_count		int		/* # cache rows in sysconfigures */
declare	@retstat		int		/* return status from other sprocs called */
declare @wash_size		int		/* wash size of a pool */
declare @apf_value		int		/* apf percent of a pool */
declare	@run_size		int		/* run_size of a pool or cache */
declare	@config_size		int		/* config size of a pool or cache */
declare @total_cfg_sz 		float		/* total, all configured cache mem */
declare @total_run_sz		float		/* total, all run cache mem */
declare	@oldglobalstat		int		/* global status from sysconfigures  */
declare	@stat			int		/* tmp var to collect status from sysconfigures */
declare	@oldlocalstat		int		/* status from sysconfigures for an instance */
declare @c_part_stat		int		/* status for cache partition */
declare	@old_stat		int		/* status before update of sysconf. */
declare	@runstat		int		/* status from syscurconfigs */
declare	@new_cache_type 	int		/* modified value of cache type */
declare @old_repl		int		/* original replacement policy */
declare @new_repl		int		/* modified replacement policy */
declare @dflt_ctype 		int		/* default cache type when unspecified */
declare @dflt_crepl 		int		/* default cache repl when unspecified */
declare @mincachename		varchar(255)	/* for looping through temp table */
declare @pools_available 	int		/* whether all pools are available */
declare @cfg_cache_repl		varchar(11)	/* to print cfg cache replacement */
declare @run_cache_repl		varchar(11)	/* to print run cache replacement */
declare @cfg_cache_partition	int		/* cache partition number	*/
declare @cache_partition_parm	varchar(30) 	/* parameter for cache partition*/
declare @instance_parm		varchar(133)	/* parameter for instance name	*/ 	
declare @cache_partition_loc	int         	/* for parsing partition parms	*/
declare @cache_partition_str	varchar(255)	/* for parsing partition number */
declare @cache_part_temp	int  	    	/* cache partition number	*/
declare @partition_number	int  	    	/* cache partition number	*/
declare @dflt_cpart		smallint	/* default part # if unspecified */
declare @msg			varchar(255)	/* used to print new pool info */
declare	@pool_config_id		int		/* new pool id */
declare @default_pool_size	int		/* config size for default pool */
declare @diff_config_run_size	int		/* difference in config and run size */
declare @config_file_name	varchar(255) 	/* Name of the config file */
/* 
** The following variables are required to copy pool config information 
** from sysconfigures
*/
declare @value		int
declare @comment	varchar(255)
declare @name		varchar(255)
declare @parent		smallint
declare @value2		varchar(255)
declare @value3		int
declare @value4		int
declare @total_config	int

/* declare and init the config_admin() commands used in this sproc */
declare   @cmdbindingcheck	int
	, @cmdupdateconfigfile	int

select    @cmdbindingcheck 	= 9
	, @cmdupdateconfigfile 	= 32

/* declare and init the config options used in this sproc */
declare	  @cfgcacheinsert	int
	, @cfgcacheupdate	int
	, @cfgcachedelete	int
	, @cfguserdefinedcache	int
	, @cfgbuffer2kpoolgrp	int
	, @cfgcfgfilename       int
	

select	  @cfgcacheinsert	= 6
	, @cfgcacheupdate	= 7
	, @cfgcachedelete	= 8
	, @cfguserdefinedcache 	= 19
	, @cfgbuffer2kpoolgrp	= 20
	, @cfgcfgfilename       = 114	
	
/* cache status bit constants used in this sproc */
declare	  @defaulttype		int
	, @mixedtype		int
	, @logonlytype		int
	, @hkignore		int
	, @activetype		int
	, @activependingtype	int
	, @deletependingtype	int
	, @relaxedlru		int
	, @strictlru		int
	, @cmpartspecified	int
	, @deletedtype		int
	, @inmemtype		int
	, @nonereplace		int

select	  @defaulttype		= 1
	, @mixedtype		= 2
	, @logonlytype		= 4
	, @hkignore		= 16
	, @activetype		= 32
	, @activependingtype	= 64
	, @deletependingtype	= 128
	, @relaxedlru		= 256
	, @strictlru		= 512
	, @cmpartspecified	= 1024
	, @deletedtype		= 16384
	, @inmemtype		= 65536 
	, @nonereplace		= 131072 



select @instancename = NULL
select @instanceid = NULL



/* Dont allow sp_cacheconfig to run with in a transaction */
if @@trancount > 0
begin
	raiserror 17260, "sp_cacheconfig"
	return 1
end
else
begin
	set transaction isolation level 1
	set chained off
	set nocount on
end

/* Check to see that the @cachename is valid. */
if char_length(@cachename) > 30
begin
	raiserror 17325, @cachename, 30
	return 1
end

/*
** 	If sp_cacheconfig is excuted without any parameter or only cache 
**	name is provided, or instance is name is provided print the 
** 	cache information. Otherwise, process the cache as indicated by
**	the input parameters.
*/

if ((@parm1 = NULL or charindex("instance ", @parm1) = 1) and @parm2 = NULL
	 and @parm3 = NULL and @parm4 = NULL and @parm5 = NULL)
begin	-- {
	/*
	** Create temp tables to store cache information
	** and pool information
	*/
	create table #cache_info	(
		cache_name varchar(255),
		Status varchar(9),
		Type  	varchar(24),
		ConfigReplacement varchar(11),
		RunReplacement varchar(11),
		configval	char(12),
		runval  	char(12),
		ConfigPartition int,
		RunPartition int,
		instanceid tinyint null)
	create table #pool_detail (
		cache_name varchar(255),
		io_sz varchar(8), 
		wash_size varchar(13),
		configval	char(12),
		runval  	char(12),
		pool_status	char(21),
		apf_value varchar(9),
		instanceid tinyint null)

	if @parm1 = NULL
	begin
		/*
		** If parm1 is NULL then there are two cases here
		** case 1: @cachename is name of the cache to display
		**	   information of cache
		** case 2: @cachename is an instance name to disply cache
		**	   information of instance
		*/
		if (charindex("instance ", @cachename) = 1)
		begin


			if @instanceid = NULL
			begin
				raiserror 19595, @instancename
				return 1
			end

			select @cachename = "%"
		end
		else
		begin
			select @instancename = NULL
			select @instanceid = NULL
		end
	end


	/*
	**  Create temp table with just those rows from sysconfigures that have
	**  to do with cache configuration.
	*/
	select co.config, parent, co.name, 
		co.value config_size, co.status, cu.status runstat,
		co.comment, cu.value run_size, 
		memory_used wash_size, apf_percent apf_value,
		co.value4 cfg_cache_partition

	into #syscacheconfig
	from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
	where 1=2

	/*
	** Get all global cache information first
	*/

	insert #syscacheconfig
	select distinct co.config, parent, co.name, 
		co.value config_size, co.status, cu.status runstat,
		co.comment, cu.value run_size, 
		memory_used wash_size, apf_percent apf_value,
		co.value4 cfg_cache_partition

	from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
	where parent = @cfguserdefinedcache
		and co.config = cu.config
		and co.name = cu.comment
		and name like "%" + @cachename + "%" 

	order by name, config




	/*
	** Determine the number of caches
	*/
	select @cache_count = count(*) 
		from #syscacheconfig where config = @cfguserdefinedcache
	
	/*
	** 18135, "The specified named cache (%1) does not exist"
	*/
	if @cache_count = 0
	begin
		select @cachename = rtrim(@cachename)
		raiserror 18135, @cachename
		return 1
	end

	/*
	** Determine the total number of caches, and pools within caches.
	*/
	select @row_count = count(*) 
		from #syscacheconfig where parent = @cfguserdefinedcache

	/*
	**  Intialize total configured and run sizes.
	*/
	select @total_cfg_sz = 0, @total_run_sz = 0

	/* Initialize the default pool size and difference */
	select @default_pool_size = 0, @diff_config_run_size = 0

	/* Until determined otherwise, all defined pools are available */
	select @pools_available = 1

	declare sysc_cursor cursor
	for select config, config_size, name, status, runstat, comment,
	run_size, wash_size, apf_value, cfg_cache_partition

	from #syscacheconfig
	order by name
 
	open sysc_cursor

	while (@row_count > 0)
	begin
		fetch sysc_cursor into @config, @config_size, @sysconf_name, 
				@stat, @runstat, @io_sz_comment, @run_size,
				@wash_size, @apf_value, @cfg_cache_partition
 
		if @stat & @deletedtype = @deletedtype
		begin
			/* Cache is deleted */
			select @row_count = @row_count - 1
			continue
		end

		/*
		** Append the instance name to cache name in case the cache 
		** is local. This will make sure that the cache names are
		** used along with scope.
		*/
 

		/*
		**  A config value of 19 means this rows holds the total size
		**  and type information for the whole cache.
		*/
		if @config = @cfguserdefinedcache
		begin
			/*
			** Check to see if this cache is actively running, 
			** has been created but the server has not been 
			** re-booted so it hasn't been instantiated, or it's 
			** been deleted and still occupying memory because 
			** the server has not been rebooted yet.
			*/
			if (@stat & @activetype = @activetype)
			begin
				select @stat_to_print = "Active"
			end
			if (@stat & @activependingtype = @activependingtype)
			begin
				select @stat_to_print = "Pend/Act"
			end
			if (@stat & @deletependingtype = @deletependingtype)
			begin
				select @stat_to_print = "Act/Del"
				select @config_size = 0
			end

			/*
			** Config size of cache is set to zero during startup
			** if it is set to DEFAULT or is not configured.
			**
			** If config size of default data cache is zero,
			** set it equal to run size(default cache size).
			*/
			if((@config_size = 0) and 
			(@sysconf_name like "default data cache"))
			begin
				select @config_size = @run_size
			end
			
			/* 
			** Save the difference in config value and run value
			** of the cache size for default data cache.
			*/
			if(@sysconf_name like "default data cache")
			begin
				select @diff_config_run_size = 
						(@run_size - @config_size)
			end

			/*
			**  Update totals for config and run size
			*/
			select @total_cfg_sz = @total_cfg_sz + 
				convert(float, @config_size)
			select @total_run_sz = @total_run_sz + 
				convert(float, @run_size)

			/*
			**  Convert run_size and config_size to megabyte 
			**  values stored as strings
			*/
			select @run_sz_str =  rtrim(str(convert(float,@run_size)/1024,9,2))
				+ " Mb"
			select @config_sz_str = rtrim(str(convert(float,@config_size)/1024,9,2))
				+ " Mb"

			/*
			**  Extract the status and the type from the status 
			**  field since  both bit values are stuffed into 
			**  this one field.
			*/
			if (@stat & @mixedtype = @mixedtype)
			begin
				if (@stat & @hkignore = @hkignore)
					select @cache_type = "Mixed, HK Ignore"
				else
					select @cache_type = "Mixed"
			end
			if (@stat & @logonlytype = @logonlytype)
			begin
				select @cache_type = "Log Only"
			end
			if (@stat & @defaulttype = @defaulttype)
			begin
				select @cache_type = "Default"	
			end
			if (@stat & @inmemtype = @inmemtype)
			begin
				select @cache_type = "In-Memory Storage"
			end
	

			/* 
			**  Determine configured cache replacement policy
			*/
			if (@stat & @relaxedlru = @relaxedlru)
			begin
				select @cfg_cache_repl = "relaxed LRU"
			end
			else if (@stat & @nonereplace = @nonereplace)
			begin
				select @cfg_cache_repl = "none"
			end
			else
			begin
				select @cfg_cache_repl = "strict LRU"
			end

			/* 
			**  Determine running cache replacement policy
			*/
			if (@runstat & @relaxedlru = @relaxedlru)
			begin
				select @run_cache_repl = "relaxed LRU"
			end
			else if (@runstat & @nonereplace = @nonereplace)
			begin
				select @run_cache_repl = "none"
			end
			else
			begin
				select @run_cache_repl = "strict LRU"
			end

			if @instanceid = NULL
			begin
				select @instanceid = 0
			end
			/*
			**  Now store the line of output for this cache
			*/
			insert #cache_info values (@sysconf_name, 
				@stat_to_print, @cache_type, 
				@cfg_cache_repl, @run_cache_repl,
				@config_sz_str, @run_sz_str,
				@cfg_cache_partition, @apf_value,
				@instanceid)
		end
		else
		begin
			/*
			** Row contains pool information. Select required
			** information.
			*/

			/* Determine pool size (in KB) */
			select @io_sz_str = substring(@io_sz_comment,1,
						charindex("K",@io_sz_comment)-1)

			/*
			** If it is the default pool for default data cache 
			** set the config size to be equal to its run size.
			*/
			if((@config_size = 0) and 
			(@sysconf_name like "default data cache") and
			((@io_sz_str = convert(varchar(3), @@maxpagesize/1024))))
			begin
				select @config_size = @run_size
				select @default_pool_size = @run_size
			end

			/* Determine the availability of the pool */
			if ((@config_size = 0) and 
			    (@run_size > 0) and
			    (@io_sz_str != convert(varchar(3), @@maxpagesize/1024)))
			begin
				/*
				** Pools, other than the default pool, which
				** have a configured size of 0, but a run size 
				** greater than zero could not be fully 
				** removed. Such pools will have been marked 
				** as unavailable by the server.
				*/
				select @pool_status = "Unavailable/deleted"
				select @pools_available = 0
			end
			else if ((@run_size < (@@maxpagesize * 256 /1024)) and
				 (@io_sz_str != convert(varchar(3), @@maxpagesize/1024)))
			begin
				/*
				** Pools, other than the default pool, which
				** have a run size less than 256 *
				** (logical pagesize) will have
				** been marked as unavailable by the
				** server, since they are too small
				** to be used.
				*/
				select @pool_status = "Unavailable/too small"
				select @pools_available = 0
			end
			else
			begin
				/* Pool is available */
				select @pool_status = ""
			end

			if @instanceid = NULL
			begin
				select @instanceid = 0
			end
			insert #pool_detail values 
				(@sysconf_name, 
				 replicate(" ", 6 -
					(charindex("K", @io_sz_comment))) +
					substring(@io_sz_comment,1,
				 	charindex("K",@io_sz_comment)-1) + 
					" Kb ",
				 str(@wash_size, 10) + " Kb",
				 rtrim(str(convert(float,@config_size) / 
					1024, 9, 2)) + " Mb",
				 rtrim(str(convert(float,@run_size) / 
					1024, 9, 2)) + " Mb",
				 @pool_status, 
				 str(@apf_value, 6),
				 @instanceid)
		end
		select @row_count = @row_count - 1
	end

	close sysc_cursor

	/*
	** If difference in the config size and run size of default data cache 
	** is not zero, it means that the cache has been shrinked. The memory 
	** lost due to cache shrinking comes from the default pool. Hence, this
	** difference in run size and config size of cache should be subtracted 
	** from the config size of default pool.
	**
	** Calculate the correct config size of default pool by subtracting
	** the difference in run value and config value of the cache size
	** and update the temp table.
	*/
	if(@diff_config_run_size != 0)
	begin
		select @default_pool_size = @default_pool_size - 
							@diff_config_run_size
		update #pool_detail
		set configval = (rtrim(str(convert(float,@default_pool_size) /
					1024, 9, 2)) + " Mb")
		where cache_name like "default data cache" and
		io_sz like "%" + (convert(varchar(3), @@maxpagesize/1024)) + "%"
	end

	select @maxnamelen = max(char_length(cache_name)) from #cache_info
	select @maxtypelen = max(char_length(Type)) from #cache_info
	select @maxstatuslen = max(char_length(Status)) from #cache_info

     if (@maxnamelen <= 30)
     begin
	/* Print cache information. */
	exec sp_autoformat @fulltabname = #cache_info,
	@selectlist = "'Cache Name' = cache_name, 'Status' = Status, 
	'Type' = Type,'Config Value' = configval, 'Run Value' = runval"
	
	/* 4 is for the four ' ' */
	select @maxlen = @maxnamelen + @maxtypelen + @maxstatuslen + 4

	/*  Now print totals. */
	select @run_sz_str =  str(convert(float,@total_run_sz) / 1024, 7, 2) + 
					" Mb"
	select @config_sz_str = str(convert(float,@total_cfg_sz) / 1024, 7, 2) +
					" Mb"
	select @print_str = replicate(' ', @maxlen) + "------------ ------------"
	print @print_str 
	select @print_str = replicate(' ', @maxnamelen + @maxstatuslen + 4) + "Total    " + 
		convert(char(13), @config_sz_str) + @run_sz_str
	print @print_str
     end
	else
     begin
	/* Print cache information. */
	select cache_name "Cache Name", Status, Type,
		configval "Config Value", runval "Run Value"
	from #cache_info

	 /*  Now print totals. */
	select @run_sz_str =  str(convert(float,@total_run_sz) / 1024, 7, 2) +
					" Mb"
	select @config_sz_str = str(convert(float,@total_cfg_sz) / 1024, 7, 2) +
					" Mb"
	select @print_str = convert(char(279), " ") + "------------ ------------"
	print @print_str
	select @print_str = convert(char(272), " ") + "Total    " +
			convert(char(13), @config_sz_str) + @run_sz_str
	print @print_str
      end
	
	/*
	** Now print cache/pool detail information 
	** A "Pend/Act" cache will not have pools configured
	*/
	select @instanceid = min(instanceid)
		from #cache_info
		where Status != "Pend/Act"
	
	select @mincachename = min(cache_name) 
		from #cache_info 
		where Status != "Pend/Act" and instanceid = @instanceid

	while @mincachename is not null
	begin

	/* 
	** Print information about the cache
	*/

	print '=========================================================================='
	select @print_str = "Cache: " + @mincachename + ",   Status: " + Status + 
			",   Type: " + Type
		from #cache_info
		where cache_name = @mincachename
	print @print_str
	select @print_str = "      Config Size: " + ltrim(configval) + 
		",   Run Size: " + ltrim(runval)
		from #cache_info
		where cache_name = @mincachename
	print @print_str
	select @print_str = "      Config Replacement: " + ConfigReplacement + 
		",   Run Replacement: " + RunReplacement
		from #cache_info
		where cache_name = @mincachename
	print @print_str
	select @print_str = "      Config Partition:   " + 
			    str(convert(int,ConfigPartition)) + 
			    ",   Run Partition:   " + 
			    str(convert(int,RunPartition))  
		from #cache_info
		where cache_name = @mincachename
	print @print_str

	/*
	** Now print the pool information. Only print status information
	** if any pool is unavailable. This will happen so seldom, that for
	** the most part it is better to leave the output as documented in 
	** the user manuals to prevent unwanted Tech Support calls about
	** the meaning of this status field. 
	*/
	if exists (select * from #pool_detail where cache_name = @mincachename)
	begin
		if (@pools_available = 1)
		begin
			select io_sz "IO Size", wash_size "Wash Size", 
				configval "Config Size", runval "Run Size",
				apf_value "APF Percent"
				from #pool_detail
				where cache_name = @mincachename 
				order by io_sz
		end
		else
		begin
			select io_sz "IO Size", wash_size "Wash Size", 
				configval "Config Size", runval "Run Size", 
				apf_value "APF Percent",
				pool_status "Status"
				from #pool_detail
				where cache_name = @mincachename 
				order by io_sz
		end
	end
	select @mincachename = min(cache_name)
		from #cache_info 
		where cache_name > @mincachename 
			and Status != "Pend/Act" 
			and instanceid = @instanceid

	if @mincachename is null
	begin
		select @instanceid = min(instanceid)
			from #cache_info
			where Status != "Pend/Act" 
			and instanceid > @instanceid
		
		select @mincachename = min(cache_name)
			from #cache_info 
			where Status != "Pend/Act"
				and instanceid = @instanceid

		if @mincachename is null 
		 		break
	end
	end
end	-- }
else
begin	-- {
	/* 
	** check if user has sa role, proc_role will also do auditing
	** if required. proc_role will also print error message if required.
	*/
	if (proc_role("sa_role") = 0)
		return 1

	/*
	**  We actually have some real work to do; either insert, modify, or
	**  delete a cache. Initialize configured size and new type.
	*/
	select @config_sz_str = NULL
	select @new_cache_type = 0
	select @new_repl = 0
	select @dflt_ctype = 0
	select @dflt_crepl = 0
	select @c_part_stat = 0
	select @partition_number = 1
	select @cache_partition_parm = NULL  
	select @instance_parm = NULL
	select @dflt_cpart = 0
	select @instancename = NULL
	select @instanceid = NULL

	/*
	** Process the @parm1 
	**
	** Here the @parm1 can be either a cache size, cache type,
	** replacement policy, cache partition number or instance name.  
	**
	** First check whether this is a cache type.
	*/
	if @parm1 IN ("logonly", "mixed", "inmemory_storage")
	begin
		if @parm1 = "logonly"
			select @new_cache_type = @logonlytype
		else if @parm1 = "mixed"
			select @new_cache_type = 2
		else
			select @new_cache_type = @inmemtype 
	end
	/* Check whether this is a cache replacement policy.*/
	else if @parm1 IN ("strict", "relaxed", "none")
	begin
		if @parm1 = "strict" or @parm1 = "relaxed"
		begin
			if (@new_cache_type & @inmemtype = @inmemtype)
			begin
				/* 
				** It is an error if cache type is 
				** 'inmemory_storage' but replacement policy 
				** is not 'none'.
				*/
				raiserror 19976, @parm1, @cachename
				return 1
			end
			else
			begin
				if @parm1 = "strict"
					select @new_repl = 512
				else
					select @new_repl = 256
			end
		end

		if @parm1 = "none"
		begin
			if (@new_cache_type & @inmemtype != @inmemtype)
			begin
				/*
				** It is an error if replacement policy is
				** 'none' but cache type is not 
				** 'inmemory_storage'.
				*/
				raiserror 19976, @parm1, @cachename
				return 1
			end
			else
			begin
				select @new_repl = @nonereplace 
			end
		end
	end
	/* Check whether this is a cache partition number. */
	else if (patindex("%cache_partition%", @parm1) != 0) 
	begin
		/* Save the partition parameter string for later process.*/
		select @cache_partition_parm = @parm1
	end
	else if (patindex("instance ", @parm1) != 0)
	begin
		/* Save the instance parameter string for later process.*/
		select @instance_parm = @parm1
	end
	else
	begin
		/* 
		** Here @parm1 could contain a junk string value or a
		** legitimate cache size.
		*/
		if patindex("%[a-z,A-Z]%", @parm1) = 1
		begin
			raiserror 18155
			raiserror 18177
			return 1
		end
		else
		begin
			/* Save the cache size parameter string.*/
			select @config_sz_str = @parm1
		end	
	end

	/*
	** Process the @parm2.
	**
	** Here the @parm2 can be either a cache type, replacement policy,
	** cache partition number or instance name.  
	*/
	if @parm2 IN ("logonly", "mixed", "inmemory_storage")
	begin
		/*
		**  It's a syntax error if the parm1 already had the cache
		**  type in it.
		*/
		if @new_cache_type != 0
		begin

			raiserror 18136
			raiserror 18177
			return 1
		end	

		/* It's 'log only' or 'mixed' or 'inmemory_storage'. */
		if @parm2 = "logonly"
			select @new_cache_type = @logonlytype
		else if @parm2 = 'mixed'
			select @new_cache_type = @mixedtype 
		else 
			select @new_cache_type  = @inmemtype
	end
	else if @parm2 IN ("strict", "relaxed", "none")
	begin
		/*
		**  It's a syntax error if the parm1 already had the 
		**  replacement policy in it.
		*/
		if @new_repl != 0
		begin

			raiserror 18420
			raiserror 18177
			return 1
		end	

		if @parm2 = "strict" or @parm2 = "relaxed"
		begin
			if (@new_cache_type & @inmemtype = @inmemtype)
			begin
				/*
				** It is an error if cache type is 
				** 'inmemory_storage' but replacement policy 
				** is not 'none'.
				*/
				raiserror 19976, @parm2, @cachename
				return 1
			end
			else
			begin
				if @parm2 = "strict"
					select @new_repl = 512
				else
					select @new_repl = 256
			end
		end

		if @parm2 = "none"
		begin
			if (@new_cache_type & @inmemtype != @inmemtype)
			begin
				/*
				** It is an error if replacement policy is
				** 'none' but cache type is not 
				** 'inmemory_storage'.
				*/
				raiserror 19976, @parm2, @cachename
				return 1
			end
			else
			begin
				select @new_repl = @nonereplace
			end
		end
	end
	else if (patindex("%cache_partition%", @parm2) != 0) 
	begin
		/* It's a syntax error if partition already specified.*/
		if @cache_partition_parm is not NULL
		begin
			raiserror 18616
			raiserror 18177 
			return 1
		end	
		
		select @cache_partition_parm = @parm2
	end

	else
	begin
		/* Issue error if @parm2 has junk string. */
		if @parm2 is not NULL
		begin
			raiserror 18155
			raiserror 18177
			return 1
		end
	end
	
	/*
	** Process the @parm3.
	**
	** At this point, @parm3 is either a replacement policy, partition
	** number, instance name, NULL, or a junk string.  
	*/
	if @parm3 IN ("strict", "relaxed", "none")
	begin
		/*
		**  It's a syntax error if the parm1 or parm2 already had the
		**  replacement policy in it.
		*/
		if @new_repl != 0
		begin

			raiserror 18420
			raiserror 18177
			return 1
		end	

		if @parm3 = "strict" or @parm3 = "relaxed"
		begin
			if (@new_cache_type & @inmemtype = @inmemtype)
			begin
				/*
				** It is an error if cache type is 
				** 'inmemory_storage' but replacement policy 
				** is not 'none'.
				*/
				raiserror 19976, @parm3, @cachename
				return 1
			end
			else
			begin
				if @parm3 = "strict"
					select @new_repl = 512
				else
					select @new_repl = 256
			end
		end

		if @parm3 = "none"
		begin
			if (@new_cache_type & @inmemtype != @inmemtype)
			begin
				/*
				** It is an error if replacement policy is
				** 'none' but cache type is not 
				** 'inmemory_storage'.
				*/
				raiserror 19976, @parm3, @cachename
				return 1
			end
			else
			begin
				select @new_repl = @nonereplace
			end
		end
	end
	else if (patindex("%cache_partition%", @parm3) != 0) 
	begin
		if @cache_partition_parm is not NULL
		begin
			raiserror 18616 
			raiserror 18177 
			return 1
		end	
		
		select @cache_partition_parm = @parm3
	end

	else
	begin
		if @parm3 is not NULL
		begin
			raiserror 18155
			raiserror 18177
			return 1
		end
	end

	/*
	** Process the @parm4.
	**
	** At this point, @parm4 is either a partition number, instance name,
	** NULL, or a junk string.
	*/
	if (patindex("%cache_partition%", @parm4) != 0) 
	begin
		if @cache_partition_parm is not NULL
		begin
			raiserror 18616 
			raiserror 18177 
			return 1
		end	
		
		select @cache_partition_parm = @parm4
	end

	else
	begin
		if @parm4 is not NULL
		begin
			raiserror 18177
			return 1
		end
	end	

	/*
	** Process the @parm5.
	**
	** At this point, @parm5 is either a partition number, instance name,
	** NULL, or a junk string.
	*/
	if (patindex("%cache_partition%", @parm5) != 0) 
	begin
		if @cache_partition_parm != NULL
		begin
			raiserror 18616 
			raiserror 18177 
			return 1
		end
		
		select @cache_partition_parm = @parm5
	end

	else
	begin
		if @parm5 != NULL
		begin
			raiserror 18177
			return 1
		end
	end

	/* Extract and validate instance name from instance parameter. */


	/*
	**  If options are not explicitly given, we use the default value
	**  for cache creation.  For cache update case, we set flags to
	**  not overwrite the existing values. 
	*/
	if @new_cache_type = 0
	begin
		/*
		** If the cache type was not specified explicitly,
		** then default cache type to mixed. If the cache
		** name is 'default data cache' then the cache type is
		** 'default'. 
		** We also indicate that the cache type was unspecified
		** by setting @dflt_ctype to 1. So that later, if we are
		** doing an update, we dont overwrite a logonly cache type
		** with the default mixed type.
		*/
		if (charindex("default data cache",@cachename) != 0)
		begin
			select @new_cache_type = @defaulttype  
		end
		else
		begin
			select @new_cache_type = @mixedtype  
		end
		select @dflt_ctype = 1	    /* cache type was unspecified */
	end

	if @new_repl = 0
	begin
		/*
		** If the cache replacement was not specified explicitly,
		** Set dflt_crepl so that later on we don't overwrite the 
		** replacement policy of a cache that is using the DEFAULT
		** replacement policy.
		*/
		if @new_cache_type = @inmemtype
		begin
			/* The default replacement policy for 'inmemory_storage'
			** cache is 'none'.
			*/
			select @new_repl = @nonereplace
		end
		else
		begin
			select @dflt_crepl = 1
		end
	end

	/*
	** If the cache partition was not specified explicitly,
	** set @partition_number to 0. Also set flag dflt_cpart to 1
	** so later on we don't overwrite the existing partition number.
	*/
	if @cache_partition_parm  is NULL
	begin
		select @dflt_cpart = 1
	end
	/* cache partition was specified, validate the partition number. */
	else
	begin	-- {
		
		select @cache_partition_loc = patindex("%=%", 
					@cache_partition_parm)

		/* if there is no "=" sign then return an error */
		if (@cache_partition_loc = 0)
		begin
			raiserror 18611
			return 1
		end
			
		/* skip the "=" part */
                select @cache_partition_loc = @cache_partition_loc + 1

        	select @cache_partition_str = convert(varchar(255), 
					substring(@cache_partition_parm,
                                        @cache_partition_loc,
                                        char_length(@cache_partition_parm) -
                                                @cache_partition_loc + 1))

		if @cache_partition_str != "default"
		begin
			/*
			** This is a new status to indicate that a valid cache
			** partition other than default is passed
			*/
			select @c_part_stat = @cmpartspecified

			select @partition_number =
				convert(int, @cache_partition_str)

			/*
			**  The cache partition number needs to be 
			**  within 1 to 128
			*/
			if (@partition_number < 1) OR (@partition_number > 128)
			begin
				raiserror 18611 
				return 1
			end

			/* The cache partition number needs to be power of 2.*/
			select @cache_part_temp = 2
			while @cache_part_temp < @partition_number
				select @cache_part_temp = @cache_part_temp * 2
			if (@partition_number != 1)
				AND (@cache_part_temp != @partition_number)
			begin
				raiserror 18611 
				return 1
			end
		end
	end	-- }

	/* Convert the specified size into kbytes. */
	select @size = 0
	if @config_sz_str is not NULL
	begin
		exec @retstat = sp_aux_getsize @config_sz_str, @size output

		if @retstat = 0
		begin
			raiserror 18177
			return 1
		end
	end
	
	/*
	**  Find out if we need to update, insert, or delete this cache
	**  from sysconfigures.
	*/
	select @oldlocalstat = -1
	select @oldglobalstat = -1

	/* fetch the instance specific current cache status. */
	select	@oldlocalstat = status 
	from	master.dbo.sysconfigures 
	where	parent = @cfguserdefinedcache
	  and	config = @cfguserdefinedcache 
	  and	name = @cachename

	/* 
	** fetch the current global cache status. Please note that for a global
	** cache, it is same as @oldlocalstat fetched above.
	*/
	select	@oldglobalstat = status
	from	master.dbo.sysconfigures 
	where	parent = @cfguserdefinedcache
	  and	config = @cfguserdefinedcache
	  and	name = @cachename


	/* If the cache exists then it's an update/delete.*/
	if (@oldlocalstat != -1) and (@oldlocalstat & @deletedtype != @deletedtype)
	begin	-- {
		/* If the specified size is 0, then delete the cache. */
		if @config_sz_str is not NULL AND  @size = 0
		begin
			if (@oldlocalstat & @defaulttype = @defaulttype) 

			begin
				/* Can't delete the global default cache.*/
				raiserror 18137
				return 1
			end

			/*  This is a cache delete. */
			select @operation = @cfgcachedelete
		end
		else
		begin
			/*  This is a cache update. */
			select @operation = @cfgcacheupdate
		end
	end	-- }
	else
	begin	-- {
		if (@config_sz_str = NULL or @size = 0) 
		begin
			/* Can't create a cache with 0 size.*/
			raiserror 18135, @cachename
			return 1
		end

		select @operation = @cfgcacheinsert
	end	-- }



	/* 
	** Prevent cache creation, or update, if it leads to incompatible status
	** for the same cache on different instances. If no new status was
	** explicitly provided by the user (@dflt_ctype = 1), we retain the old
	** status during update and so do not need this check.
	*/
	if 	(@operation = @cfgcacheinsert)
	   OR 	((@operation = @cfgcacheupdate) AND (@dflt_ctype != 1))
	begin	-- {
		
		/* 
		** Note, the sproc accepts only 'mixed'/'log-only' status as
		** input. And for default data cache it should never be allowed.
		*/
		if (charindex("default data cache", @cachename) != 0)
			AND (@dflt_ctype != 1)
		begin 
			raiserror 19981
			return 1
		end
		

	end	-- } 
	
	/*
	**  Begin a transaction.  We'll be modifying rows in sysconfigures
	**  and then calling the built-in function config_admin to verify the
	**  new configuration.  If config_admin fails the verification phase
	**  we'll have to rollback the changes to sysconfigures.
	*/

	begin tran cacheconfig

	if @operation = @cfgcacheinsert
	begin	-- {
		/*
		** This is a cache create. Insert a row for the new
		** cache into sysconfigures. The "status" field
		** is made up of several components:
		**	The cache type (eg "logonly" or "mixed" or "default"
		** 	for instance specific default data cache)
		**	The initial cache status (set to "pending/active")
		**	The cache replacement policy ("strict" or "relaxed")
		**	Whether the cache was user-partitioned or not.
		** 
		** NOTE that the @oldlocalstat may be = -1 here in which case
		** the following condition will be always true (-1 = 0xffff). 
		** But it is harmless as we're only deleting entries marked 
		** deleted.
		*/
		if (@oldlocalstat & @deletedtype = @deletedtype)
		begin
			/*
			** If there exists any cache entries with same name
			** and status as deleted then delete them.
			*/
			delete from master.dbo.sysconfigures 
			where	parent = @cfguserdefinedcache 
			  and 	name = @cachename
			  and	status = @deletedtype
		end
		
		insert into master.dbo.sysconfigures 
		values(@cfguserdefinedcache, @size, "User Defined Cache", 
		       (@new_cache_type | @activependingtype | @new_repl | @c_part_stat), 
		       @cachename, @cfguserdefinedcache, @config_sz_str, 0,
		       @partition_number

				)



		/*
		** If there is already a global configuration and the
		** request is for instance specific configuration then
		** we need to copy global pool configuration rows and 
		** set the instnceid of rows to target instanceid.
		** Otherwise, we insert only default pool information.
		*/
		if (@oldglobalstat != -1)
			AND (@oldglobalstat & @deletedtype != @deletedtype)
		begin	-- {

			select	@row_count = count(*) 
			from 	master.dbo.sysconfigures
			where	parent = @cfguserdefinedcache
			  and	config != @cfguserdefinedcache
			  and	name = @cachename


			declare pool_info cursor for 
				select 	config, value, comment, name, parent, 
					value2, value3, value4
				from	master.dbo.sysconfigures
				where	parent = @cfguserdefinedcache
				  and	config != @cfguserdefinedcache
				  and	name = @cachename


			open pool_info

			while (@row_count > 0)
			begin
				fetch pool_info into @config, @value, @comment,
						     @name, @parent, @value2, 
						     @value3, @value4

				/* Insert pool information */
				insert into master.dbo.sysconfigures
				values(@config, @value, @comment, 
					(@new_cache_type | @activependingtype | @new_repl | @c_part_stat),
					@name, @parent, @value2, @value3, @value4

					)

				select @row_count = @row_count - 1
			end

			close pool_info
		end	-- }
		else
		begin	-- {
			/*
			** The newly-created cache must have at least a "pagesize"
			** buffer pool. Insert a row into sysconfigures to reflect
			** this. Like the cache, the pool is initially set to
			** the "pending/active" state. 
			*/
			select @pool_config_id 
				= @cfgbuffer2kpoolgrp 
					+ (log10(@@maxpagesize /@@pagesize)/log10(2))
			select @msg = rtrim(convert(varchar(255), @@maxpagesize/1024)) +
					"K I/O Buffer Pool"
			insert into master.dbo.sysconfigures
			values(@pool_config_id, 0, @msg,
				(@new_cache_type | @activependingtype | @new_repl | @c_part_stat),
				@cachename, @cfguserdefinedcache, NULL, 0, (-1) 

				)

			
		end	-- }
	end	-- }
	else if @operation = @cfgcachedelete
	begin	-- {
		/*
		** Retain the existing cache type(7=default+mixed+logonly) and
		** replacement policy(768=strict+relaxed) and partition state
		** (1024=cmpartspecified) and set the Pend/Del(128) bit.
		*/
		update	master.dbo.sysconfigures 
		set	status = ((status & (7 | 768 | 1024)) | @deletependingtype)
		where	parent = @cfguserdefinedcache
		  and	name = @cachename

	end	-- }
	else if @operation = @cfgcacheupdate
	begin	-- {
		/*
		**  If @dflt_ctype is set to 1, we dont update the
		**  existing cache type with the default mixed type.
		*/
		if @new_cache_type != 0 and @dflt_ctype != 1
		begin	-- {
			/*
			** If we're making the cache a log only cache then
			** verify that there are no non-log objects bound to
			** the cache.
			*/
			if (@new_cache_type & @logonlytype = @logonlytype)
			begin
				select @retstat = config_admin(@cmdbindingcheck, 1,
							0, 0, 

							NULL,

							@cachename)
				if @retstat = 0
				begin
					raiserror 18140
					rollback tran cacheconfig
					return 1
				end
			end

			select  @old_stat = status
			from	master.dbo.sysconfigures
			where	parent = @cfguserdefinedcache
			  and	config = @cfguserdefinedcache
			  and 	name = @cachename

			
			/*
			** If the cache type is changing then we need to
			** turn off the old cache type bits in the status
			** word before or-ing the new value in.
			*/
			if (@old_stat & @new_cache_type != @new_cache_type)
			begin
				if ((@old_stat & @inmemtype = @inmemtype) or
				    (@new_cache_type = @inmemtype))
				begin
					/*
					** Disallow changing the cache type
					** between 'inmemory_storage' and 
					** 'logonly | mixed'.
					*/
					raiserror 19977, @cachename, 'inmemory_storage'
					rollback tran cacheconfig
					return 1
				end

				select @old_stat = @old_stat & ~6
				select @old_stat = @old_stat & ~@deletedtype
				select @old_stat = @old_stat | @new_cache_type 

				update	master.dbo.sysconfigures 
				set	status = @old_stat
				where	parent = @cfguserdefinedcache
				  and	name = @cachename

			end
			
		end	-- }
		else
		begin	-- {
			/*
			** Make sure @new_cache_type has the existing cache type
			** so we don't overwrite it with the default value when
			** we we call config_admin() down below.
			*/
			if (@oldlocalstat & @defaulttype) = @defaulttype
			begin
				select @new_cache_type = @defaulttype
			end
			else if (@oldlocalstat & @mixedtype) = @mixedtype
			begin
				select @new_cache_type = @mixedtype
			end
			else if (@oldlocalstat & @logonlytype) = @logonlytype
			begin
				select @new_cache_type = @logonlytype
			end
		end	-- }

		/*
		** If @dflt_crepl is set to 1, we dont update the existing
		** cache replacement with the default replacement policy.
			end 
			else if (@old_stat & @inmemtype) = @inmemtype
			begin
				select @new_cache_type = @inmemtype
		*/
		if @new_repl != 0 and @dflt_crepl != 1
		begin	-- {
		
			select	@old_stat = status
			from	master.dbo.sysconfigures
			where	parent = @cfguserdefinedcache
			  and	config = @cfguserdefinedcache
			  and 	name = @cachename



			/*
			** If the replacement policy is changing then we need to
			** turn off the old replacement policy
			** (768=strict+relaxed) bits in the status word before
			** or-ing the new value.
			*/
			if (@old_stat & @new_repl != @new_repl)
			begin
				if ((@old_stat & @nonereplace = @nonereplace) or
				    (@new_repl = @nonereplace))
				begin
					/*
					** Disallow changing cache replacement
					** policy between 'none' and 'strict|
					** relaxed'.
					*/
					raiserror 19978, 'none', 'strict|relaxed' 
					rollback tran cacheconfig
					return 1
				end

				select @old_stat = @old_stat & ~768
				select @old_stat = @old_stat | @new_repl 
				
				update	master.dbo.sysconfigures 
				set	status = @old_stat
				where	parent = @cfguserdefinedcache
				  and	name = @cachename

			end
		end	-- }

		/*
		** If @dflt_cpart is set to 1, this is the case where cache
		** partition is not specified in sp_cacheconfig, then we do not
		** update the existing cache partition number.
		*/
		if @dflt_cpart != 1
		begin
			select	@old_stat = status
			from	master.dbo.sysconfigures
			where	parent = @cfguserdefinedcache
			  and	config = @cfguserdefinedcache
			  and 	name = @cachename

			
			select @old_stat = @old_stat & ~@cmpartspecified
			select @old_stat = @old_stat | @c_part_stat
			
			update	master.dbo.sysconfigures 
			set	value4 = @partition_number, status = @old_stat
			where	config = @cfguserdefinedcache
			  and	parent = @cfguserdefinedcache
			  and	name = @cachename

		end

		if @config_sz_str is not NULL
		begin	-- {
			update	master.dbo.sysconfigures
			set	value2 = @config_sz_str, value = @size
			where	config = @cfguserdefinedcache
			  and	parent = @cfguserdefinedcache
			  and	name = @cachename


			/*
			** Retain the current cache type and set status to
			** Active or Pend/Act if the current status is Pend/Del.
			*/
			select	@old_stat = status
			from	master.dbo.sysconfigures
			where	parent = @cfguserdefinedcache
			  and	config = @cfguserdefinedcache
			  and 	name = @cachename


			if (@old_stat & @deletependingtype = @deletependingtype)
			begin	-- {
				if exists (select value
					   from   master.dbo.syscurconfigs
					   where  config = @cfguserdefinedcache
					     and  comment = @cachename

						)
				begin
					/* 
					** The cache is active prior to 
					** being deleted. 
					*/
					select @old_stat = @activetype
				end
				else
				begin
					/* 
					** The cache is Pend/Act prior to
					** being deleted.
					*/
					select @old_stat = @activependingtype
				end

				update	master.dbo.sysconfigures
				set	status = ((status & (7 | 768 | 1024)) 
							| @old_stat)
				where	parent = @cfguserdefinedcache
				  and	name = @cachename

			end	-- }
		end	-- }
	end	-- }
	
	select @retstat = config_admin(@operation, @cfguserdefinedcache, 
					@partition_number, @new_cache_type,

					NULL,

					@cachename)

	/* If the status is '1' then operation is successful. Otherwise rollback */
	if @retstat != 1
	begin
		rollback tran cacheconfig
		return 1
	end

	/* Operation is successfull. */
	/* 
	** The return values for successfull calls is in cachemgr.h
	** under the enum ONL_CACHE_RET_STATUS.
	*/

	if @operation = @cfgcacheinsert
	begin	-- {
		/*
		** The cache creation was successful so modify the status of the
		** cache & the default pool from "pending/active" to "active".
		*/
		update	master.dbo.sysconfigures
		set	status = (@new_cache_type | @activetype 
					| @new_repl | @c_part_stat)
		where	parent = @cfguserdefinedcache
		  and	name = @cachename

	end	-- }
	else if @operation = @cfgcachedelete
	begin	-- {

			delete from master.dbo.sysconfigures 
			where  parent = @cfguserdefinedcache
			  and  name = @cachename

	end	-- }

	/*
	**  If the type of this cache has changed then we need to make sure
	**  that if the new type is log only, there are no non-log objects
	**  bound to this cache.
	*/
	if (@oldlocalstat & @new_cache_type != @new_cache_type)
		and @operation != @cfgcacheinsert
		and @operation != @cfgcachedelete
	begin
		if (@new_cache_type & @logonlytype = @logonlytype)
		begin
			select @retstat =  config_admin(@cmdbindingcheck, 1, 0,
						0,

						NULL,

						@cachename)
			if @retstat = 0
			begin
				raiserror 18140
				rollback tran cacheconfig
				return 1
			end
		end
	end

	commit tran cacheconfig

	return 0 
end	-- }
go
exec sp_procxmode 'sp_cacheconfig', 'anymode'
go
grant execute on sp_cacheconfig to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_bindcache')
begin
	drop procedure sp_bindcache
end
go
print "Installing sp_bindcache"
go

/* Stored procedure for binding entites to named caches.  Entity must
** be the name of a database, table or index.
**
** Databases can only be bound when using Master.
** The Master database cannot be bound to a named cache, but individual
** tables in Master can.
*/

/*
** Messages for "sp_bindcache"	18086
**
**  17260, "Can't run %1! from within a transaction."
**  18086, "Specified named cache does not exist."
**  18087, "You must be in Master to bind or unbind a database."
**  18089, "The Master database cannot be bound to or unbound from
**	    a named cache."
**  18092, "Only logs may be bound to this cache."
**  18098, "Individual tables in a temporary database cannot be bound to or 
**          unbound from named caches.  However, all of a temporary database
**	    may be bound or unbound."
**  18156, "Usage: sp_unbindcache dbname [, [ownername.]tablename
**	    [, indexname | `text only']]"
**  18170, "Usage: sp_bindcache cachename, dbname [, [ownername.]tablename
**	    [, indexname | `text only']]"
**  18175, "Specified named cache does not exist. The SQL Server must be
**	    rebooted to activate the named cahce."
**  18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
**  19120, "Cache binding changes for 'tempdb' are not dynamic. Adaptive Server
**	    must be restarted for the change to take effect."
**  19686, "Warning! Binding a local temporary database to a local named cache
**	    that doesn't exist on the instance that owns the temporary 
**	    database."
**  19776, "Cache binding changes for local system temporary databases are not 
**	    dynamic. The owner instance must be rebooted for the change to take
**	    effect."
**  19777, "Cache binding change for local temporary database '%1!' failed due 
**	    to owner instance '%2!' status change. Please try again after the 
**	    owner instance change completes."
**  19828, "Cache binding failed for database '%1!'"
**  19974, "Individual object or database cannot be bound to or unbound from
**	   cache, '%1!', which is an in-memory storage cache."
**  19979, "Cannot run '%1!' for in-memory database '%2!'."
**  19991, "You cannot bind an in-memory database, or individual objects in an 
**	   in-memory database, to cache '%1!', which is a regular named cache. 
*/
create procedure sp_bindcache
@cachename	varchar(255),
@dbname		varchar(30),
@tablename	varchar(512) = NULL,
@indexname	varchar(255)  = NULL
as

declare @dbid		int
declare @ownerid	int
declare @objid		int
declare @indid		int
declare @entitytype	char(1)
declare @aiobject	int
declare @status		int
declare @separator	int
declare @mask		int
declare @cachecount	int
declare @class		smallint
declare @attribute	smallint
declare @action		smallint
declare @objtype	char(1)
declare @sysattrtype	char(2)
declare @tempdb_mask 	int	/* all tempdb status bits */
declare @local_tempdb_mask int	/* all local tempdb status bits */
declare @localsystdbbit	int	/* local system tempdb status3 bit */
declare @tdb_instanceid	int	/* local tempdb instanceid */
declare @tdb_instancename	varchar(255)
declare @sqlbuf		varchar(255)
declare @islocalsystdb	int	/* It is a local system tempdb */
declare @is_others_ltdb	int	/* It is a local tempdb on remote instance */
declare @dbstat		int
declare @dbstat3	int
declare @msg		varchar(1024)
declare @is_inmemcache	int

/*
**  Don't allow this in a transaction because we can't undo what
**  the bind_cache() builtin has done.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_bindcache"
	return (1)
end
else
begin
	set transaction isolation level 1
	set chained off
end

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sa_role") = 0)
	return (1)

/* Make sure the target cache exists. */
if (@cachename is not NULL)
begin
	select @status=0
	select @is_inmemcache = 0

	/* Don't get deleted entries. We may have valid entry */

	select @status = status from master.dbo.sysconfigures
		where name=@cachename and parent=19 and config=19
		and status != 16384
	/* if the named cache does not exist */
	if (@status = 0)
	begin
		/*  18086, "Specified named cache does not exist." */
		raiserror 18086
		return 1
	end
	/* if the named cache is not active */
	if (@status & 32) != 32
	begin
		/*  
		** 18175, "Specified named cache does not exist. The SQL Server must be
		** rebooted to activate the named cache."
		*/
		raiserror 18175
		return 1
	end

	/* if the named cache is an in-memory storage cache */
	if (@status & 65536 = 65536)
	begin
		select @is_inmemcache = 1
		raiserror 19974, @cachename
		return 1
	end
end

if @dbname is NULL
begin
	/*
	** Dbname is required for both sp_bindcache and sp_unbindcache.
	*/
	if @cachename is NULL
	begin
		/*
		** Raise the sp_unbindcache usage message.
		*/
		raiserror 18156
		return 1
	end
	else
	begin
		/*
		** Raise the sp_bindcache usage message.
		*/
		raiserror 18170
		return 1
	end
end

/*
** Retrieve the id's required to identify the object the cache is being
** bound to.
*/
select @status		= 0
select @dbid		= NULL
select @ownerid		= NULL
select @objid		= NULL
select @indid		= NULL
select @entitytype	= NULL
exec @status = sp_aux_parse_entity @dbname, @tablename, @indexname,
				   @dbid output, @ownerid output,
				   @objid output, @indid output,
				   @entitytype output

if @status = 2
begin
	/*
	** A syntax error was encountered.  Raise the appropriate usage
	** message.
	*/
	if @cachename is NULL
	begin
		/*
		** Raise the sp_unbindcache usage message.
		*/
		raiserror 18156
		return 1
	end
	else
	begin
		/*
		** Raise the sp_bindcache usage message.
		*/
		raiserror 18170
		return 1
	end
end
else if @status != 0
begin
	return @status
end

/* Do not allow sp_bindcache/sp_unbindcache to be run on an archive database. */
if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid
			and   (status3 & 4194304) = 4194304)
begin
	/* Cannot run '%1!' on an archive database." */
	if @cachename = NULL
		raiserror 19424, "sp_unbindcache"
	else
		raiserror 19424, "sp_bindcache"
	return (1)
end

/* Do not allow sp_unbindcache to be run on an in-memory database. */
if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid
			and (status4 & 4096 = 4096))
begin
	if @cachename = NULL
	begin
		raiserror 19979, "sp_unbindcache", @dbname
		return (1)
	end
	else if @is_inmemcache = 0 
	begin
		/* Inmemory database or any object in inmemory database
		** cannot be bound to normal named cache.
		*/
		raiserror 19991, @cachename
		return (1)
	end
end

select @is_others_ltdb = 0
select @islocalsystdb = 0

select @dbstat = status, @dbstat3 = status3

	from master.dbo.sysdatabases
	where dbid = @dbid

/*
** If we are [un]binding a database...
*/
if @entitytype = 'D'
begin
	/* 
	** Make sure we are currently in the master database.
	** If not display an error message and exit.
	*/
	if db_id() != 1
	begin
		raiserror 18087
		return 1
	end
	/* 
	** If the cache type is "logonly", make sure we are binding only
	** syslogs to it.  Binding a database to a "logonly" cache is illegal.
	*/
	select @status=0 
	select @status = status
		from master.dbo.sysconfigures
		where name=@cachename and parent=19 and config=19
	select @mask = @status & 4
	if @mask > 0
	begin
		/*  
		**	18092, "Only logs may be bound to this cache."
		*/
		raiserror 18092
		return 1
	end



	/* Master itself cannot be bound */
	if @dbid = 1
	begin
		raiserror 18089
		return 1
	end

	select @aiobject = @dbid
end
else
begin
	select @tempdb_mask =  number
		from master.dbo.spt_values
		where   type = "D3" and name = "TEMPDB STATUS MASK"

	/* Individual tables in temporary databases cannot be bound. */
	if ((@dbid = 2) OR (@dbstat3 & @tempdb_mask) != 0)
	begin
		raiserror 18098
		return 1
	end

	select @aiobject = @objid

	/* if the log-only bit is set, make sure we're binding the log. */
	select @status=0
	select @status = status from master.dbo.sysconfigures
		where name=@cachename and parent=19 and config=19
	select @mask = @status & 4
	if @mask > 0
	begin
		if (@objid != 8)
		begin
			raiserror 18092
			return 1
		end
	end
end

/*
** Map entity type to attribute type.  Note that the attribute manager
** needs a two-byte string...
*/
select @sysattrtype = @entitytype + " "

/* Figure out if we need to insert, update or delete from sysattributes. */
begin tran bindcache
if @cachename is not NULL
BEGIN
	if exists(select * from sysattributes where
		class = 3 AND
		attribute = 0 AND
		object_type = @sysattrtype AND
		object = @aiobject AND
		object_info1 = @indid)
	BEGIN
		select @action = 2 /* ATTR_CHANGE */
	END
	ELSE
	BEGIN
		select @action = 1 /* ATTR_ADD */
	END
END
ELSE
BEGIN
	select @action = 3 /* ATTR_DROP */
END

/*
**  Call the notification routine before modifying sysattributes.  This
**  is necessary because cm_bind_cache() needs to look up the OLD binding
**  for the entity.
*/
select @status = 0
select @class = 3
select @attribute = 0

/*
** For system 'tempdb' all (un)bindings are delayed untill the
** next reboot. The changes on the systemtables are done anyway.
**
** In SDC, same goes with local system tempdb. However,
** This restriction on dynamic binding doesn't apply to the global
** system 'tempdb' since it is not used for worktable or #temp tables
** unless in configuration mode.
*/
if @@clustermode = "shared disk cluster"
begin
	select @localsystdbbit = number
		from master.dbo.spt_values
		where type = "D3" and name = "local system temp db"
	if ((@dbstat3 & @localsystdbbit) = @localsystdbbit)
	begin
		select @islocalsystdb = 1
	end
end

if ((@dbid != 2 or (@@clustermode = "shared disk cluster" and 
		    	sdc_intempdbconfig() = 0)) 
    and @islocalsystdb = 0 
    and @is_others_ltdb = 0)
BEGIN
	select @status = attrib_notify(@class, @attribute, @sysattrtype, @aiobject,
			@indid, NULL, NULL, NULL, NULL, @cachename, NULL, 
			NULL, NULL, @action)

	if @status = 1
	BEGIN
		rollback tran bindcache
		raiserror 19828, @dbname
		return @status
	END
END

if @action = 1
BEGIN
	insert into sysattributes 
		(class, attribute, object_type, object, 
		 object_info1, char_value, int_value)
		VALUES
		(3,	/* BUFFER MANAGER */
		 0,	/* CACHE BINDING */
		 @sysattrtype,
		 @aiobject,
		 @indid,
		 @cachename,
		 1	/* Binding is valid */
		)
END

if @action = 2
BEGIN
	update sysattributes
		set 	char_value = @cachename,
			int_value = 1	/* binding is valid */
		where	class = 3 AND
			attribute = 0 AND
			object_type = @sysattrtype AND
			object = @aiobject AND
			object_info1 = @indid
END

if @action = 3
BEGIN
	delete from sysattributes
			where	class = 3 AND
				attribute = 0 AND
				object_type = @sysattrtype AND
				object = @aiobject AND
				object_info1 = @indid
END

/*
** If we come here for bindings of local tempdb owned by remote instance,
** we have assumed that the local tempdb is not recovered and we can
** safely update master..sysattributes only. Verify that the local tempdb
** is still not recovered, otherwise, rollback the transaction.
*/ 
if (@@clustermode = "shared disk cluster" and @is_others_ltdb = 1)
begin
	select @dbstat = status
		from master.dbo.sysdatabases
		where dbid = @dbid
	if ((@dbstat & 64) = 0)
	begin
		/*
		** 19777, "Cache binding change for local tempdb '%1!' 
		** failed due to owning instance '%2!' status change. 
		** Please try again after the owning instance change
		** completes."
		*/
		raiserror 19777, @dbname, @tdb_instancename
		rollback tran bindcache
		return 1
	end
end
commit tran bindcache	

if (@dbid = 2 and (@@clustermode != "shared disk cluster" or
		   sdc_intempdbconfig() = 1))
BEGIN
	/*
	** 19120, "Cache binding changes for 'tempdb' are not dynamic.
	** Adaptive Server must be restarted for the change to take effect."
	**
	** This message should be printed as a warning/informational message
	** and not user error but it is not changed to avoid any impact to 
	** user applications.
	*/
	raiserror 19120
END

if (@islocalsystdb = 1)
begin
	/*
	** 19776, "Cache binding changes for local system temporary databases 
	** are not dynamic. The owner instance must be rebooted for the change 
	** to take effect."
	*/
	exec sp_getmessage 19776, @msg output
	print @msg
end

return @status

go
exec sp_procxmode 'sp_bindcache', 'anymode'
go
grant execute on sp_bindcache to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_do_poolconfig')
begin
	drop procedure sp_do_poolconfig
end
go
print "Installing sp_do_poolconfig"
go

/* This stored procedure is for configuring buffer pools. This is an internal
** stored procedure calle by either sp_poolconfig or from recovery process
** directly.
**
**	Messages for sp_do_poolconfig
**
** 17260, "Can't run %1 from within a transaction."
**
** 18076, "Could not set curwrite to object level. Set your maxwrite 
**	   label correctly."
**
** 18095, "The destination buffer pool size must be a minimum of %1!
**	   kilobytes."
**
** 18138, "A cache name must be supplied."
**
** 18135, "The specified named cache (%1) does not exist."
**
** 18141, "Syntax error encountered. Specification of the wash size must be 
**	   of the form 'wash = %d[PKMG]'
**
** 18142, "I/O size of the memory pool is expected as the third argument."
**
** 18143, "The source pool (%1k buffers, total size %2k) is not large enough 
**	   to satisfy the request to move %3k of memory.
**
** 18144, "Source pool (%1k) and destination pool (%2k) are the same pool.  
**	   The source and destination pools must be different."
**
** 18147, "Invalid buffer size of %1! encountered. Valid buffer sizes are 
**	   powers of two between %2! and %3! kilobytes inclusive."
**
** 18148, "The specified pool (%1!) does not exist in named cache '%2!'."
**
** 18558, "Unable to delete the '%1!' pool in cache '%2!'."
**
** 18559, "This pool has been marked unavailable. You can
**	   remove it completely by retrying sp_poolconfig when
**	   the cache is not in use or by restarting the Server."
** 
** 18560, "Unable to move '%1!' from the '%2!' pool to the '%3!' pool in
**	   cache '%4!'. Only '%5!' moved."
** 
** 18339, "The '%1!' pool has been marked as being unavailable since it is
**	   smaller than the minimum pool size of %2! kilobytes."
** 
** 18562, "You can size the pools correctly by retrying sp_poolconfig 
**	   when the cache is not in use or by restarting the Server."
** 
** 19111, "Cannot change the pool configurations in the '%1!' when the server is
**	   in recovery."
**
** 19595, "Instance '%1!' does not exist."
**
** 19973, "Configuring large I/O pools for in-memory storage cache '%1' is
**	  not allowed." 
*/

create procedure sp_do_poolconfig
@cachename 		varchar(255) = NULL,
@parm1			varchar(30) = NULL,
@parm2			varchar(40) = NULL,
@parm3			varchar(30) = NULL,
@is_in_recovery		varchar(30) = NULL,
@parm4			varchar(255) = NULL
as

declare @equal_sign_loc		int	/* for parsing parms */
declare @wash_or_apf_val_loc	int	/* for parsing parms */
declare @wash_or_apf_size	int	/* user supplied wash size or '
					** apf percent
					*/
declare @wash_delta_size	int	/* delta of the wash size */
declare	@src_buf_size		int	/* size of bufs in src pool */
declare @dest_buf_size		int	/* size of bufs in dest pool */
declare @config_num_src		int	/* config # for src pool */
declare @config_num_dest	int	/* config # for dest pool */
declare	@temp_size		int	/* temporary variable */
declare @requested_size		int	/* requested total size of dest pool */
declare @existing_pool_size	int	/* exisiting size of dest pool */
declare @curr_pool_size		int	/* current exisiting size of dest pool */
declare @stat			int	/* status of cache from sysconfigures */
declare @stat1			int	/* status of cache from sysconfigures */
declare @stat2			int	/* status of cache from sysconfigures */
declare @mem_to_move		int	/* amount of mem to move */
declare @inst_mem_to_move	int	/* amount of mem to move at an instance */
declare @mem_moved		int	/* Memory that should have been moved */
declare @src_pool_size		int	/* amount of mem in src pool */
declare @dest_pool_size		int	/* amount of mem in dest pool */
declare	@ret			int	/* return status from sp_aux_getsize */
declare	@result_size		int	/* resulting size of dest pool after 
					** config_admin call.
					*/
declare @delete_pool		int	/* 1 if src pool 2 if dest pool */
declare @temp_float		float	/* for temp float calculations */
declare @temp_value		int	/* for temp int calculations */
declare @temp_pool_size		int	/* for temp pool size value */
declare	@dest_buf_sz_str	varchar(30) /* size of bufs in dest pool */
declare	@src_buf_sz_str		varchar(30) /* size of bufs in src pool */
declare	@dest_pool_sz_str	varchar(30) /* total mem in dest pool */
declare @res_sz_str		varchar(30) /* str value of result size */
declare @req_sz_str		varchar(30) /* str value of requested size */
declare @temp_str		varchar(30) /* scratch pad */
declare @wash_or_apf_str	varchar(255) /* wash size or apf percentage */
declare @msg			varchar(255)
declare	@config_file_name	varchar(255)
declare @min_buf_size		int	
declare @max_buf_size		int
declare @rec_state		varchar(30)
declare @instanceid		int
declare @instancename		varchar(255)
declare @cur_instanceid		int
declare @cur_instancename	varchar(255)
declare @instance_count		int
declare @failure_count		int
declare @total_pool_size	int
declare @cache_size		int
declare @i                      int     /* iterator */

/* declare and init the config_admin() commands used in this sproc */
declare   @cmdbindingcheck      int
        , @cmdsetwashsize       int
        , @cmdpoolconfig        int
        , @cmdsetapfsize        int
        , @cmdupdateconfigfile  int

select    @cmdbindingcheck      = 9
        , @cmdsetwashsize       = 10
        , @cmdpoolconfig        = 11
        , @cmdsetapfsize        = 17
        , @cmdupdateconfigfile  = 32

/* declare and init the config options used in this sproc */
declare   @cfguserdefinedcache  int
        , @cfgbuffer2kpoolgrp   int
        , @cfgcfgfilename       int

select    @cfguserdefinedcache  = 19
        , @cfgbuffer2kpoolgrp   = 20
        , @cfgcfgfilename       = 114

select    @wash_or_apf_str 	= NULL

if @@trancount > 0
begin
	raiserror 17260, "sp_poolconfig"
	return 1
end
else
begin
	set chained off
end

set transaction isolation level 1

if @cachename is NULL
begin
	raiserror 18138
	return 1
end

/*
**  If the cache name is the only parameter that's supplied just pass it 
**  along to sp_cacheconfig and have it print out all of the configured pools
**  for the cache.
*/
if (@parm1 is NULL) and (@parm2 is NULL) and (@parm3 is NULL) 
begin
	exec sp_cacheconfig @cachename
	return 0
end
else if (patindex("instance %", @parm1) !=0) and (@parm2 is NULL) and (@parm3 is NULL)
begin
        exec sp_cacheconfig @cachename, @parm1
        return 0
end

/* 
** check if user has sa role, proc_role will also do auditing & print error
** message, if required. 
*/
if (proc_role("sa_role") = 0)
	return 1

/*
** If we are in the middle of boot time recovery, and not called by recovery,
** changing configuration in default data cache is not allowed.
*/
select @rec_state = @@recovery_state
if ((@rec_state not like "NOT_IN_RECOVERY%") 
	and (@is_in_recovery not in ("TRUE", "true")))
begin
	if (patindex("%default data cache%", @cachename) != 0) 
	begin
		raiserror 19111, @cachename
		return 1
	end
end

select @instancename = NULL
select @instanceid = NULL



select @dest_pool_sz_str = @parm1
select @min_buf_size = @@maxpagesize /1024
select @max_buf_size = @min_buf_size * 8

/*
**  Parm2 may be of the form "wash = %d" or %d [K | M | G]  
**  Or
**  Parm2 may be of the form "local async prefetch limit=%d" 
*/
if (patindex("%wash%", @parm2) != 0) or (patindex("%local async%", @parm2) != 0)
begin	-- {
	/*
	**  Translate destination buffer pool into units of k
	*/
	exec  @ret = sp_aux_getsize @dest_pool_sz_str, @dest_buf_size output

	if @ret = 0
	begin
		return 1
	end

	select @equal_sign_loc = 0
	select @equal_sign_loc = patindex("%=%", @parm2)
	/*
	**  proper syntax for specifying the wash is "wash = %d". Make sure 
	**  the string follows this syntax.
	*/
	if @equal_sign_loc = 0
	begin
		raiserror 18141
		return 1
	end

	select @wash_or_apf_val_loc = patindex("%[0-9]%", @parm2)
	select @wash_or_apf_str = convert(varchar(255), substring(@parm2, 
				 	@wash_or_apf_val_loc, 
				 	char_length(@parm2) - 
						@wash_or_apf_val_loc + 1))

	/* sp_aux_get_size will take string of the form "100 [kmpg]" */
	exec @ret = sp_aux_getsize @wash_or_apf_str, @wash_or_apf_size output
	if @ret = 0
	begin
		return 1
	end

	/*
	** First sanity check the destination buffer size to make sure it's 
	** within the legal range i.e., powers of 2 between a logical page 
	** to 8 logical pages.
	*/
	if (@dest_buf_size < @min_buf_size) or (@dest_buf_size > @max_buf_size)
	begin
		raiserror 18147, @dest_pool_sz_str, @min_buf_size, @max_buf_size
		return 1
	end

	select @temp_size = 2
	while @temp_size < @dest_buf_size
		select @temp_size = @temp_size * 2
	if @temp_size != @dest_buf_size
	begin
		raiserror 18147, @dest_pool_sz_str, @min_buf_size, @max_buf_size
		return 1
	end
	
	/*
	**  Config numbers in sysconfigures start at 20 for the 2k buffer pool,
	**  21 for the 4k buffer pool, 22 for the 8k buffer pool and so on.
	**  Basically if we add log base 2 of the destination buffer size to
	**  the base of 20 and subtract one we should get the correct config 
	**  number to index into sysconfigures.
	*/
	select @config_num_dest 
		= @cfgbuffer2kpoolgrp 
			+ (log10(@dest_buf_size*1024/@@pagesize)/log10(2))

	/* Parm3 may contain instance specific information */
	if (charindex("instance ", @parm3) = 1)
	begin
		select @instancename = substring(@parm3, 10,
					char_length(@parm3) - 9)
		select @instanceid = instance_id(@instancename)

		if @instanceid is NULL
		begin
			raiserror 19595, @instancename
			return 1
		end
	end

	/* Check to see if the cache exists */
	select 	@stat = -1
	select 	@stat = status 
	from 	master.dbo.sysconfigures 
	where 	name = @cachename 
	  and	parent = @cfguserdefinedcache 
	  and 	config = @cfguserdefinedcache
	  and 	status & 128 != 128


	if @stat = -1
	begin
		raiserror 18135, @cachename
		return 1
	end

	/* Disallow configuring large I/O pool for in-memory storage cache. */
	if (@stat & 65536 = 65536)
	begin	
		raiserror 19973, @cachename
		return 1
	end



	begin
		select @instance_count = 1
	end

	select @failure_count = 0



	select @i = @instance_count
	while (@i > 0)
	begin	-- {


		select 	@temp_size = memory_used 
		from	master.dbo.syscurconfigs
		where 	config = @config_num_dest 
		  and 	comment = @cachename


		/*
		** Check if there is an instance specific config for instance
		** @cur_instanceid
		*/
		select 	@stat = -1
		select 	@stat = status 
		from 	master.dbo.sysconfigures 
		where 	name = @cachename 
		  and 	parent = @cfguserdefinedcache
		  and 	config = @cfguserdefinedcache


		/* 
		** Skip the instance if there exists an instance specific
		** configuration and the requested operation is global
		*/
		if (@instanceid is NULL) and (@stat != 1) and (@@instanceid != NULL)
		begin
			select @i = @i - 1
			continue
		end

		/* If the pool doesn't exist it's an error. */
		if @temp_size = 0
		begin

			raiserror 18148, @dest_pool_sz_str, @cachename
			return 1
		end
		select @i = @i - 1
	end	-- }



	/* if parm2 is wash related then do the following */
	if patindex("%wash%", @parm2) != 0
	begin	-- {
		if @@clustermode != 'shared disk cluster'
		begin
			select @wash_delta_size = @wash_or_apf_size - @temp_size
		end

		/*
		** In syscurconfigs, we obtain the wash size in Kilobytes.
		** However, we store the wash size, in sysconfigures, in
		** kilobytes/Buffer pool size.
		** Note: we are reusing the variable 'temp_size' here.
		*/
		select @temp_size = @wash_or_apf_size / @dest_buf_size

		/*
		** If due to round off error, we get a wash size of 0,
		** even if it was not specified as the input, we will pass a 
		** non-zero invalid value to the update. This will be 
		** caught by the config manager and this update will 
		** rolled back later.This can happen, if the wash size
		** specified is not zero, but gets rounded of to 
		** zero. The wash size 0 is a special value.
		*/
		if @temp_size = 0 and @wash_or_apf_size != 0
			select @temp_size = -1

		begin tran set_wash

		update 	master.dbo.sysconfigures
	 	set 	value3 = @temp_size
		where	config = @config_num_dest 
		  and	name = @cachename

	
		/*
		** In SDC, we consider named cache creation as success even if
		** some instance allocated memory partially only. Due to this
		** pools may have different run sizes and hence wash sizes.
		** Hence, we can't determine a unique value to change at stored
		** procedure level. Hence, we pass total wash value for SDC.
		**
		** For SMP we need to pass 'delta' value of wash size.
		*/

			select @stat = config_admin(@cmdsetwashsize, 
						@dest_buf_size, 
						@wash_delta_size, 0, 
						@instancename, @cachename)

		if @stat = 0
		begin
			rollback tran set_wash
			return 1
		end

		commit tran set_wash
		return 0
	end	-- }
	
	/* if parm2 is apf related do the following */
	if patindex("%local async%", @parm2) != 0
	begin
		begin tran set_apf

		update	master.dbo.sysconfigures
		set 	value4 = @wash_or_apf_size 
		where	config = @config_num_dest
		  and	name = @cachename
		
		select @stat = config_admin(@cmdsetapfsize, @dest_buf_size,
					@wash_or_apf_size, 0, @instancename,
					@cachename)

		if @stat = 0
		begin
			rollback tran set_apf
			return 1
		end

		commit tran set_apf
		return 0
	end
end	-- }

/*
**  If we make it here then the command must be of the form:
**		sp_poolconfig "foo", "100M", "16k", "instance <instancename>"
**  We'll check against that syntax here.
*/
if @parm2 is NULL
begin
	raiserror 18142
	return 1
end

select @dest_buf_sz_str = @parm2

if @parm3 is NULL
begin
	select @src_buf_sz_str = "1p"
	select @instancename = NULL
	select @instanceid = NULL
end
else
begin	-- {
	/* @parm3 may contain instance specific information. */
	if (charindex("instance ", @parm3) = 1)
	begin
		select @instancename = substring(@parm3, 10,
					char_length(@parm3) - 9)
		select @instanceid = instance_id(@instancename)

		if @instanceid is NULL
		begin
			raiserror 19595, @instancename
			return 1
		end

		select @src_buf_sz_str = "1p"
	end
	else
	begin
		if (charindex("instance ", @parm4) = 1)
		begin
			select @instancename = substring(@parm4, 10,
					char_length(@parm4) - 9)
			select @instanceid = instance_id(@instancename)

			if @instanceid is NULL
			begin
				raiserror 19595, @instancename
				return 1
			end
		end
		else
		begin
			select @instancename = NULL
			select @instanceid = NULL
		end

		select @src_buf_sz_str = @parm3
	end
end	-- }

/* Check to see if the cache exists. */
select	@stat = -1
select	@stat = status 
from	master.dbo.sysconfigures 
where	name = @cachename
  and	parent = @cfguserdefinedcache 
  and	config = @cfguserdefinedcache
  and	status & 128 != 128


if @stat = -1
begin
	raiserror 18135, @cachename
	return 1
end

/* Disallow configuring large I/O pool for in-memory storage cache. */
if (@stat & 65536 = 65536)
begin 
	raiserror 19973, @cachename 
	return 1 
end

/* Convert the destination pool size to units of kilobytes.*/
exec  @ret = sp_aux_getsize @dest_pool_sz_str, @requested_size output
if @ret = 0
begin			
	return 1 
end

/*
**  First sanity check the destination pool size to make sure
**  it is at least 256 * pagesize big.
*/
if (@requested_size != 0 and  @requested_size < @@min_poolsize)
begin
	raiserror 18095, @@min_poolsize
	return 1
end

/*
**  Translate the size in K of the destination and src pools to a 
**  config value that we can use to look up the pool in sysconfigures.
*/
exec  @ret = sp_aux_getsize @dest_buf_sz_str, @dest_buf_size output
if @ret = 0
begin
	return 1
end

exec @ret = sp_aux_getsize @src_buf_sz_str, @src_buf_size output
if @ret = 0
begin
	return 1
end

/* The source and destination pools cannot be the same.*/
if @dest_buf_size = @src_buf_size
begin
	raiserror 18144, @src_buf_sz_str, @dest_buf_sz_str
	return 1
end

/*
**  Sanity check the destination and source buffer sizes to make sure it's 
**  within the legal range (i.e. powers of 2 between a logical page and 
**  8 logical pages inclusive.
*/
if (@dest_buf_size < @min_buf_size or @dest_buf_size > @max_buf_size)
begin
	raiserror 18147, @dest_buf_sz_str, @min_buf_size, @max_buf_size
	return 1
end

if (@src_buf_size < @min_buf_size or @src_buf_size > @max_buf_size)
begin
	raiserror 18147, @src_buf_sz_str, @min_buf_size, @max_buf_size
	return 1
end

select @temp_size = 2
while @temp_size < @dest_buf_size
	select @temp_size = @temp_size * 2
if @temp_size != @dest_buf_size
begin
	raiserror 18147, @dest_buf_sz_str, @min_buf_size, @max_buf_size
	return 1
end

select @temp_size = 2
while @temp_size < @src_buf_size
	select @temp_size = @temp_size * 2
if @temp_size != @src_buf_size
begin
	raiserror 18147, @src_buf_sz_str, @min_buf_size, @max_buf_size
	return 1
end

/*
**  Translate buffer sizes into config numbers to index into sysconfigures
**  and syscurconfigs with.
*/
select @config_num_src 
	= @cfgbuffer2kpoolgrp + (log10(@src_buf_size*1024/@@pagesize)/log10(2))
select @config_num_dest 
	= @cfgbuffer2kpoolgrp + (log10(@dest_buf_size*1024/@@pagesize)/log10(2))

/* Get the list of instances where the operations needs to be run. */




/*
**  Find out how much memory is already in the destination pool.  It could
**  turn out that this request is for making the pool smaller.  In that case
**  turn around the arguments (i.e. destination pool becomes source and source
**  pool becomes destination) and give the extra memory to the source
**  pool. We need to consider the config value for configuring the pools as
**  different instances can different run values.
*/
select 	@delete_pool = 0
select 	@existing_pool_size = 0
select	@existing_pool_size = value 
from	master.dbo.sysconfigures 
where	name = @cachename
  and	config = @config_num_dest


select @mem_to_move = @requested_size - @existing_pool_size

/*
**  If there is nothing to move just return. No need to work 
**  without a good reason.
*/
if @mem_to_move = 0
begin
	return 0
end

begin tran pool_config

/*
**  If the memory to move is positive, we're moving memory from the source
**  pool (parm3) to the destination pool (parm2).  If it is negative then
**  we're moving memory from the destination pool (parm2) to the source
**  pool (parm3). Negative memory indicates that we're making a pool smaller.
*/
if @mem_to_move > 0
begin	-- {
	/*
	**  Check to see if the source pool has enough memory in it to
	**  satisfy the request.
	*/
	select	@src_pool_size = 0
	select	@src_pool_size = value 
	from	master.dbo.sysconfigures
	where	config = @config_num_src
	  and	name = @cachename


	/*
	** If @src_pool_size = 0 means it has default pool size.
	** We need to calculate the config size this pool by
	** reading other pool information and cache size
	*/
	if  @src_pool_size = 0 
	begin
		select	@total_pool_size = sum(value) 
		from	master.dbo.sysconfigures
		where	parent = @cfguserdefinedcache
		  and	name = @cachename

		  and	config != @cfguserdefinedcache

		select  @cache_size = value
		from	master.dbo.sysconfigures
		where	parent = @cfguserdefinedcache 
		  and	name = @cachename

		  and	config = @cfguserdefinedcache
	
		if @cache_size = 0
		begin
			select	@cache_size = value
			from	master.dbo.syscurconfigs
			where	config = @cfguserdefinedcache
			  and	comment = @cachename
		end

		select @src_pool_size = @cache_size - @total_pool_size
	end
	
	select @temp_size = @src_pool_size - @mem_to_move
	if (@temp_size != 0 and @temp_size < (256 * @@maxpagesize / 1024))
	begin
		/* Use wash_or_apf_str to covert mem_to_move to string. */
		select @wash_or_apf_str 
			= rtrim(convert(varchar(20), @mem_to_move)) + "Kb"
		raiserror 18143, @src_buf_sz_str, @src_pool_size,
			    @wash_or_apf_str 

		/*
		** We are not using a rollback tran here as it will
		** complain that their is nothing to rollback. The
		** reason being we have not done any work in this
		** transaction so far.
		*/
		commit tran poolconfig
		return 1
	end
	
	if exists (select * 
		   from master.dbo.sysconfigures 
		   where name = @cachename 
		     and config = @config_num_dest

			)
	begin
		/*
		** @temp_str contains the string equivalent of @requested_size
		** in @dest_pool_sz_str format.
		*/
		exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output,
				@requested_size, @temp_str output 
		
		update	master.dbo.sysconfigures 
		set 	value = @requested_size,
		    	value2 = @temp_str
		where 	config = @config_num_dest
		  and	name = @cachename 

	end
	else
 	begin
		select	@stat = status 
		from	master.dbo.sysconfigures
		where	name = @cachename 
		  and	config = @cfguserdefinedcache


		select @msg = rtrim(convert(varchar(255), @dest_buf_size)) 
				+ "K I/O Buffer Pool"

		exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output,
			@requested_size, @temp_str output 

		/*
		** Note the last 2 values for the insert below is '0'and (-1). 
		** This corresponds to the wash size and default apf percentage
		** of the newly created buffer pool. 
		** Newly created pools get a wash size of zero which 
		** corresponds to default wash size.
		*/
		insert into master.dbo.sysconfigures 
		values (@config_num_dest, @requested_size, @msg, @stat,
			@cachename, @cfguserdefinedcache, @temp_str, 0, (-1) 

			)
	end
	
	if @temp_size = 0
	begin
		/* Flag that we should delete the source buffer pool later. */
		select @delete_pool = 1
	end
		
	/* 
	** Update the source pool size after transfer.
	** If the updated value would become negative then
	** set it to zero.  @temp_str contains the string equivalent 
	** of the value field in @src_pool_sz_str format.
	*/
	select @temp_size = value - @mem_to_move 
	from master.dbo.sysconfigures
	where   config = @config_num_src
	  and 	name = @cachename


	if @temp_size < 0
	begin
		exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output,
				0, @temp_str output 
		update	master.dbo.sysconfigures 
		set	value = 0,
			value2 = @temp_str
		where	config = @config_num_src
		  and	name = @cachename

	end
	else
	begin
		exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output,
				@temp_size, @temp_str output 
		update	master.dbo.sysconfigures 
		set 	value = @temp_size,
			value2 = @temp_str	
		where	config = @config_num_src
		  and	name = @cachename

	end
end	-- }
else
begin 	-- {
	/*
	**  We're actually removing memory from the destination pool since
	**  @mem_to_move is negative.  If we've deleted this pool then delete
	**  the entry from sysconfigures.  Otherwise just subtract (by adding
	**  -@mem_to_move from the value already in sysconfigures).
	*/
	/* Check to see whether we have enough space in the dest pool */
	select	@dest_pool_size = 0
	select	@dest_pool_size = value 
	from	master.dbo.sysconfigures
	where	config = @config_num_dest
	  and	name = @cachename


	select @temp_size = @dest_pool_size + @mem_to_move
	if (@temp_size != 0 and @temp_size < (256 * @@maxpagesize / 1024))
	begin
		/* Use wash_or_apf_str to covert mem_to_move to string.	*/
		select @wash_or_apf_str 
			= rtrim(convert(varchar(20), @mem_to_move)) + "Kb"
		raiserror 18143, @dest_buf_sz_str, @dest_pool_size,
			    @wash_or_apf_str 

		/*
		** We are not using a rollback tran here as it will
		** complain that their is nothing to rollback. The
		** reason being we have not done any work in this
		** transaction so far.
		*/
		commit tran poolconfig
		return 1
	end
	
	if exists (select * 
		   from   master.dbo.sysconfigures 
		   where  name = @cachename 
		     and config = @config_num_src 

			)
	begin 	-- {
		/*
		** @temp_str contains the string equivalent of value field 
		** in @src_pool_sz_str format.
		*/
		select 	@temp_value = value 
		from	master.dbo.sysconfigures
		where 	config = @config_num_src
		  and	name = @cachename

		
		/*
		** If we are updating the default pool and
		** the size of the default pool is zero then don't add
		** @mem_to_move to 'value'.
	 	*/
		if (@config_num_src != 
			(@cfgbuffer2kpoolgrp 
				+ (log10(@@maxpagesize/@@pagesize)/log10(2))))
		begin
			select @temp_value = @temp_value + abs(@mem_to_move)
		end
		else
		begin
			if (@temp_value != 0)
			begin
				select @temp_value = @temp_value + abs(@mem_to_move)
			end
		end

		exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output,
			@temp_value, @temp_str output 
		update	master.dbo.sysconfigures 
		set 	value = @temp_value,
			value2 = @temp_str
		where 	config = @config_num_src
		  and	name = @cachename

		
	end	-- }
	else
 	begin 	-- {
		select	@stat = status
		from	master.dbo.sysconfigures
		where	name = @cachename
		  and	config = @cfguserdefinedcache


		select @msg = rtrim(convert(varchar(255), @src_buf_size))
				+ "K I/O Buffer Pool"
		select @temp_value = abs(@mem_to_move)
		exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output,
				@temp_value, @temp_str output 
		/*
		** Note the last 2 values for the insert below is '0'and (-1). 
		** This corresponds to the wash size and default apf percentage
		** of the newly created buffer pool. 
		** Newly created pools get a wash size of zero which 
		** corresponds to default wash size.
		*/
		insert into master.dbo.sysconfigures
		values (@config_num_src, @temp_value, @msg, @stat, @cachename,
			@cfguserdefinedcache, @temp_str, 0, (-1)

			)
	end	-- }
	
	if @temp_size = 0
	begin
		/* 
		** Flag that we should delete the destination buffer pool 
		** later. 
		*/
		select @delete_pool = 2
	end

	/* 
	** Update the destination pool size after transfer.
	** @temp_str contains the string equivalent
	** of the value field @dest_pool_sz_str format.
	*/
	exec sp_aux_getsize @dest_pool_sz_str, @temp_pool_size output, 
			@requested_size, @temp_str output 
	update	master.dbo.sysconfigures 
	set 	value = @requested_size, 
		value2 = @temp_str 
	where 	config = @config_num_dest
	  and 	name = @cachename


end	-- }




	select @instance_count = 1



select @failure_count = 0



select @i = @instance_count
while (@i > 0)
begin	-- {



	/*
	** We need to calculate the amount of memory to be moved
	** separately for each instance and use it for poolconfig
	** The reason for this is, there is a possibility of having
	** different run values at different instances.
	*/

	select  @curr_pool_size = 0
	select  @curr_pool_size = value 
	from	master.dbo.syscurconfigs
	where	comment = @cachename
	  and	config = @config_num_dest

	select @inst_mem_to_move = @requested_size - @curr_pool_size

	/*
	** The amount of memory to be moved may be negative some instance which
	** means not enough memory
	*/
	if (@inst_mem_to_move = 0)
	begin
		select @i = @i - 1
		continue
	end


	 select @cur_instancename = NULL



	begin
		select @stat = config_admin(@cmdpoolconfig, @src_buf_size, 
					@inst_mem_to_move, @dest_buf_size,
					@cur_instancename, @cachename)
	end

	if @stat = 0
	begin
		select @failure_count = @failure_count + 1
	end

	select @i = @i - 1
end	-- }




/*
** We rollback the transanction only if the operation is failed
** at all nodes.
*/
if @failure_count = @instance_count
begin
	rollback tran pool_config
	return 1
end


/*
** We need to check the result size at each instance and check
** whether we satisfied the requirement at all nodes before we 
** delete a pool entry if needed.
*/
select	@result_size = value
from	master.dbo.sysconfigures
where	config = @config_num_dest
  and	name = @cachename


/*
** ASE cannot guarentee that all of the requested buffers can be
** moved from one pool to another. Determine if the correct number of 
** buffers were moved.
**
** When moving memory, ASE cannot move fractions of MASSes. Therefore
** the actual amount of memory moved may be rounded down to a multiple
** of the greater of the source and destination MASS size. Take this
** into account when determining if the request has been fulfilled.
** For example, if a request is made to move 28K from the 2K to the 8K
** pool, then the server will only attempt to move 24K, since half a
** MASS (the remaining 4K) has no meaning to the 8K pool.
**
** NOTE: This fact creates a dependency between the server's behaviour and
** the behaviour of sp_do_poolconfig, and care should be taken in future not
** to break this. These sorts of dependencies will continue to exist until
** such time as config_admin() is modified to return good status 
** information. The stored procedure needs to know whether the memory move
** succeeded or not, and should not be left to duplicate the server's 
** behaviour in order to work this out.
** 
** Calculate this rounded down value and save it in @mem_moved.
*/
if @src_buf_size > @dest_buf_size
begin
        select @temp_value = @mem_to_move / @src_buf_size
        select @mem_moved = @temp_value * @src_buf_size
end
else
begin
        select @temp_value = @mem_to_move / @dest_buf_size
        select @mem_moved = @temp_value * @dest_buf_size
end

/*
** If the requisite number of buffers were moved successfully between 
** pools, remove corresponding entries from sysconfigures if this was a 
** request to delete a pool.
*/
if @result_size = (@mem_moved + @existing_pool_size)
begin	-- {
	if @delete_pool = 1
	begin
		delete from master.dbo.sysconfigures
		where  config = @config_num_src
		  and  parent = @cfguserdefinedcache
		  and  name = @cachename


		select @stat = config_admin(@cmdbindingcheck, 5, 
					@src_buf_size*1024, 0, @instancename,
					@cachename)

		if @stat = 0
		begin
			select "Unbinding failed at source pool"
		end
	end
	if @delete_pool = 2
	begin
		delete from master.dbo.sysconfigures
		where  config = @config_num_dest
		  and  parent = @cfguserdefinedcache
		  and  name   = @cachename


		select @stat = config_admin(@cmdbindingcheck, 5, 
					@dest_buf_size*1024, 0, @instancename, 
					@cachename) 
		if @stat = 0
		begin
			select "Unbinding failed at destination pool"
		end
	end
end	-- }
else
begin	-- {
	/*
	** Unable to move the requested number of buffers. If this was an
	** attempt to delete a pool then generate a message indicating
	** the failure to fully do do. The pool will have been marked
	** as unavailable by the server in such cases.
	*/
	if (@delete_pool > 0)
	begin
		if (@delete_pool = 1)
		begin
			raiserror 18558, @src_buf_sz_str, @cachename
		end
		else
		begin
			raiserror 18558, @dest_buf_sz_str, @cachename
		end

		raiserror 18559
	end
	else
	begin	-- {
		/*
		** Unable to move the correct number of buffers, but there
		** was no attempt to delete either source or destination
		** pool.
		*/
		select @res_sz_str = 
			rtrim(convert(varchar(30), abs(@mem_moved)))
		select @req_sz_str = 
			rtrim(convert(varchar(30), abs(@mem_to_move)))

		if (@mem_to_move > 0)
		begin
			raiserror 18560, @req_sz_str, @src_buf_sz_str,
				@dest_buf_sz_str, @cachename, @res_sz_str
		end
		else
		begin
			raiserror 18560, @req_sz_str, @dest_buf_sz_str,
				@src_buf_sz_str, @cachename, @res_sz_str
		end

		/*
		** If the destination pool has been left with a size of
		** less than 256 * (logical pagesize), then the server
		** will have marked this pool as unuseable.
		** Print a warning in such cases.
		*/
		if (@result_size != 0 and @result_size < @@min_poolsize)
		begin
			raiserror 18339, @dest_buf_sz_str, @@min_poolsize
		end

		/*
		** If the source pool has been left with a size of
		** less than 256 * (logical pagesize), then the server
		** will have marked this pool as unuseable. Print a
		** warning in such cases.
		*/
		select  @result_size = value
		from	master.dbo.sysconfigures
		where	config = @config_num_src
		  and	name = @cachename


		if (@result_size != 0 and @result_size <  @@min_poolsize)
		begin
			raiserror 18339, @src_buf_sz_str, @@min_poolsize
		end

		/*
		** Print a general message as to how to correctly resize
		** the pools.
		*/
		raiserror 18562
	end	-- }
end	-- }

/*
** Update the wash size for source and destination buffer pools if required.
** We do this at the end because, here the actual buffer movement
** has already been done and we will have the new wash size available
** for the affected buffer pools.
**
** NOTE: In syscurconfigs, we obtain the wash size in Kilobytes.
** However, we store the wash size, in sysconfigures, in
** kilobytes/Buffer pool size.
*/

/*
** There are two system tables which has all the config information.
** syscurconfigs maintains current running configuration and sysconfigures
** contains the configuration user has asked through config file and
** using config releated commands. The values in these two system catalogs
** may be different because server might calculate some values for example
** if wash size is DEFAULT (i.e value3=0 in sysconfigures) server will find
** out what is the optimal wash size and set that in syscurconfigs where as
** sysconfigures will have 0 only. This is useful because when memory is
** moved between pools and if user give wash size as DEFAULT server adjusts
** to optimal value otherwise wash size might become more than the pool
** hence memory may not be allowed to move. 
*/

/* For source pool, get the current wash size from sysconfigures. */
select  @temp_value = 0
select	@temp_value = value3 
from	master.dbo.sysconfigures 
where	config = @config_num_src
  and 	name = @cachename


/*
** At this point user has created or modified a pool. We should not update the
** wash size here because it was not specified as a parameter.
** We should leave wash size as 0 which indicates a default value.
** @temp_value will not be zero if user has explicitly changed the wash size 
** at some point of the time, in such cases we should go update the
** value to that of running value because server might give a diffrent wash
** size than we asked for.
*/
if (@temp_value != 0)
begin
	select	@wash_or_apf_size = memory_used
	from	master.dbo.syscurconfigs 
	where	config = @config_num_src
	  and	comment = @cachename


	update	master.dbo.sysconfigures 
	set 	value3 = @wash_or_apf_size/@src_buf_size
	where	config = @config_num_src
	  and	name = @cachename

end

/* Now, do the aame for destination pool.*/
select	@temp_value = 0
select	@temp_value = value3
from	master.dbo.sysconfigures 
where	config = @config_num_dest
  and	name = @cachename

  
if (@temp_value != 0)
begin
	select	@wash_or_apf_size = memory_used
	from	master.dbo.syscurconfigs
	where	config = @config_num_dest
	  and	comment = @cachename

	update	master.dbo.sysconfigures 
	set	value3 = @wash_or_apf_size/@dest_buf_size
	where	config = @config_num_dest
	  and	name = @cachename

end

/*
** Write the changes to the config file. We do not want to do this when called
** by recovery during runtime buffer tuning because in case of private install,
** when the cluster is started, the first instance writing this will prevent 
** the rest of the instance from joining the cluster in first attempt.
*/
if (@is_in_recovery not in ("TRUE", "true"))
begin
	/*
	** For SMP server the instanceid is set to NULL. In SMP we only have one
	** configuration file and hence a special where clause of instanceid is 
	** not required. 
	*/
	if (@@instanceid = NULL)
	begin
		select	@config_file_name = value2 
		from	master.dbo.syscurconfigs
		where	config = @cfgcfgfilename
	end
	else
	begin
		select	@config_file_name = value2
		from	master.dbo.syscurconfigs where	

		 config = @cfgcfgfilename
	end

	select @stat = -1
	select @stat = config_admin(@cmdupdateconfigfile, 0, 0, 0, 
				@instancename, @config_file_name) 

	if @stat = 0
	begin
		rollback tran pool_config
		return 1
	end
end
commit tran pool_config

return 0
go
exec sp_procxmode 'sp_do_poolconfig', 'anymode'
go
grant execute on sp_do_poolconfig to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_poolconfig')
begin
	drop procedure sp_poolconfig
end
go
print "Installing sp_poolconfig"
go

/* This stored procedure is a wrapper for the user to configure buffer pools. 
** It executes the stored procedure (sp_do_poolconfig) which does the actual 
** job.
**
** Validations will be done in sp_do_poolconfig.
*/
create procedure sp_poolconfig
@cachename 	varchar(255) = NULL,
@parm1		varchar(30) = NULL,
@parm2		varchar(40) = NULL,
@parm3		varchar(30) = NULL,
@parm4		varchar(255) = NULL
as

declare @ret	int	/* return status from sp_do_poolconfig */
declare @current_mode           varchar(10)

/* Store the current view */
select @current_mode = @@system_view

/*
** We will set the view to cluster here to get the entries of syscurconfigs
** for all instances.
*/
if @@clustermode = 'shared disk cluster'
begin
	set system_view cluster
end

exec @ret = sp_do_poolconfig @cachename, @parm1, @parm2, @parm3, NULL, @parm4

/* Set the view back to current mode */
if @@clustermode = 'shared disk cluster'
begin
	set system_view @current_mode
end

return @ret 

go
exec sp_procxmode 'sp_poolconfig', 'anymode'
go
grant execute on sp_poolconfig to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_unbindcache')
begin
	drop procedure sp_unbindcache
end
go
print "Installing sp_unbindcache"
go

/* Stored procedure for unbinding entites that are bound to named caches.
**
** Databases can only be unbound when using Master.
*/
create procedure sp_unbindcache
@dbname		varchar(255),
@tablename	varchar(512) = NULL,
@indexname	varchar(255) = NULL
as

declare @returncode 	smallint

/*
**  Don't allow this in a transaction because we can't undo what
**  the bind_cache() builtin has done.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_unbindcache"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sa_role") = 0)
	return (1)

execute @returncode = sp_bindcache NULL, @dbname, @tablename, @indexname

return @returncode
go
exec sp_procxmode 'sp_unbindcache', 'anymode'
go
grant execute on sp_unbindcache to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_unbindcache_all')
begin
	drop procedure sp_unbindcache_all
end
go
print "Installing sp_unbindcache_all"
go

/* Stored procedure for unbinding all entites bound to a named cache.
**
**    Databases can only be unbound when using Master.
**
**	Messages for sp_cacheconfig
**
** 17260, "Can't run %1 from within a transaction."
**
** 18135, "The specified named cache (%1) does not exist"
** 
** 18352, "Failed to set curwrite label to data_low."
**
** 19119, "You cannot use sp_unbindcache_all since 'tempdb' is bound to this cache.
**         Instead use sp_unbindcache for each object bound to this cache or run
**         sp_unbindcache_all after unbinding 'tempdb' with sp_unbindcache."
**
** 19778, "You cannot use sp_unbindcache_all when system or remote local 
**	   temporary databases are bound to this cache. Instead use
** 	   sp_unbindcache to unbind each of these databases first."
**
** 19974, "Individual object or database cannot be bound to or unbound from
**	   cache, '%1!', which is an in-memory storage cache."
*/
create procedure sp_unbindcache_all
@cachename	varchar(255)
as

declare @status		integer
declare @stat		int

/*
**  Don't allow this in a transaction because we can't undo what
**  the bind_cache() builtin has done.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_unbindcache_all"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* check if user has sa role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
if (proc_role("sa_role") = 0)
	return (1)



if not exists (select * from master.dbo.sysconfigures where name = @cachename
		and config = 19)
begin
	/* 18135, "The specified named cache (%1) does not exist" */
	raiserror 18135, @cachename
	return(1)
end



select @stat = status from master.dbo.sysconfigures 
		where name = @cachename
		and config = 19
if (@stat & 65536 = 65536)
begin
	raiserror 19974, @cachename 
	return (1)
end


	
if exists (select 1 from
		master.dbo.sysattributes
		where class = 3 and
		attribute = 0 and
		object_type = 'D' and
		object = 2 and
		char_value = @cachename)
begin
	/*
	** 19119, "You cannot use sp_unbindcache_all since 'tempdb' is 
	** bound to this cache. Instead use sp_unbindcache for each
	** object bound to this cache or run sp_unbindcache_all after
	** unbinding 'tempdb' with sp_unbindcache."
	*/
	raiserror 19119
	return (1)
end

select @status = config_admin(9, 3, 0, 0, NULL, @cachename)

/*
**  The builtin returns TRUE for success, FALSE for failure.
**  Translate that into the stored procedure lingo where 0 is success.
*/
if (@status = 1)
begin
	return(0)
end
else
begin
	return (1)
end
go
exec sp_procxmode 'sp_unbindcache_all', 'anymode'
go
grant execute on sp_unbindcache_all to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setrepcol')
begin
	drop procedure sp_setrepcol
end
go
print "Installing sp_setrepcol"
go

/*
** Generated by spgenmsgs.pl on Wed Feb  8 14:55:57 2006 
*/
/*
** raiserror Messages for setrepcol [Total 3]
**
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17966, "Due to system failure, the replication status for '%1!' has not been changed."
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) or a user with REPLICATION authorization may execute this stored procedure."
*/
/*
** sp_getmessage Messages for setrepcol [Total 15]
**
** 17142, "You need to be able to set curwrite label to data_high. This script will continue in spite of failure to set curwrite. Please rerun after setting your labels correctly."
** 17460, "Object must be in the current database."
** 17964, "The replication status for '%1!' is set to %2!."
** 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
** 18109, "Usage: sp_setrepcol table_name, column_name, {do_not_replicate | always_replicate | replicate_if_changed}"
** 18110, "The table '%1!' is not marked as replicated."
** 18111, "do_not_replicate"
** 18112, "always_replicate"
** 18113, "replicate_if_changed"
** 18114, "A table name must be provided."
** 18115, "No Text/Image or off-row object columns in '%1!'."
** 18116, "The replication status for all Text/Image and off-row object columns in '%1!' has been set to %2!."
** 18117, "Column '%1!' does not exist in '%2!' or it is not a Text/Image or off-row object column."
** 18118, "Object '%1!' does not exist in this database."
** 18687, "Cannot set replication status for in-row objects, use sp_setreptable to set the table's replication status instead. The replication status for '%1!.%2!' is not changed."
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_setrepcol
@replicate_name	varchar(767) = NULL,	/* table for the column */
@column_name	varchar(767) = NULL,	/* column we want to mark */
@setflag 	varchar(22) = NULL,	/* the replicate status. */
@use_index	varchar(10) = NULL	/* use index for text columns */
as

declare @current_status	int /* current sysstat value for the object. */
declare @new_status	int /* new sysstat value for the object. */
declare @rep_constant 	smallint /* bit which indicates a replicated object. */
declare @db		varchar(255) 	/* db of object. */
declare @owner		varchar(255) 	/* owner of object. */
declare @object		varchar(255)	/* object's name. */
declare @msg 		varchar(1024)	/* variable to get the error message */ declare @sptlang	int
declare @procval	int
declare @rnever		smallint	/* flag value for "do_not_replicate" */
declare @ralways	smallint	/* flag value for "always_replicate" */
declare @rifchanged	smallint	/* flag value for "replicate_if_changed" */
declare @rcolbitmask	smallint	/* mask for the above flags */
declare @repnever	varchar(30)	/* "do_not_replicate" */
declare @repalways	varchar(30)	/* "always_replicate" */
declare @repifchanged	varchar(30)	/* "replicate_if_changed" */
declare @colid		smallint	/* Column id of the column */
declare @objid		int		/* Id of the object */
declare @lsetflag	varchar(22)	/* lower case value of @setflag */
declare @texttype	smallint	/* SYB_TEXT type. */
declare @imagetype	smallint	/* IMAGE type. */
declare @xtype_type	smallint	/* XTYPE_TOKEN type. */
declare	@unitexttype	smallint	/* UNITEXT type. */
declare @dbname		varchar(255)
declare @xstatus	int		/* xstatus field. */
declare	@offrow		smallint	/* Object stored OFFROW. */
declare @setrep_index	int		/* Bit which indicates if the replicated					** object will use internal indexes for
					** replication.
					*/
declare @tipsa_in_index	smallint

if @@trancount = 0
begin
	set transaction isolation level 1
	set chained off
end

/*
** Replication enabled flag is 8000H (which is -32768D)
*/
select @rep_constant = -32768,
	@rnever = 0,
	@ralways = 1,
	@rifchanged = 2,
	@rcolbitmask = 3,
	@imagetype = 34,
	@texttype = 35,
	@xtype_type = 36,
	@unitexttype = 174,
	@offrow = 1,
	@setrep_index = 0,
	@tipsa_in_index = 2048

/*
** Initialize strings
*/
/* 18111, "do_not_replicate" */
exec sp_getmessage 18111, @repnever out
/* 18112, "always_replicate" */
exec sp_getmessage 18112, @repalways out
/* 18113, "replicate_if_changed" */
exec sp_getmessage 18113, @repifchanged out

/* Create a temp table for messages */
create table #setrepcol (val int, str varchar(255))
insert into #setrepcol values(@ralways, @repalways)
insert into #setrepcol values(@rnever, @repnever)
insert into #setrepcol values(@rifchanged, @repifchanged)

/*
** Set 'sptlang' for proper printing of object information.  Used mainly
** for the 'select' statement which is executed when we are invoked with
** no parameters.  Copied from similar code in 'sp_help'
*/
select @sptlang = @@langid
if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	    select @sptlang = 0
end

if (@replicate_name is NULL)
begin
	/*
	** 18114, "A table name must be provided."
	*/
        exec sp_getmessage 18114, @msg output
        print @msg
	return (1)
end
/*
** Crack the name into its corresponding pieces.
*/
execute sp_namecrack 	@replicate_name, 
			@db = @db output, 
			@owner = @owner output,
			@object = @object output

/*
** Make sure that the object is in the current database.
*/
if (@db is not NULL and @db != db_name())
begin
	/*
	** 17460, "Object must be in the current database."
	*/
        exec sp_getmessage 17460, @msg output
        print @msg
	return (1)
end

/*
**  Make sure that the object actually exists.
*/
if (object_id(@replicate_name) is NULL)
begin
	/*
	** 18118, "Object '%1!' does not exist in this database."
	*/
	exec sp_getmessage 18118, @msg output
	print @msg, @replicate_name
	return (1)
end

/*
** Check if the object is a table.
*/
if not exists (
	select id from sysobjects 
	where
		id = object_id(@replicate_name) and
		type = "U")
begin
	/*
	** 18114, "A table name must be provided."
	*/
        exec sp_getmessage 18114, @msg output
        print @msg
	return (1)
end
/*
** Check if the table is marked for replication.
*/
select @current_status = sysstat 
	from sysobjects
	where id = object_id(@replicate_name)

/*
** Is the replicate status bit even set?
*/
if (@current_status & @rep_constant) = 0
begin
	/*
	** 18110, "The object '%1!' is not marked for replication."
	*/
	exec sp_getmessage 18110, @msg output
	print @msg, @replicate_name
	return(1)
end

if (@column_name is not NULL)
begin
	if not exists (select colid from syscolumns
			   where name = @column_name
				 and id = object_id(@replicate_name)
				 and type in (@imagetype, @texttype,
					      @xtype_type, @unitexttype))
	begin
		/*
		** 18117 "Column '%1!' does not exist in '%2!' or is not
		** 	  a Text/Image or an off-row object column."
		*/
		exec sp_getmessage 18117, @msg output
		print @msg, @column_name, @replicate_name
		return(1)
	end
	
	/* If object column is specified, it must be an off-row object. */
	if exists (select colid from syscolumns
			where name = @column_name
			  and id = object_id(@replicate_name)
			  and type = @xtype_type
			  and (xstatus & @offrow) = 0 )
	begin
		/*
		** 18687, "Cannot set replication status for in-row objects,
		**	   use sp_setreptable to set the table's replication
		**	   status instead. The replication status for '%1!.%2!'
		**	   is not changed."
		*/
		exec sp_getmessage 18687, @msg output
		print @msg, @replicate_name, @column_name
		return(1)
	end

end
else
begin
	if not exists (select colid from syscolumns
			   where id = object_id(@replicate_name)
			     and ( type in (@imagetype, @texttype, @unitexttype)
				   or (type = @xtype_type
				       and (xstatus & @offrow) = @offrow) ) )
	begin
		/*
		** 18115 "No Text/Image nor an off-row object columns in '%1!'."
		*/
		exec sp_getmessage 18115, @msg output
		print @msg, @replicate_name
		return(1)
	end
end

/*
** Currently, marking for TEXT/IMAGE replication user table columns in the
** 'master' database is not allowed.
**
** Therefore, if the current database is the 'master' database, reset the
** '@setflag' to NULL so that the system procedure will report the current
** status of the user table column.  A proper error message should be
** implemented at a later date.
*/
if (db_name() = "master")
begin
	select @setflag = NULL
end

/*
** If we are invoked with two parameters, then just print out status
*/
if (@setflag is NULL)
begin
	if (@column_name is NULL)
	begin
		select
			Name = c.name,
			Type = t.name,
			Status = s.str,
			Mode = case 
				when (c.status2 & @tipsa_in_index) = @tipsa_in_index
					then "using index"
				when (c.status2 & @tipsa_in_index) = 0
					then "no index"
				when c.status2 is null
					then "no index"
			end
					
		into #setrepcol1rs
		from
			syscolumns c holdlock,
			systypes t,
			#setrepcol s
		where 
			c.id = object_id(@replicate_name)
			and ( c.type in (@imagetype, @texttype, @unitexttype)
			      or (c.type = @xtype_type
				  and (c.xstatus & @offrow) = @offrow) )
			and c.type = t.type
			and s.val = (c.status & @rcolbitmask)
	exec sp_autoformat @fulltabname = #setrepcol1rs
	drop table #setrepcol1rs
	end
	else
	begin
		select
			Name = c.name,
			Type = t.name,
			Status = s.str,
			Mode = case 
				when (c.status2 & @tipsa_in_index) = @tipsa_in_index
					then "using index"
				when (c.status2 & @tipsa_in_index) = 0
					then "no index"
				when c.status2 is null
					then "no index"
			end
					
		into #setrepcol2rs
		from
			syscolumns c holdlock,
			systypes t,
			#setrepcol s
		where 
			c.id = object_id(@replicate_name)
			and c.name = @column_name
			and ( c.type in (@imagetype, @texttype, @unitexttype)
			      or (c.type = @xtype_type
				  and (c.xstatus & @offrow) = @offrow) )
			and c.type = t.type
			and s.val = (c.status & @rcolbitmask)
	exec sp_autoformat @fulltabname = #setrepcol2rs	
	drop table #setrepcol2rs
	end
	return (0)
end

/*
** Check for a valid setname parameter
*/
if (lower(@setflag) not in ("do_not_replicate", "always_replicate",
			    "replicate_if_changed", @repnever,
			    @repalways, @repifchanged))
begin
	/*
	** 18109, "Usage: sp_setrepcol table_name, column_name,	
	**					{do_not_replicate |
	**					 always_replicate |
	**					 replicate_if_changed}
	**					[, use_index ] "
	*/
	exec sp_getmessage 18109, @msg output
	print @msg
	return (1)
end

select @use_index = lower(@use_index)

/* Check for valid use_index parameter */
if (@use_index is not null and @use_index != "use_index")
begin
	/*
	** 18109, "Usage: sp_setrepcol table_name, column_name,
        **                                      {do_not_replicate |
        **                                       always_replicate |
        **                                       replicate_if_changed}"
	**					[, use_index ]
        */
        exec sp_getmessage 18109, @msg output
        print @msg
        return (1)
end

if (@use_index in ("use_index"))
begin
	/* Set LT_SETREP_TIPSA_INDEX */
	select @setrep_index = 8
end

/*
** You must be SA, dbo or have REPLICATION role to execute this
** sproc.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("replication_role", show_role()) = 0)
	begin
		/*
		** 18418, "Only the System Administrator (SA), the
		**	   Database Owner (dbo) or a user with REPLICATION
		**	   authorization may execute this stored
		**	   procedure."
		*/
		raiserror 18418
		return (1)
	end
	else
	begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
	end
end

/*
** Perform the requested operation on the object.
*/
select @objid = object_id(@replicate_name)
select @lsetflag = lower(@setflag)



/* Start the transaction to log the execution of this procedure.
**
** IMPORTANT: The name "rs_logexec is significant and is used by 
**            Replication Server
*/
begin transaction rs_logexec

if @lsetflag in ("always_replicate", @repalways)
begin
	if (@column_name is NULL)
	begin

		declare syscol_cursor cursor for
		select  colid from syscolumns
		where
			id = @objid
			and ( type in (@imagetype, @texttype, @unitexttype)
			      or (type = @xtype_type
				  and (xstatus & @offrow) = @offrow) )
		order by colid

		open syscol_cursor
		fetch syscol_cursor into @colid
		while (@@sqlstatus = 0)
		begin
			dbcc replicate_txtcol(@objid, @colid, @lsetflag, @setrep_index)
			if @@error != 0
			begin
				/*
				** 17966 "Due to system failure, the 
				**        replication status for '%1!' has
				**	  not been changed."
				*/
				raiserror 17966, @replicate_name

				/*
				** The DBCC command may have already
				** rolled back the transaction
				*/
				if @@trancount > 0
					rollback transaction rs_logexec

				return (1)
			end
				
			fetch syscol_cursor into @colid
		end
		close syscol_cursor
		deallocate cursor syscol_cursor
	end
	else
	begin
		/* A column name was provided */
		select @colid = colid from syscolumns
		where
			name = @column_name
			and id = @objid

		dbcc replicate_txtcol(@objid, @colid, @lsetflag, @setrep_index)
		if @@error != 0
		begin
			/*
			** 17966 "Due to system failure, the 
			**        replication status for '%1!' has
			**	  not been changed."
			*/
			raiserror 17966, @replicate_name
			
			/*
			** The DBCC command may have already rolled back
			** the transaction
			*/
			if @@trancount > 0
				rollback transaction rs_logexec

			return (1)
		end
	end
end
else 
/* flag is either repnever or repifchanged */
begin
	if (@column_name is NULL)
	begin
		/*
		** Set the status for all
		** text, image, and off-row-object columns.
		*/
		declare syscol_cursor cursor for
		select colid from syscolumns
		where
			id = @objid
			and (type in (@imagetype, @texttype, @unitexttype)
			     or (type = @xtype_type
				 and (xstatus & @offrow) = @offrow) )
		order by colid

		open syscol_cursor
		fetch syscol_cursor into @colid
		while (@@sqlstatus = 0)
		begin
			dbcc replicate_txtcol(@objid, @colid, @lsetflag, @setrep_index)
			if @@error != 0
			begin
				/*
				** 17966 "Due to system failure, the 
				**        replication status for '%1!' has
				**	  not been changed."
				*/
				raiserror 17966, @replicate_name

				/*
				** The DBCC command may have already rolled
				** back the transaction
				*/
				if @@trancount > 0
					rollback transaction rs_logexec

				return (1)
			end
			fetch syscol_cursor into @colid
		end
		close syscol_cursor
		deallocate cursor syscol_cursor
	end
	else
	begin
		/* Set the status for the given column */
		select @colid = colid from syscolumns
		where
			id = @objid and 
			name = @column_name

		dbcc replicate_txtcol(@objid, @colid, @lsetflag, @setrep_index)
		if @@error != 0
		begin
			/*
			** 17966 "Due to system failure, the 
			**        replication status for '%1!' has
			**	  not been changed."
			*/
			raiserror 17966, @replicate_name

			/*
			** The DBCC command may have already rolled back
			** the transaction
			*/
			if @@trancount > 0
				rollback transaction rs_logexec

			return (1)
		end
	end
end

/*
** Write the log record to replicate this invocation 
** of the stored procedure.
*/
if (logexec() != 1)
begin
	/*
	** 17756, "The execution of the stored procedure '%1!' in
	**         database '%2!' was aborted because there was an
	**         error in writing the replication log record."
	*/
	select @dbname = db_name()
	raiserror 17756, "sp_setrepcol", @dbname
			
	rollback transaction rs_logexec
	return(1)
end

commit transaction rs_logexec

if (@column_name is NULL)
begin
	/*
	** 18116, "The replication status for all Text/Image and off-row
	**	   objectcolumns in '%1!' is set to %2!."
	*/
	exec sp_getmessage 18116, @msg output
	print @msg, @replicate_name, @setflag
	return(0)
end
else
begin
	/*
	** 17964 "The replication status for '%1!' is set to %2!."
	*/
	exec sp_getmessage 17964, @msg output
	print @msg, @column_name, @setflag
	return(0)
end
go
exec sp_procxmode 'sp_setrepcol', 'anymode'
go
grant execute on sp_setrepcol to public
go
exec sp_procxmode 'sp_setrepcol', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setrepproc')
begin
	drop procedure sp_setrepproc
end
go
print "Installing sp_setrepproc"
go

/* Sccsid = "@(#) generic/sproc/setreplicate 155.1 11/10/94" */
/*
** Messages for "sp_setreplicate"	17960
**
** 17230, "Only the System Administrator (SA) or the Database Owner
**	   (dbo) may execute this stored procedure."
** 17432, "false"
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 17962, "The replication status for '%1!' is already set to %2!.
**	   Replication status for '%3!' does not change."
** 17963, "A object with the same name, but owned by a different user
**	   is already being replicated.  The object '%1!' cannot be
**	   replicated."
** 17965, "The replication status for '%1!' is currently %2!."
** 17966, "Due to system failure, the replication status for '%1!' has
**	   not been changed."
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) or
**	   a user with REPLICATION authorization may execute this stored
**	   procedure."
** 17968, "The built-in function logschema() failed for '%1!'."
** 18104, "table"
** 18105, "function"
** 18106, "Stored Procedure must be in the current database."
** 18107, "Stored Procedure '%1!' does not exist in this database."
** 18108, "Usage: sp_setrepproc [proc_name [, {'false' | 'table' | 
			{'function' [,{'log_current' | 'log_sproc'}]}}]]
** 18688, "Stored procedures with object parameters cannot be marked for
**	   replication yet at this time. Instead, use sp_setreptable to
**	   mark the invidual tables for replication. The replication status
**	   for '%1!' is not changed."
** 18846, "Object name cannot be null when other parameters are non null.
** 18847, "The log mode for '%1!' is currently %2!."
** 18848, "The replication status for '%1!' is already set to %2!,
**	   with log mode set to %3!. Replication status for '%4!'
**	   does not change.
** 18849, "The log mode is set to %1!."
*/

create procedure sp_setrepproc
@replicate_name	varchar(767) = NULL,	/* obj we want to mark as replicate */
@setflag 	varchar(20) = NULL,	/* set or unset the replicate status. */
@logflag	varchar(20) = NULL	/* log EXECBEGIN in the current
					** database or in the sproc's database.
					*/
as

declare @sysstat1_curr	int 		/* current sysobjects.sysstat.	*/
declare @sysstat1_new	int 		/* new sysobjects.sysstat.	*/
declare @sysstat1_mask	int 		/* mask for sysobjects.sysstat.	*/
declare @sysstat2_curr	int		/* current sysobjects.sysstat2.	*/
declare @sysstat2_new	int		/* new sysobjects.sysstat2.	*/
declare @sysstat2_mask	int 		/* mask for sysobjects.sysstat2.*/
declare @rep_constant 	int 		/* O_REPLICATED (0x8000) bit in
					** bit in sysobjects.sysstat.	*/
declare @sub_constant	int 		/* O_PROC_SUBSCRIBABLE (0x40)
					** bit in sysobjects.sysstat.	*/
declare @log_constant	int		/* O2_REP_LOG_SPROC (0x800000)
					** bit in sysobjects.sysstat2.	*/
declare @setrep_flags	int	 	/* repflags parameter passed to
					** setrepstatus().		*/
declare @db		varchar(255) 	/* db of object. */
declare @owner		varchar(255) 	/* owner of object. */
declare @object		varchar(255)	/* object's name. */
declare @true		varchar(30)   	/* "TRUE" */
declare @table		varchar(30)	/* "TABLE" */
declare @function	varchar(30)	/* "FUNCTION" */
declare @false		varchar(30)	/* "FALSE" */
declare @log_current	varchar(30)	/* "LOG_CURRENT" */
declare @log_sproc	varchar(30)	/* "LOG_SPROC" */
declare @msg 		varchar(1024)	/* Used to get Error messages */
declare @tmpstr		varchar(20)	/* Used to display replication type
					** (table/function) in messages.
					*/
declare @logstr		varchar(20)	/* Used to display logmode in messages.
					*/
declare @procval	int
declare @objid		int	/* Id of the procedure to be marked */
declare @log_aft_img	int	/* log after image schema when replication
				** status is turned on, or the replication
				** status is already on, but the sproc
				** replication type (function/table), or
				** logging mode (sproc/current) changes.
				*/
declare @log_bef_img	int	/* log before image schema when replication
				** status is turned off.
				*/
declare @user_tran	int	/* are we inside a user tran? */
declare @after_image	int	/* log the after image of the schema */
declare @mod_versionts	int	/* modify version timestamp after logging
				** the schema
				*/
declare @dbname varchar(30)
declare @xtype_token	int	/* Type for object paramters. */
declare @setrep_replicate	int	/* setrepstatus() LT_SETREP_REPLICATE
					** flag.   */
declare @setrep_subscribable	int	/* setrepstatus() LT_SETREP_SUBSCRIBABLE
					** flag.*/
declare @setrep_log_sproc	int	/* setrepstatus() LT_SETREP_LOG_SPROC
					** flag. */

if @@trancount = 0
begin
	set transaction isolation level 1
	set chained off
end

if (@@trancount > 0)
	select @user_tran = 1
else
	select @user_tran = 0

/*
** Define sysobject sysstat and sysstat2 constants.
**
** O_REPLICATED bit flag in sysstat is 0x8000 (-32768)
** O_PROC_SUBSCRIBABLE bit flag in sysstat flag is 0x0040 (64)
** O2_REP_LOG_SPROC bit flag in sysstat2 is 0x800000 (8388608).
** See objects.h for bit flag defines.
*/
select	@rep_constant = -32768,
	@sub_constant = 64,
	@log_constant = 8388608


/* set @log_aft_img and @log_bef_img to false initially */
select	@log_aft_img = 0,
	@log_bef_img = 0

/* Datatype value for objects. */
select @xtype_token = 36

/*
** Initialize ssetrepstatus() repflags constants.
** See logtrans.h for bit flag defines.
*/
select	@setrep_replicate = 1,		/* LT_SETREP_REPLICATE	  0x00000001 */
	@setrep_subscribable = 2,	/* LT_SETREP_SUBSCRIBABLE 0x00000002 */
	@setrep_log_sproc = 4		/* LT_SETREP_LOG_SPROC    0x00000004 */

/*
** Initialize 'true' and 'false' strings
*/
/* 18104, "table" */
exec sp_getmessage 18104, @table out
/* 18105, "function" */
exec sp_getmessage 18105, @function out
/* 17432, "false" */
exec sp_getmessage 17432, @false out
/* 18844, "log_current" */
exec sp_getmessage 18844, @log_current out
/* 18845, "log_sproc" */
exec sp_getmessage 18845, @log_sproc out

/*
** If we are invoked with no parameters, then just print out all procedures
** which are marked for replication.  The 'select' statement is heavily
** based upon the one found in 'sp_help'.
*/
if (@replicate_name is NULL and @setflag is NULL and @logflag is NULL)
begin
	select
		Name = o.name,
		Type = convert(char(14), m1.description),
		Mode = convert(char(14), m2.description)
	into #setrepproc1rs
	from
		sysobjects o,
		master.dbo.sysmessages m1,
		master.dbo.sysmessages m2
	where 
		o.type = "P"		
		and isnull(m1.langid,0) = @@langid
		and isnull(m2.langid,0) = @@langid
		and (o.sysstat & @rep_constant) = @rep_constant
		and (    ((o.sysstat & @sub_constant) = @sub_constant
			    and m1.error = 18105)  	/* function */
		     or  ((o.sysstat & @sub_constant) = 0
			    and m1.error = 18104) )	/* table */
		and (    ((o.sysstat2 & @log_constant) = @log_constant
			    and m2.error = 18845)	/* log_sproc */
		     or  ((o.sysstat2 & @log_constant) = 0
			    and m2.error = 18844) )	/* log_current */
	exec sp_autoformat @fulltabname = #setrepproc1rs,
		@selectlist = "Name, Type,'Log Mode'= Mode" 
	drop table #setrepproc1rs
	return (0)
end

/*
** Don't allow replicate name to be null, with non-null setflag and/or logflag.
*/
if (@replicate_name is NULL) and (@setflag is not NULL or @logflag is not NULL)
begin
	/*
	** 18846, "Object name cannot be null when other parameters
	**	   are non null."
	*/
	raiserror 18846
	return (1)
end

/*
** Crack the name into its corresponding pieces.
*/
execute sp_namecrack 	@replicate_name, 
			@db = @db output, 
			@owner = @owner output,
			@object = @object output

/*
** Make sure that the object is in the current database.
*/
if (@db is not NULL and @db != db_name())
begin
	/*
	** 18106, "Procedure must be in the current database."
	*/
	raiserror 18106
	return (1)
end

/*
**  Make sure that the object actually exists.
*/
select @objid = object_id(@replicate_name)

if (@objid is NULL)
	or (not exists (select name from sysobjects where 
		id = @objid and
		type = "P"
		))
begin
	/*
	** 18107, "Procedure does not exist in this database."
	*/
	raiserror 18107, @replicate_name
	return (1)
end

/*
** If the @setflag and @logflag are NULL, then we are only interested in the
** current replication status of the specified object.
*/
if (@setflag is NULL and @logflag is NULL)
begin
	/*
	** Get the sproc's current sysstat and sysstat2 from sysobjects
	** Hold a read lock on sysobjects so that the statuses cannot be
	** changed until we're done.
	*/
	select
		@sysstat1_curr = sysstat,
		@sysstat2_curr = sysstat2
	from 
		sysobjects holdlock
	where 
		id = @objid 

	/*
	** If sproc is replicated, get replication type and log mode.
	*/
	if (@sysstat1_curr & @rep_constant) = @rep_constant
	begin
		/* Is this a subscribable function?. */
		if (@sysstat1_curr & @sub_constant) = @sub_constant
		begin
			select @tmpstr = @function
		end
		else
		begin
			select @tmpstr = @table
		end

		/* Is log mode log_sproc?. */
		if (@sysstat2_curr & @log_constant) = @log_constant
		begin
			select @logstr = @log_sproc
		end
		else
		begin
			select @logstr = @log_current
		end
	end

	/* Otherwise, sproc is not replicated. */
	else
	begin
		select @tmpstr = @false
	end


	/*
	** 17965 "The replication status for '%1!' is currently %2!."
	*/
	exec sp_getmessage 17965, @msg output
	print @msg, @replicate_name, @tmpstr

	/* If the sproc is replicated, display the log mode. */
	if (@tmpstr != @false)
	begin
		/*
		** 18847 "The log mode for '%1!' is currently %2!"
		*/
		exec sp_getmessage 18847, @msg output
		print @msg, @replicate_name, @logstr
	end
	return (0)
end

/*
** You must be SA, dbo or have REPLICATION role to execute this
** sproc.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("replication_role", show_role()) = 0)
	begin
		/*
		** 18418, "Only the System Administrator (SA), the
		**	   Database Owner (dbo) or a user with REPLICATION
		**	   authorization may execute this stored
		**	   procedure."
		*/
		raiserror 18418
		return (1)
	end
	else
	begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
	end
end

/*
** At this point, we know that the sproc is not being invoked for
** informational purposes. 
*/

/*
** Disallow any log mode when the replication status is not "function".
** The default value will be applied.
*/
if (lower(@setflag) not in ("function", @function)) and (@logflag is not NULL)
begin
	/*
	** 18108 "Usage: sp_setrepproc [proc_name [, {'false' | 'table' |
                        {'function' [,{'log_current' | 'log_sproc'}]}}]]
	*/
	raiserror 18108
	return (1)
end

/*
** Replace any null parameters by the default value for that parameter.
*/

/* If @setflag is null, default is function. */
if (@setflag is NULL)
begin
	select @setflag = @function
end

/* If @logflag is null, default is log_sproc. */
if (@logflag is NULL)
begin
	select @logflag = @log_sproc
end

/*
** Check for a valid setname parameter
*/
if (lower(@setflag) not in ("function", "table", "false",
			    @function,  @table,  @false))
begin
	/*
	** 18108 "Usage: sp_setrepproc [proc_name [, {'false' | 'table' |
                        {'function' [,{'log_current' | 'log_sproc'}]}}]]
	*/
	raiserror 18108
	return (1)
end

/*
** Check for a valid logflag parameter
*/
if (lower(@logflag) not in ("log_sproc", "log_current",
			    @log_sproc,  @log_current))
begin
	/*
	** 18108 "Usage: sp_setrepproc [proc_name [, {'false' | 'table' |
                        {'function' [,{'log_current' | 'log_sproc'}]}}]]
	*/
	raiserror 18108
	return (1)
end

/*
** Get the object's current status. Hold a read lock on sysobjects so that 
**	the statuses cannot be changed until we're done.
*/
select
	@sysstat1_curr = sysstat,
	@sysstat2_curr = sysstat2
from
	sysobjects holdlock
where
	id = @objid 

/*
** Perform the requested operation on the object.
*/
if lower(@setflag) in ("false", @false)
begin
	/* Is the replicate status bit even set? */
	if (@sysstat1_curr & @rep_constant) = 0
	begin
		/*
		** 17962 "The replication status for '%1!' is already
		**	  set to %2!.  Replication status for '%3!'
		**	  does not change."
		*/
		raiserror 17962, @replicate_name, @setflag, @replicate_name
		return(1)
	end

	/*
	** Initialize new values for sysstat, sysstat2 with all replication
	** related bit cleared. Initialize @setrep_flags to 0 to have
	** setrepstatus() clear all replication related bits.
	** Since the replication status is being turned off, we need to
	** set @log_bef_img to log the before image.
	*/
	select	@sysstat1_new = @sysstat1_curr &
					~(@rep_constant | @sub_constant),
		@sysstat2_new = @sysstat2_curr & ~@log_constant,
		@setrep_flags = 0,
		@log_bef_img = 1
end

/*
** If @setflag is table or function, check the following..
**	- not already marked for replication
**	- another object with same name but different owner is
**	  already marked  for replication
**	- has no parameters of type object.
*/
else if lower(@setflag) in ("table", @table, "function", @function)
begin
	/* The @sysstat1 mask has all replication related bits set. */
	select @sysstat1_mask = (@rep_constant | @sub_constant)

	/* Calculate the new the sysstat value based on @setflag. */
	if lower(@setflag) in ("table", @table)
	begin
		/* New sysstat will have the replicate bit set. */
		select @sysstat1_new = @rep_constant
	end
	else
	begin
		/*
		** New sysstat will have the replicate and the subscribable
		** bits set.
		*/
		select @sysstat1_new = @rep_constant | @sub_constant
	end

	/* The @sysstat2 mask has all replication related bits set. */
	select @sysstat2_mask = @log_constant

	/* Calculate the new sysstat2 value. */
	if lower(@logflag) in ("log_sproc", @log_sproc)
	begin
		/* New sysstat2 value will have the log_sproc bit set. */
		select @sysstat2_new = @log_constant
	end
	else
	begin
		/* New sysstat2 value will have the log_sproc bit cleared. */
		select @sysstat2_new = 0
	end

	/*
	** If sysstat and sysstat2 are not going to change, raise 18848
	*/
	if ((@sysstat1_curr & @sysstat1_mask) = @sysstat1_new)
	    and ((@sysstat2_curr & @sysstat2_mask) = @sysstat2_new)
	begin
		/*
		** 18848 "The replication status for '%1!' is already
		**	  set to %2!, with log mode set to %3!. Replication
		**	  status for '%4!' does not change."
		*/
		raiserror 18848, @replicate_name, @setflag, @logflag,
				 @replicate_name
		return(1)
	end

	/*
	** Make sure that no like object with the same name, but a
	** different owner, exists.  We need to do this because
	** the SQL Server does not send owner information along
	** with the object to the Replication Server.  This
	** restriction may be lifted in future versions.
	*/
	if exists (select * from sysobjects
			where name = @object
			and id != @objid 
			and (
				(type = "U ") /* user table */
			or
				(type = "P ") /* stored procedure */
			)
			and sysstat & @rep_constant != 0)
	begin
		/*
		** 17963 "An object with the same name, but owned by a
		**	  different user is already being replicated.
		**	  The object '%1!' cannot be replicated."
		*/
		raiserror 17963, @replicate_name
		return(1)
	end

	/* Disallow sprocs with object parameters. */
	if exists( select * from syscolumns
		   where id = @objid and type = @xtype_token )
	begin
		/*
		** 18688, "Stored procedures with object parameters cannot be
		**	   marked for replication yet at this time. Instead,
		**	   use sp_setreptable to mark the invidual tables for
		**	   replication. The replication status for '%1!' is
		**	   not changed."
		*/
		raiserror 18688, @replicate_name
		return(1)
	end

	/*
	** Calculate @sysstat1_new and @sysstat2_new values.
	** The new value is calculated by first clearing all replication
	** related bits, and then setting the desired bits.
	*/
	select @sysstat1_new = (@sysstat1_curr & ~@sysstat1_mask)
					| @sysstat1_new
	select @sysstat2_new = (@sysstat2_curr & ~@sysstat2_mask)
					| @sysstat2_new
	
	/*
	** Calcuate @setrep_flags based on the new sysstat1 and sysstat2 values.
	** This variable is the repflags parameter to be passed to
	** setrepstatus(), which will update the replication status of
	** an object in cache. Whatever bits that are cleared or set in
	** the object's sysobjects row, must also be cleared or set in the
	** cached version.
	**
	** First initialize @setrep_flags to 0.
	*/
	select @setrep_flags = 0

	/* Is the replication bit set?. */
	if ((@sysstat1_new & @rep_constant) != 0)
	begin
		select @setrep_flags = @setrep_flags | @setrep_replicate
	end

	/* Is the subscribable bit set?. */
	if ((@sysstat1_new & @sub_constant) != 0)
	begin
		select @setrep_flags = @setrep_flags | @setrep_subscribable
	end

	/* Is the log_sproc bit set?. */
	if ((@sysstat2_new & @log_constant) != 0)
	begin
		select @setrep_flags = @setrep_flags | @setrep_log_sproc
	end

	/*
	** The after image needs to be logged because replication is being
	** turned from off to on, or the sproc's replication type or
	** logging mode is being changed. Any of these changes require the
	** after image to be logged.
	*/
	select @log_aft_img = 1
end

/*
** Update the object's sysstat and sysstat2 columns
**
** IMPORTANT: This transaction name is significant and is used by
**            Replication Server
*/
begin transaction rs_logexec

	select @objid = @objid 

	/* log the schema first if we are turning off replication */
	if (@log_bef_img = 1)
	begin
		/*
		** Initialize flags passed to logschema().
		**   @after_image is 0 because this is not an after image.
		**   @mod_versionts is 1 to modify the object's log version
		**		timestamp.
		**
		** logschema() will log the objects schema, before image in
		** this case.
		*/
		select	@after_image = 0,
			@mod_versionts = 1
		if (logschema(@objid, @user_tran, @after_image, @mod_versionts)
			!= 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'."
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name
		
			rollback transaction rs_logexec
			return(1)
		end
	end

	/* Update the sysobjects row. */
	update	sysobjects
	set	sysstat = @sysstat1_new,
		sysstat2 = @sysstat2_new
	where	id = @objid

	/*
	** Log the after image only if we are in a user initiated transaction.
	** After images are needed to rebuild the object's schema in the case
	** or rollbacks and ddl-in-tran is on.
	*/
	if ((@log_aft_img = 1) and (@user_tran = 1))
	begin
		/*
		** Initialize flags passed to logschema().
		**    @after_image is 1 because this is an after image.
		**    @mod_versionts is 0 because we don't want to change
		**	the object's log version timestamp.
		*/
		select	@after_image = 1,
			@mod_versionts = 0
		if (logschema(@objid, @user_tran, @after_image, @mod_versionts)
			!= 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'."
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name
		
			rollback transaction rs_logexec
			return(1)
		end
	end

	/*
	** Update the object's status in cache.
	*/
	if (setrepstatus(@objid, @setrep_flags) != 1)
	begin
		/*
		** 17966 "Due to system failure, the replication status
		**	  for '%1!' has not been changed."
		*/
		raiserror 17966, @replicate_name

		rollback transaction rs_logexec

		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_setrepproc", @dbname
			
		rollback transaction rs_logexec
		return(1)
	end

commit transaction

/*
** 17964 "The replication status for '%1!' is set to %2!."
*/
exec sp_getmessage 17964, @msg output
print @msg, @replicate_name, @setflag

/*
** If status is not being turned off, also display log_mode.
** Detect the status not being turned off by @setrep_flags not being 0.
*/
if (@setrep_flags != 0)
begin
	/*
	** 18849 "The log mode is set to %1!."
	*/
	exec sp_getmessage 18849, @msg output
	print @msg, @logflag
end

return(0)
go
exec sp_procxmode 'sp_setrepproc', 'anymode'
go
grant execute on sp_setrepproc to public
go
exec sp_procxmode 'sp_setrepproc', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setreptable')
begin
	drop procedure sp_setreptable
end
go
print "Installing sp_setreptable"
go

/*
** Generated by spgenmsgs.pl on Wed Feb  8 14:55:58 2006 
*/
/*
** raiserror Messages for setreptable [Total 10]
**
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 17962, "The replication status for '%1!' is already set to %2!. Replication status for '%3!' does not change."
** 17966, "Due to system failure, the replication status for '%1!' has not been changed."
** 18100, "Usage: sp_setreptable [ table_name [, {true | false} [, {owner_on | owner_off} ] ] ]"
**
** RESOLVER:
** This message has to be changed, as sp syntax has changed
**
** 18101, "The specified table must be in the current database."
** 18102, "Table '%1!' does not exist in this database."
** 18103, "An object with the same name, but owned by a different user, is already being replicated.  The table '%1!' cannot be replicated."
** 18409, "The built-in function '%1!' failed. Please see any other messages printed along with this message."
** 18410, "The replication status of '%1!' is corrupt. Please contact Sybase Technical Support."
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) or a user with REPLICATION authorization may execute this stored procedure."
*/
/*
** sp_getmessage Messages for setreptable [Total 7]
**
** 17431, "true"
** 17432, "false"
** 17964, "The replication status for '%1!' is set to %2!."
** 17965, "The replication status for '%1!' is currently %2!."
** 17968, "The built-in function logschema() failed for '%1!'. See the other messages printed along with this message for more information."
** 18538, "owner_on"
** 18539, "owner_off"
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_setreptable
@replicate_name	varchar(767) = NULL,	/* obj we want to mark as replicate */
@setflag 	varchar(5) = NULL,	/* set or unset the replicate status.*/
@repdefmode	varchar(10) = NULL,	/* Send Owner Information ? */
@use_index	varchar(12) = NULL	/* Use indexes for text columns */
as

declare @current_status	int /* current sysstat value for the object. */
declare @current_mode	int /* current repdef mode for the object. */
declare @current_index_mode
			int /* current index mode for the object. */
declare @current_never	int /* current never mode for the object. */
declare @new_status	int /* new sysstat value for the object. */
declare @new_status2	int /* new sysstat2 value for the object. */
declare @rep_constant 	smallint /* bit which indicates a replicated object. */
declare	@setrep_repl	int	 /* setrepstatus() LT_SETREP_REPLICATE flag
				 ** for setting the replication bit.
				 */
declare @setrep_owner	int	/* Bit which indicates if the replicated object
				** will use owner information for replication
				*/
declare @setrep_index	int	/* Bit which indicates if the replicated object
				** will use internal indexes for text
				** replication */
declare	@setrep_never	int	/* Bit which indicates if the object will be
				** marked as never replicated regardless of the
				** database configuration setting.
				*/
declare @colrepalwys	smallint
declare @colrepifch	smallint
declare @tipsa_in_index	smallint
declare @db		varchar(255) 	/* db of object. */
declare @owner		varchar(255) 	/* owner of object. */
declare @object		varchar(255)	/* object's name. */
declare @true		varchar(10)
declare @false		varchar(10)
declare @never		varchar(10)
declare @msg 		varchar(1024)
declare @tmpstr		varchar(30)
declare @sptlang	int
declare @procval	int
declare @texttype	smallint
declare @imagetype	smallint
declare @unitexttype	smallint	/* UNITEXT type. */
declare @xtype_type	smallint
declare @offrow		smallint
declare @objid		int
declare @rep_on_schema	int	/* log schema when turning replication on? */ 
declare @rep_off_schema	int	/* log schema when turning replication off? */ 
declare @owner_on	varchar(10)
declare @owner_off	varchar(10)
declare @user_tran	int	/* are we inside a user tran? */
declare @after_image	int	/* log the after image of the schema */
declare @mod_versionts  int	/* modify version timestamp after logging
				** the schema
				*/
declare @owner_bit	int
declare @index_bit	int 
declare @setrep_flags	int	/* repflags parm passed to setrepstatus(). */
declare @retstat	int
declare @omsg		varchar(40)
declare @dbname 	varchar(255)
declare @col_name	varchar(255)

declare @curstat        int
declare @reptostandbyon        int /* 1: standby server is running */
declare @db_rep_level_all      int /* All level replication */
declare @db_rep_level_none     int /* no replication        */
declare @db_rep_level_l1       int /* L1 level replication  */
declare @lt_rep_get_failed     int /* LT_GET_REP_FAILED */
declare @lt_rep_all            int /* LT_REP_ALL */
declare @lt_rep_l1             int /* LT_REP_L1 */
 
 
if @@trancount = 0
begin
	set transaction isolation level 1
	set chained off
end

if (@@trancount > 0)
	select @user_tran = 1
else
	select @user_tran = 0

/*
** Replication enabled flag is 8000H (which is -32768D)
*/
select @rep_constant = -32768,
	@colrepalwys  = 1,
	@colrepifch = 2,
	@imagetype = 34,
	@texttype = 35,
	@xtype_type = 36,
	@unitexttype = 174,
	@offrow = 1,
	@owner_bit = 4096,   		/* 0x1000 in sysstat2 */
        @db_rep_level_all = -1,
        @db_rep_level_l1 = 1,
	@tipsa_in_index = 2048,
	@setrep_index = 8,		/* LT_SETREP_TIPSA_INDEX */
	@setrep_owner = 16,		/* LT_SETREP_OWNER */
	@setrep_never = 1024,		/* LT_REP_NEVER */
	@retstat = 1,
	@index_bit = 8388608, 		/* 0x800000 in sysstat2 */
	@lt_rep_get_failed = -2,        /* LT_GET_REP_FAILED */
	@lt_rep_all = 2048,		/* LT_REP_ALL */
	@lt_rep_l1 = 4096		/* LT_REP_L1 */

/*
** Initialize @setrep_repl to LT_SETREP_REPLICATE (0x00000001).
** setrepstatus() flags are defined in logtrans.h
*/
select @setrep_repl = 1

/* set @rep_on_schema and rep_off_schema to false initially */
select @rep_on_schema = 0
select @rep_off_schema = 0

/*
** Initialize 'true' and 'false' strings
*/
/* 17431, "true" */
exec sp_getmessage 17431, @true out
/* 17432, "false" */
exec sp_getmessage 17432, @false out
/* 18538, "owner_on" */
exec sp_getmessage 18538, @owner_on out
/* 18539, "owner_off" */
exec sp_getmessage 18539, @owner_off out
/* 19896, "never" */
exec sp_getmessage 19896, @never out

/* Create the temporary table for printing the values */
create table #repdefmode(val int, str varchar(10))

insert #repdefmode values(0, @owner_off)
insert #repdefmode values(@owner_bit, @owner_on)

/* Create the temporary table for printing index status value */
create table #indexmode(val int, str varchar(15))

insert #indexmode values(0, 'no index')
insert #indexmode values(@index_bit, 'using index')

select @dbname = db_name()

/*
** Set 'sptlang' for proper printing of object information.  Used mainly
** for the 'select' statement which is executed when we are invoked with
** no parameters.  Copied from similar code in 'sp_help'
*/
select @sptlang = @@langid
if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	    select @sptlang = 0
end

/*
** If we are invoked with no parameters, then just print out all objects
** which are marked for replication.  The 'select' statement is heavily
** based upon the one found in 'sp_help'.
*/
if (@replicate_name is NULL and @setflag is NULL and @use_index is NULL)
begin
	select
		Name = o.name,
		"Repdef_Mode" = t.str,
		"Index_Mode" = x.str
	into #show_replicate_table
	from
		sysobjects o,
		#repdefmode t,
		#indexmode x
	where 
		o.type = "U"
		and (o.sysstat & @rep_constant) = @rep_constant
		and (o.sysstat2 & @owner_bit) = t.val
		and (o.sysstat2 & @index_bit) = x.val
	
	exec sp_autoformat #show_replicate_table, 
	   "Name = Name, 'Repdef Mode' = Repdef_Mode, 'Index Mode' = Index_Mode"
	
	drop table #show_replicate_table

	return (0)
end

/*
** Crack the name into its corresponding pieces.
*/
execute sp_namecrack 	@replicate_name, 
			@db = @db output, 
			@owner = @owner output,
			@object = @object output

/*
** Make sure that the object is in the current database.
*/
if (@db is not NULL and @db != db_name())
begin
	/*
	** 18101, "Table must be in the current database."
	*/
	raiserror 18101
	return (1)
end

/*
**  Make sure that the object actually exists.
*/
select @objid = object_id(@replicate_name)

if (@objid is NULL) or
	(not exists (select name from sysobjects where 
		id = @objid and
		type = "U"
		))
begin
	/*
	** 18102, "Table '%1!' does not exist in this database."
	*/
	raiserror 18102, @replicate_name
	return (1)
end

/*
** Currently, marking for replication user tables in the 'master' database
** is not allowed.
**
** Therefore, if the current database is the 'master' database, reset the
** '@setflag' to NULL so that the system procedure will report the current
** status of the user table.  A proper error message should be implemented
** at a later date.
*/
if (db_name() = "master")
begin
	select @setflag = NULL
end

/*
** If the 'setflag' parameter is NULL, then we are only interested in the
** current replication status of the specified object.
*/
if (@setflag is NULL)
begin
	select
		@current_status = (sysstat & @rep_constant),
		@current_mode = (sysstat2 & @owner_bit),
		@current_index_mode = (sysstat2 & @index_bit)
	from 
		sysobjects 
	where 
		id = @objid 

	select  @current_never = getrepdefmode(@objid)

	if (@current_never < 0)
	begin
		/*
		** 18409, "The built-in function '%1!' failed. Please see any 
		** other messages printed along with this message."
		*/
                raiserror 18409, "getrepdefmode"
                return (1)
	end

	if @current_status  = @rep_constant
		select @tmpstr = @true
	else
	begin
		if ((@current_never & @setrep_never) != 0)
			select @tmpstr = @never
		else
			select @tmpstr = @false
	end
	if @current_mode = 0
		select @tmpstr = @tmpstr + ", " + @owner_off
	else
		select @tmpstr = @tmpstr + ", " + @owner_on
	if @current_index_mode = @index_bit
		select @tmpstr = @tmpstr + ", " + "using index"
	/*
	** 17965 "The replication status for '%1!' is currently %2!."
	*/
	exec sp_getmessage 17965, @msg output
	print @msg, @replicate_name, @tmpstr

	return (0)
end

/*
** You must be SA, dbo or have REPLICATION role to execute this
** sproc.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and
	    charindex("replication_role", show_role()) = 0)
	begin
		/*
		** 18418, "Only the System Administrator (SA), the
		**	   Database Owner (dbo) or a user with REPLICATION
		**	   authorization may execute this stored
		**	   procedure."
		*/
		raiserror 18418
		return (1)
	end
	else
	begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
	end
end

/*
** Check for a valid setflag parameter
*/
if (lower(@setflag) not in ("true", "false", "never", @true, @false, @never))
begin
	/*
	** 18100 "Usage: sp_setreptable table_name, {true | false | never} 
	**	   				 {owner_on | owner_off}
	**					 [, use_index ]"
	*/
	raiserror 18100
	return (1)
end

/* Default repdefmode is "owner_off"
*/
if (@repdefmode is NULL)
	select @repdefmode = @owner_off
/*
** Check for a valid repdefmode parameter
*/
if (lower(@repdefmode) not in (@owner_on, @owner_off, "owner_on", "owner_off"))
begin
	/*
	** 18100, "Usage: sp_setreptable table_name, {true | false | never},
	**	   				 {owner_on | owner_off}
	**					 [, use_index ]"
	*/
	raiserror 18100
	return (1)
end

/*
** Check for valid use_index parameter
*/
if (@use_index is not null and (lower(@use_index) != "use_index"))
begin
	/*
	** 18100, "Usage: sp_setreptable table_name, {true | false | never},
	**	   				 {owner_on | owner_off}
	**					 [, use_index ]"
	*/
	raiserror 18100
	return(1)
end
if (@use_index is not null)
begin
	select @setrep_repl = @setrep_repl | @setrep_index
end

/*
** First, determine the current replication status of the database.
*/
select @curstat = getdbrepstat()
 
/*
** Perform sanity checks on the returned value
** getdbrepstat() return current status of replication server. Check returned
** message, system supports only L1 and All level replication.
*/
if (@curstat = @lt_rep_get_failed)
begin
        /*
        ** 18409, "The built-in function '%1!' failed. Please
        ** see any other messages printed along with this message."
        */
        raiserror 18409, "getdbrepstat"
        return (1)
end
 
if ((@curstat & @lt_rep_all = @lt_rep_all) or
	(@curstat & @lt_rep_l1 = @lt_rep_l1))
 begin
	select @reptostandbyon = 1
end
else
begin
	select @reptostandbyon = 0
end
        
/*
** Get the object's current status. Hold a read lock on sysobjects so that 
**	the status cannot be changed until we're done.
*/
select @current_status = sysstat, @current_mode = sysstat2
	from sysobjects holdlock
		where id = @objid 

/*
** Perform the requested operation on the object.
** If setflag is FALSE or NEVER, we ignore the other parameters.
*/
if lower(@setflag) in ("false", @false)
begin
	select @current_never = getrepdefmode(@objid)

	/*
	** Check if we have to remove the replication status
	*/
	if ((@current_never & @setrep_never) = 0)
		and (@current_status & @rep_constant) = 0
	begin
		/*
		** 17962 "The replication status for '%1!' is already
		**	  set to %2!.  Replication status for '%3!'
		**	  does not change."
		*/
		raiserror 17962, @replicate_name, @setflag, @replicate_name
		return(1)
	end

	select @new_status = @current_status & ~@rep_constant
	select @new_status2 = @current_mode & ~(@owner_bit | @index_bit)
	select @rep_off_schema = 1
	select @setrep_flags = 0

	/*
	** Even if the user gives a third parameter, set it to
	** "owner_off" so that the message printed out at the end
	** of the procedure is correct.
	*/
	select @repdefmode = @owner_off
end
else if lower(@setflag) in ("never", @never)
begin
	select  @current_never = getrepdefmode(@objid)

	if (@current_never & @setrep_never) != 0
	begin
		/*
		** 17962 "The replication status for '%1!' is already
		**	  set to %2!.  Replication status for '%3!'
		**	  does not change."
		*/
		raiserror 17962, @replicate_name, @setflag, @replicate_name
		return(1)
	end
	set @setrep_flags = @setrep_never
end
else
begin
	/*
	** We are turning ON replication on this table.
	**
	** Is the replicate status bit already set?
	*/
	if (@current_status & @rep_constant) != 0
	begin
		/*
		** 17962 "The replication status for '%1!' is already
		**	  set to %2!.  Replication status for '%3!'
		**	  does not change."
		*/
		raiserror 17962, @replicate_name, @setflag, @replicate_name
		return(1)
	end

	if (lower(@repdefmode) in (@owner_off, "owner_off"))
	begin
		/*
		** Make sure that no like object with the same name, but a
		** different owner, exists.  We need to do this because
		** the SQL Server does not send owner information along
		** with the object to the Replication Server.  This
		** restriction may be lifted in future versions.
		*/
		if exists (select * from sysobjects
				where name = @object
				and (
					(type = "U ") /* user table */
				or
					(type = "P ") /* stored procedure */
				)
				and sysstat & @rep_constant != 0
				and sysstat2 & @owner_bit = 0)
		begin
			/*
			** 18103 "An object with the same name, but owned by a
			**	  different user is already being replicated.
			**	  The table '%1!' cannot be replicated."
			*/
			raiserror 18103, @replicate_name
			return(1)
		end

		select @new_status = @current_status | @rep_constant
		select @new_status2 = @current_mode & ~@owner_bit
		select @rep_on_schema = 1
		select @setrep_flags = @setrep_repl
	end
	else
	begin
		/* We are setting owner mode to ON */
		select @new_status = @current_status | @rep_constant
		select @new_status2 = @current_mode | @owner_bit
		select @rep_on_schema = 1
		select @setrep_flags = @setrep_repl
	end

	/* Check if we want to use indexes for replication */
	if @use_index is not null
	begin
		select @new_status2 = @new_status2 | @index_bit
	end
end

/*
** Update the object's sysstat column
**
** IMPORTANT: This transaction name is significant and is used by
**            Replication Server
*/
begin transaction rs_logexec
	
	/* log the schema first if we are turning off replication 
	** or if we repdefmode has ower_mode on, or if standby replication
        ** server is running.
	*/
	if ((@rep_off_schema = 1) or (@repdefmode = @owner_on)
		or (@reptostandbyon = 1))
	begin
		select @after_image = 0
		select @mod_versionts = 1
		if (logschema(@objid, @user_tran, @after_image, 
				@mod_versionts) != 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'." 
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name
	
			rollback transaction
			return(1)
		end
	end

	/* 
	** Update the column bits for text/image/off-row-object columns 
	*/
	if (@setrep_flags = @setrep_repl)
	begin
                update syscolumns
                set status = status | @colrepalwys,
                    status2 =
                        case
                                when status2 is null
                                and     @use_index is not null
                                        then @tipsa_in_index
                                when status2 is not null
                                and     @use_index is not null
                                        then status2 | @tipsa_in_index
				else status2
                        end
                where
                        id = @objid
                        and (type in (@imagetype, @texttype,  @unitexttype)
                             or (type = @xtype_type
                                 and (xstatus & @offrow) = @offrow) )

	end
	/* If we are turning off replication, reset status in syscolumns */
        else if (@setrep_flags = 0)
        begin
                update syscolumns
                set status = status & ~(@colrepalwys | @colrepifch),
                    status2 = status2 & ~(@tipsa_in_index)
                where
                        id = @objid
                        and (type in (@imagetype, @texttype,  @unitexttype)
                             or (type = @xtype_type
                                 and (xstatus & @offrow) = @offrow) )

        end

	/* 
	** Log the schema now if we are turning on replication and we are
	** inside a user transaction.
	*/ 
	if ((@rep_on_schema = 1) and (@user_tran = 1))
	begin
		select @after_image = 1
		select @mod_versionts = 0
		if (logschema(@objid, @user_tran, @after_image, 
				@mod_versionts) != 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'." 
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name
	
			goto clear_all
		end
	end

	/*
	** Update the object's status in cache.
	*/
	if (setrepstatus(@objid, @setrep_flags) != 1)
	begin
		/*
		** 17966 "Due to system failure, the replication status
		**	  for '%1!' has not been changed."
		*/
		raiserror 17966, @replicate_name, @setflag

		goto clear_all
	end

	/* We are turning on /off replication. Update status */
	if (@setrep_flags = @setrep_repl) or (@setrep_flags = 0)
	begin
		/* We are turning on replication */
		if (@setrep_flags = @setrep_repl)
		begin
			/* Set individual status bits in the cache */
			if ((@new_status2 & @owner_bit) != 0)
			begin
				select @retstat = setrepdefmode(@objid, 
							@setrep_owner, 1)
			end
			if (@retstat = 1) and ((@new_status2 & @index_bit) != 0)
			begin
				select @retstat = setrepdefmode(@objid, 
								@setrep_index, 1)
			end
		end
		else 
		begin
			/* 
			** We are turning off replication, remove the 
			** index status from the cache 
			*/
			select @retstat = setrepdefmode(@objid, 
							@setrep_index, 0)
			if (@retstat = 1)
			begin
				/* Remove the owner status from the cache */
				select @retstat = setrepdefmode(@objid, 
								@setrep_owner, 0)
			end
		end
		if (@retstat != 1)
		begin
			/*
			** 17966 "Due to system failure, the replication status
			**	  for '%1!' has not been changed."
			*/
			raiserror 17966, @replicate_name, @setflag

			goto clear_all
		end

		/*
		** Set status at table level
		*/
		update sysobjects set sysstat = @new_status,
				      sysstat2 = @new_status2
		where
		id = @objid
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		raiserror 17756, "sp_setreptable", @dbname
			
		goto clear_all
	end

commit transaction

/*
** 17964 "The replication status for '%1!' is set to %2!."
*/
if (@use_index is not null)
	select @use_index = ", " + @use_index

if (@setrep_flags = @setrep_never)
	select @omsg = @setflag
else
	select @omsg = @setflag + ", " + @repdefmode + @use_index

exec sp_getmessage 17964, @msg output
print @msg, @replicate_name, @omsg
return(0)

clear_all:
	rollback transaction rs_logexec
	return(1)
go
exec sp_procxmode 'sp_setreptable', 'anymode'
go
grant execute on sp_setreptable to public
go
exec sp_procxmode 'sp_setreptable', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_logiosize')
begin
	drop procedure sp_logiosize
end
go
print "Installing sp_logiosize"
go

/* Stored procedure for setting the log I/O size. */

/*
** Messages for sp_logiosize
**
** 17260, "Can't run %1! from with in a transaction."
** 17289, "Set your curwrite to the hurdle of current database."
** 18126, "Log I/O size must be a power of 2, and is between a 
**         logical pagesize to size of 8 logical pages. For example,
**         if the logical pagesize is %1!K, the log I/O size should be
**         %2!, %3!, %4!, or %5![k|K]."
** 18127, "You must have System Administrator (SA) role to 
**	   execute this stored procedure." 
** 18128, "Unable to change the log I/O size. The memory pool 
**	   for the specified log I/O size does not exist." 
** 18129, "Log I/O size is set to %1! Kbytes."
** 18130, "sp_logiosize failed.  Please contact Sybase Technical 
**	   Support to help you resolve the problem."
** 18131, "Log I/O Size value '%1!' is illegal."
** 18132, "The transaction log for database '%1!' will use I/O size of %2! 
**	   Kbytes."
** 19979, "Cannot run '%1!' for in-memory database '%2!'."
*/

/*
** Syntax:
**
** sp_logiosize ["default" | "size" | "<size>[k|K]" | "all"]
** 
** Internal variables used:
**
**	@old_value - The log I/O size from the sysattributes if it exists.
**	@new_value - The log I/O size specified through sp_logiosize.
**	@use_value - The log I/O size server would use based on available
**		     resources.
**	@action	   - Denotes add, change, drop or fetch an I/O size value.
**
**	Handle the following 3 cases for @new_value
**		case NULL
**		case @new_value > 0
**		case @new_value = "default"
*/

create procedure sp_logiosize
@size		varchar(30) = NULL
as
declare	@new_value	int
	, @objid	int
	, @old_value	int
	, @action	int 
	, @use_value	int
	, @tempiosize	int
	, @retstat	int
	, @row_count	int
	, @cstat	int
	, @unit_loc 	int
	, @size_len	int
	, @logicalpgsz1 int
	, @logicalpgsz2 int
	, @logicalpgsz3 int
	, @logicalpgsz4 int
	, @msg          varchar(1024)
	, @tempstr	varchar(30)
	, @dbname	varchar(255)
	, @name         varchar(255)/* cache name from sysconfigures */
	, @imdbstat	int
	, @adbstat	int
	, @status3	int
	, @status4	int

/* 
** Extract the I/O size value from the input.
*/
select @tempstr = lower(ltrim(rtrim(@size)))

if @tempstr is NULL
begin
	select @new_value =  NULL
end
else
begin
   
        /* 
	** Check whether the input value has correct unit k or K.
        ** Parse the input string.
	*/
	select @unit_loc = patindex("%[kK]%", @size)

	/* If the unit is specified, check if it is the last char
        ** in the string, input like "2kk" should raise an error.
        ** If the input is correct, grap the digit string and put
        ** it into @tempstr.
        */ 
	if @unit_loc != 0
	begin
		select @size_len = char_length(@size)
		if @size_len = @unit_loc
		begin
			select @tempstr = substring(@size, 1, @unit_loc -1)
		end

		/* 
                ** 18131, "Log I/O Size value '%1!' is illegal."
                */
		else
		begin
			raiserror 18131, @size
			return(1)
		end
	end

	/* Check whether the input value is an integer */
	if @tempstr like "[0-9]%"
	begin
		select @new_value = convert(int , @tempstr)
		/* 
		** Make sure the log I/O size is a power of 2 and is 
		** between a logical pagesize to size of 8 logical pages.
		*/

		select @tempiosize = 2
		while @tempiosize < @new_value
			select @tempiosize = @tempiosize * 2
		if @tempiosize != @new_value
			or @tempiosize > 8 * @@maxpagesize / 1024
			or @tempiosize < @@maxpagesize / 1024
		begin
			/* 18126, "Log I/O size must be a power of 2, and is
                        ** between a logical pagesize to size of 8 logical 
                        ** pages. For example, if the logical pagesize is
                        ** %1!K, the log I/O size should be %2!, %3!, %4!,
                        ** or %5![k|K]." 
                        */
			select @logicalpgsz1 = @@maxpagesize / 1024
			select @logicalpgsz2 = 2 * @logicalpgsz1
			select @logicalpgsz3 = 4 * @logicalpgsz1
                        select @logicalpgsz4 = 8 * @logicalpgsz1
			raiserror 18126, @logicalpgsz1, @logicalpgsz1,
				@logicalpgsz2, @logicalpgsz3, @logicalpgsz4
			return(1)
		end
	end
	else
	/* Process the value as a character string */
	begin
		/* Check whether the input value is "default" */
		if @tempstr = "default"
		begin
			select @new_value = 0
		end
		else if @tempstr = "all"
		begin
			/* 
			** There is no sanctity about this value. We just
			** want to differentiate this value from other
			** valid values. This indicates that user wants
			** log I/O size listing for all data bases.
			*/
			select @new_value = 99
		end
		else
		begin
			/* 
                        ** 18131, "Log I/O Size value '%1!' is illegal." 
                        */
			raiserror 18131, @size
			return(1)
		end
	end
end

/*
** Don't allow this in a transaction because we can't undo what 
** we have done through the attr_notify() built-in.
*/
if @@trancount >0
begin
	/*
	** 17260, "Can't run %1! from with in a transaction."
	*/				
	raiserror 17260, "sp_logiosize"
	return(1)
end
else
begin
	set transaction isolation level 1
	set chained off
end

select @objid = object_id("syslogs")
select @dbname = db_name()
select @use_value = 0

/* 
** If the input value is NULL, print the log I/O size set for the current
** database.
*/
if @new_value is NULL
begin
	/* 
	** Print the log I/O size set for the current database 
	*/
	select @action = 4 /* Denotes fetching a value */
	select @use_value = attrib_notify(2,0,"T",@objid,NULL,NULL,
					NULL,NULL,@new_value,NULL,NULL,
					NULL,NULL,@action)
end
else if @new_value = 99
begin
	/* List log I/O size values for all the data bases */
	select name into #syscacheconfig from master.dbo.sysconfigures
		where parent = 19 and config = 19	

	/*
	**  Find out the number of rows we want to look at.
	*/
	select @row_count = count(*) from #syscacheconfig
	
	declare logiosize_cursor cursor
	for select name from #syscacheconfig
 
	open logiosize_cursor

	while (@row_count > 0)
	begin
		fetch logiosize_cursor into @name
		print "Cache name: %1!", @name
		print "Data base                       Log I/O Size" 
		print "------------------------------  ------------"
		select @cstat = config_admin(9, 4, 0, 0, NULL, @name)
		print " "
		select @row_count = @row_count - 1
	end

	close logiosize_cursor
	return(0)
end
/* 
** Process other input values.  Look for a matching row in the 
** sysattributes table for the Log I/O Size attribute.
*/
else
begin

	select @status4 = status4, @status3 = status3 
	from master..sysdatabases
	where dbid = db_id()

	/* Don't let sp_logiosize to be run on an in-memory database. */
	select @imdbstat = number from master..spt_values
	where name = "in-memory database" and type="D4"

	if (@status4 & @imdbstat != 0)
	begin
		raiserror 19979, "sp_logiosize", @dbname
		return (1)
	end

	select @adbstat=number from master.dbo.spt_values
	where name="archive database" and type="D3"
	
	/* Do not allow sp_logiosize to be run on an archive database. */
	if (@status3 & @adbstat != 0)
	begin
		/* Cannot run '%1!' on an archive database." */
		raiserror 19424, "sp_logiosize"
		return (1)
	end

	/* 
	** Check if user has "sa" role. proc_role() also does auditing 
	** if required.  proc_role() will also print error message if 
	** required.
	*/
	if (proc_role("sa_role") = 0)
	begin
		/*
		** 18127, "You must have System Administrator (SA) role 
		** to execute this stored procedure." 
		*/
		raiserror 18127
		return(1)
	end

	select @old_value = int_value  from sysattributes 
			where 	class 		= 2 	and
				attribute 	= 0 	and
				object 		= @objid

	/* We found a matching entry in sysattributes */

	if @old_value != 0 and @old_value is not NULL
	begin 
		if @new_value > 0
		begin
		
			select @action = 2 /* Denotes a change */

			/* If the previous Log I/O Size value is same as the 
			** requested value do not do any thing. Otherwise update
			** the value.
			*/
		
			if @new_value = @old_value
			begin
				select @use_value = @old_value
			end
			else
			begin
				select @use_value = attrib_notify(2,0,"T",
					@objid,NULL,NULL,NULL,NULL,@new_value,
					NULL,NULL,NULL,NULL,@action)
				if @use_value = @new_value
				begin
					update sysattributes 
					set int_value = @new_value 
					where 	class 	= 2 	and
					attribute 	= 0 	and
					object 		= @objid
				end
			end
		end

		if @new_value = 0	/* Handles "default" value */
		begin
			select @action = 3 /* Denotes a drop */
			select @use_value = attrib_notify(2,0,"T",
				@objid,NULL,NULL,NULL,NULL,@new_value,NULL, 
				NULL,NULL,NULL,@action)
			/* Delete the entry from sysattributes */
			delete sysattributes 
			where 	class 	= 2 	and
			attribute 	= 0 	and
			object 		= @objid
		end

	end

	else

	/* There are no entries in the sysattributes table. */
	begin
		/* We did not find a matching entry.  So insert a new entry */
		if @new_value > 0 
		begin
			/* 
			** First check whether specified buffer pool exists.
			** It it does, then insert the row.
			*/
		
			select @action = 1 /* Denotes an addition of a row */
			select @use_value = attrib_notify(2,0,"T",
				@objid,NULL,NULL,NULL,NULL,@new_value,NULL,
				NULL,NULL,NULL,@action)
			if @use_value = @new_value
			begin
				/* Insert an entry in sysattributes */
				insert sysattributes(class, attribute, 
					object_type, object, int_value)
					values(2, 0, 'T', @objid, @new_value)
			end
		end

		if @new_value = 0 	/* Handles "default" value */
		begin
			/* 
			** The action taken is same as @action = 3 above
			** except we dont have any row to delete.
			*/
			select @action = 3 
			select @use_value = attrib_notify(2,0,"T",
				@objid,NULL,NULL,NULL,NULL,@new_value,NULL,
				NULL,NULL,NULL,@action)
		end
	end
end

/* 
** Process the return values from the attrib_notify built-in function.
** @use_value = 0 denotes that sysattributes notification has failed.
*/

if (@use_value = 0)
begin
	/*
	** 18130, "sp_logiosize failed.  Please contact Sybase 
	** Technical Support to help you resolve the problem."
	*/
	raiserror 18130
	return(1)
end 

/*
** @action = 1  Qualified for an addition of row in sysattributes 
** @action = 2  Qualified for a change of row in sysattributes 
** @action = 3  Qualified for a deletion of row in sysattributes 
** @action = 4  Fetched a log I/O size value 
*/

if (@action = 1) or (@action = 2)
begin
	if @use_value = @new_value
	begin
		/*
		** 18129, "Log I/O size is set to %1! Kbytes."
		** 18132, "The transaction log for database '%1!' will use 
		** 	   I/O size of %2! Kbytes."
		*/
		exec sp_getmessage 18129, @msg output
		print @msg, @new_value
		exec sp_getmessage 18132, @msg output
		print @msg, @dbname, @use_value
	end
	else
	begin
		/*
		** 18128, "Unable to change the log I/O size. 
		** The buffer pool for the specified log I/O size 
		** does not exist." 
		*/
		raiserror 18128
		return (1)
	end
end
else if (@action = 3)
begin
	/*
	** 18132, "The transaction log for database '%1!' will use 
	**         I/O size of %2! Kbytes."
	*/
	exec sp_getmessage 18132, @msg output
	print @msg, @dbname, @use_value
end
else if (@action = 4)
begin
	/*
	** 18129, "Log I/O size is set to %1! Kbytes."
	*/
	if @old_value != 0 and @old_value is not NULL
	begin
		/*
		** 18129, "Log I/O size is set to %1! Kbytes."
		*/
		exec sp_getmessage 18129, @msg output
		print @msg, @old_value
	end
	/*
	** 18132, "The transaction log for database '%1!' will use 
	**         I/O size of %2! Kbytes."
	*/
	exec sp_getmessage 18132, @msg output
	print @msg, @dbname, @use_value
end
else /* sp_logiosize failed */
begin
	/*
	** 18130, "sp_logiosize failed.  Please contact Sybase 
	** Technical Support to help you resolve the problem."
	*/
	raiserror 18130
	return (1)
end 
go
exec sp_procxmode 'sp_logiosize', 'anymode'
go
grant execute on sp_logiosize to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sqlrep_check_syntax')
begin
	drop procedure sp_sqlrep_check_syntax
end
go
print "Installing sp_sqlrep_check_syntax"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setrepdefmode')
begin
	drop procedure sp_setrepdefmode
end
go
print "Installing sp_setrepdefmode"
go

if exists (select name from sysobjects
		where sysstat & 7 = 4
		and name = 'sp_sqlrep_check_syntax')
	drop procedure sp_sqlrep_check_syntax
go

/*
** sp_sqlrep_check_syntax checks that @parameter is a valid substring
** of @sqlrep.
**
** It returns 1 if it is, and 0 if it is not.
**
** For example, if @sqlrep = 'udis', then a valid substring of @sqlrep
** is a string in which only characters 'u', 'd', 'i' or 's' may appear.
** They may appear exactly 0 or 1 time.
**
** 'ud' is a valid substring, so is 'si'.
** 'uu' is not and neither ' ', nor 'uais' are.
*/
create procedure sp_sqlrep_check_syntax
@parameter	varchar(20) = NULL,	/* parameter to be checked */ 
@sqlrep		varchar(4) = NULL,	/* 'udis' or 'udi' */
@syntax_ok	int output		/* 1 if ok, 0 otherwise */
as
begin
	declare @c		char(1)
	declare	@update		char(1)
	declare	@delete		char(1)
	declare	@inserts	char(1)
	declare	@selinto	char(1)
	declare	@sqlrep_length	int
	declare @param_count	int
	declare @num_update	int
	declare @num_delete	int
	declare @num_inserts	int
	declare @num_selinto	int

	select @sqlrep_length = datalength(@sqlrep)
	select @syntax_ok = 1

	/*
	** If displaying mode only, syntax is OK;
	** just return.
	*/
	if (@parameter is NULL)
		return
		
	select @parameter = ltrim(@parameter)
	select @parameter = rtrim(@parameter)

	/*
	** Expedite obviously invalid conditions.
	** Single out NULL value for @parameter
	** because the NULL value would pass the
	** other tests below.
	 */
	if (datalength(@parameter) > @sqlrep_length) or
		(@parameter is NULL) or
		@sqlrep is NULL
	begin
		select @syntax_ok = 0
	end
	else
	begin
		select @update = substring(@sqlrep,1,1)
		select @delete = substring(@sqlrep,2,1)
		select @inserts = substring(@sqlrep,3,1)

		/*
		** @selinto is NULL if the @sqlrep string
		** is 'udi'.
		** It is 's' if the @sqlrep string is 'udis'.
		*/
		select @selinto = substring(@sqlrep,4,1)

		select @num_update = 0
		select @num_delete = 0
		select @num_inserts = 0
		select @num_selinto = 0

		select @param_count = 1 
		while (@param_count < datalength(@parameter) + 1)
		begin
			select @c = substring(@parameter,@param_count,1)
			if (@c = @update)
			begin
				select @num_update = @num_update + 1
				if (@num_update > 1)
				begin
					select @syntax_ok = 0
					break
				end
			end
			else
			if (@c = @delete)
			begin
				select @num_delete = @num_delete + 1
				if (@num_delete > 1)
				begin
					select @syntax_ok = 0
					break
				end
			end
			else
			if (@c = @inserts)
			begin
				select @num_inserts = @num_inserts + 1
				if (@num_inserts > 1)
				begin
					select @syntax_ok = 0
					break
				end
			end
			else
			if (@c = @selinto)
			begin
				select @num_selinto = @num_selinto + 1
				if (@num_selinto > 1)
				begin
					select @syntax_ok = 0
					break
				end
			end
			else
			begin
				select @syntax_ok = 0
				break
			end
			select @param_count = @param_count + 1
		end
	end
return(0)
end
go

/*
** Messages for "sp_setrepdefmode"	
**
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) or
**	   a user with REPLICATION authorization may execute this stored
**	   procedure."
** 18101, "Table must be in the current database."
** 18102, "Table '%1!' does not exist in this database."
** 18110, "The table '%1!' is not marked for replication."
** 18409, "The built-in function '%1!' failed. Please see any other messages printed along with this message."
** 18537, "Usage: sp_setrepdefmode table_name, {owner_on | owner_off}
** 18538, "owner_on"
** 18539, "owner_off"
** 18540, "The replication definition mode for '%1!' is already set to
**	   '%2!'. Replication definition mode for '%3!' does not change."
** 18541, "An object with the same name but owned by a different user is
**	   already being replicated with the replication definition mode
**	   'owner_off'. The replication definition mode for '%1!' is not
**	   changed."
** 18542, "Failed to change the replication definition mode for '%1!'
**	   because of an internal error."
** 18543, "The replication definition mode for '%1!' is set to '%2!'."
*/
create procedure sp_setrepdefmode
@replicate_name	varchar(767) = NULL,	/* obj we want to mark as replicate */
@setflag 	varchar(10) = NULL,	/* set or unset the replicate status. */
@setmode	varchar(10) = NULL
as

declare @is_replicated	smallint /* The object is marked for replication */
declare @current_status	int /* current sysstat value for the object. */
declare @new_status	int /* new sysstat value for the object. */
declare @rep_constant 	smallint /* bit which indicates a replicated object. */
declare @setrep_owner	int	 /* bit indicating the owner bit */
declare @setrep_never	int	 /* bit indicating the rep status 'never' */
declare @owner_bit	smallint
declare @db		varchar(255) 	/* db of object. */
declare @owner		varchar(255) 	/* owner of object. */
declare @object		varchar(255)	/* object's name. */
declare @msg 		varchar(1024)
declare @tmpstr		varchar(255)	/* Use to display current status */
declare @sqlstr		varchar(20)	/* Use to display sql current status */
declare @sptlang	int
declare @procval	int
declare @objid		int
declare @mode		int
declare @flagval	int
declare @dbname varchar(255)
declare @user_tran      int	/* are we inside a user tran? */
declare @after_image    int	/* log the after image of the schema */
declare @mod_versionts  int	/* modify version timestamp after logging
				** the schema
				*/
declare @owner_syntax  smallint /* Use to check stored proc syntax */
declare @sqlrep_syntax smallint /* Use to check stored proc syntax */
declare @threshold_syntax smallint /* Use to check strored proc syntax */
declare @sqlrep_mask	int	/* Holds the mask of bits for sql rep. */
declare @set		int
declare	@c1		char(1)
declare	@c2		char(1)
declare	@c3		char(1)

/* Following variables hold constant strings retrieved from spt_values */
declare @owner_on	varchar(10)
declare @owner_off	varchar(10)
declare	@update		char(1)
declare	@delete		char(1)
declare	@inserts	char(1)
declare @on		char(2)
declare @off		char(3)
declare @never		char(5)
declare @sqlrep		varchar(4)

/* Sql replication log threshold management */ 
declare @threshold	char(9)	
declare @threshold_value int
declare @current_threshold int
declare @threshold_max	int
declare @outvalue	varchar(10)	
declare @outvalue1	varchar(10)	

if @@trancount = 0
begin
	set transaction isolation level 1
	set chained off
end

if (@@trancount > 0)
	select @user_tran = 1
else
	select @user_tran = 0
 
/*
** Replication enabled flag is 8000H (which is -32768D)
*/
select @rep_constant = -32768,  /* 0x8000 in sysstat  */
       @owner_bit = 4096,   	/* 0x1000 in sysstat2 */
       @setrep_owner = 16,	/* LT_SETREP_OWNER */
       @setrep_never = 1024	/* LT_REP_NEVER */


/*
** Initialize constant strings.
*/
select @sqlrep = name 
	from master.dbo.spt_values
	where type = 'SQ'
	and number = 1

select @sqlrep = substring(@sqlrep,1,3)
select @update = substring(@sqlrep,1,1)
select @delete = substring(@sqlrep,2,1)
select @inserts = substring(@sqlrep,3,1)

exec sp_getmessage 18538, @owner_on out
exec sp_getmessage 18539, @owner_off out
exec sp_getmessage 19895, @off out
exec sp_getmessage 19896, @never out
exec sp_getmessage 19897, @on out
exec sp_getmessage 19931, @threshold out

/* Create the temporary table for printing the values */
create table #repdefmode(val int, str varchar(10))

insert #repdefmode values (0, @owner_off)
insert #repdefmode values (@owner_bit, @owner_on)
insert #repdefmode values (32, @update)	 /* LT_SQLREP_UPD */
insert #repdefmode values (64, @delete)	 /* LT_SQLREP_DEL */
insert #repdefmode values (128, @inserts)/* LT_SQLREP_INSSEL */
insert #repdefmode values (512, @never)  /* LT_SQLREP_NEVER */

select @threshold_max = 10000	/* LT_SQLREP_MAX_THRESHOLD */
select @sqlrep_mask = (32|64|128|512)

/*
** Set 'sptlang' for proper printing of object information.  Used mainly
** for the 'select' statement which is executed when we are invoked with
** no parameters.  Copied from similar code in 'sp_help'
*/
select @sptlang = @@langid
if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	    select @sptlang = 0
end

/*
** If we are invoked with no parameters or fewer than two parameters,
** print the usage message. 
*/
if (@replicate_name is null)
begin
	/*
	** 18537 "Usage: sp_setrepdefmode table_name 
	**	  [, owner_on | owner_off | 'udi' [, 'on' | 'off' | 'never']
	**		| 'threshold' [, value]]"
	*/
	raiserror 18537
	return (1)
end

/*
** Crack the name into its corresponding pieces.
*/
execute sp_namecrack 	@replicate_name, 
			@db = @db output, 
			@owner = @owner output,
			@object = @object output

/*
** Make sure that the object is in the current database.
*/
if (@db is not NULL and @db != db_name())
begin
	/*
	** 18101, "Table must be in the current database."
	*/
        raiserror 18101
	return (1)
end

/*
**  Make sure that the object actually exists.
*/
select @objid = object_id(@replicate_name)

if (@objid is NULL) or
	(not exists (select name from sysobjects where 
		id = @objid and
		type = "U"
		))
begin
	/*
	** 18102, "Table '%1!' does not exist in this database."
	*/
	raiserror 18102, @replicate_name
	return (1)
end

/*
** You must be SA, dbo or have REPLICATION role to execute this
** sproc.
*/
if (user_id() != 1)
begin
	if (charindex("sa_role", show_role()) = 0 and 
	    charindex("replication_role", show_role()) = 0)
	begin
		/*
		** 18418, "Only the System Administrator (SA), the
		**	   Database Owner (dbo) or a user with REPLICATION
		**	   authorization may execute this stored
		**	   procedure."
		*/
		raiserror 18418
		return (1)
	end
	else
	begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
	end
end

/* Initialize variables to control correct syntax */
select @owner_syntax = 0,
       @sqlrep_syntax = 0,
       @threshold_syntax = 0

select @setflag = lower(@setflag)

/*
** We check whether @setflag is a valid
** 'udi' substring. If it is, then
** we know that we are dealing with a sqlrep 
** mode setting command. @sqlrep_syntax will
** then be set to 1, and to 0 otherwise.
*/
exec sp_sqlrep_check_syntax @setflag,
			@sqlrep,
			@sqlrep_syntax output

/*
** Check whether the table is marked to be never replicated 
** regardless of the database replication setting.
** In that case, no replication setting may be changed.
*/
select @current_status = getrepdefmode(@objid)
if (@current_status < 0)
begin
	/*
	** 18409, "The built-in function '%1!' failed. Please see any 
	** other messages printed along with this message."
	*/
	raiserror 18409, "getrepdefmode"
	return (1)
end
if ((@current_status & @setrep_never) != 0)
begin
	/*
	** 17965 "The replication status for '%1!' is currently %2!."
	*/
	raiserror 17965, @replicate_name, @never
	return (1)
end

/*
** Check whether the table is explicitely marked for replication.
*/
if (exists 
	(select * from sysobjects
	 where
		id = @objid
		and (sysstat & @rep_constant) = @rep_constant
		and type = "U"))
begin
	select @is_replicated = 1
end
else
begin
	select @is_replicated = 0
end

/*
** We solely display setrepdefmode status in the
** following cases:
**
**	1. 'sp_setrepdefmode <table name>'
**
**	2. 'sp_setrepdefmode <table name>, <string>'
**
**	3. 'sp_setrepdefmode <table name>, 'threshold'
**
*/
if ((@setflag is null) or
    (@setmode is null and @sqlrep_syntax = 1) or
    (@setmode is null and @setflag = @threshold))
begin
	/*
	** Display the replication status only when the table 
	** is marked for replication.
	*/
	if (@is_replicated = 1)
	begin
		select @current_status = getrepdefmode(@objid)
		if (@current_status < 0)
		begin
			/*
			** 18409, "The built-in funtion '%1!' failed. 
			** Please see any other messages printed along 
			** with this message."
			*/
			raiserror 18409, "getrepdefmode"
			return (1)
		end
		select @tmpstr = ""
		select @sqlstr = ""
		if ((@current_status & @setrep_owner) != 0)
			select @tmpstr = @tmpstr + @owner_on
		else
			select @tmpstr = @tmpstr + @owner_off
	
		/* Build the string with the sql rep status */
		select @mode = val 
		from #repdefmode where str = @update
		if ((@current_status & @mode) != 0)
			select @sqlstr = @sqlstr +  @update 

		select @mode = val 
		from #repdefmode where str = @delete
		if ((@current_status & @mode) != 0)
			select @sqlstr = @sqlstr + @delete

		select @mode = val 
		from #repdefmode where str = @inserts
		if ((@current_status & @mode) != 0)
			select @sqlstr = @sqlstr + @inserts

		select @mode = val 
		from #repdefmode where str = @never
		if ((@current_status & @mode) != 0)
			select @sqlstr = @sqlstr + @never 

		/* Get rid of empty string if necessary */
		select @sqlstr = ltrim(@sqlstr)

		if (datalength(@sqlstr) > 0)
			select @tmpstr = @tmpstr + ", '" + @sqlstr + "'"

		/*
		** 17965 "The replication status for '%1!' is currently %2!."
		*/
		exec sp_getmessage 17965, @msg output
		print @msg, @replicate_name, @tmpstr
	end

	/* Get the current replication threshold */
	select @current_threshold = getrepthreshold(@objid)

	if (@current_threshold < 0)
	begin
       		/*
	       	** "The built-in function getrepthreshold() failed.
		** Please see any other messages printed along with
		** this message."
		*/
		raiserror 18409, "getrepthreshold"
		return (1)
	end

	/* Check first if there is not a threshold defined */
	if (@current_threshold = 0)
	begin
		/*
		** 19949, "There is no replication threshold defined
		**	   for '%1!'."
		*/
		exec sp_getmessage 19949, @msg output
		print @msg, @replicate_name
		return(0)
	end

	/*
	** 19932, "The replication threshold for table '%1!' is '%2!'." 
	*/
	exec sp_getmessage 19932, @msg output
	select @outvalue = convert(varchar(10), @current_threshold)
	print @msg, @replicate_name, @outvalue 

	return (0)
end

select @setflag = ltrim(rtrim(@setflag))

/*
** If the table is not marked for replication, 
** then only a threshold operation is allowed.
*/
if ((@is_replicated = 0) and (@setflag != @threshold))
begin
	/*
	** 18110, "The table '%1!' is not marked for replication."
	*/
	raiserror 18110, @replicate_name
	return(1)
end

/* check for valid threshold syntax.  */
if (@setflag = @threshold)
begin
	select @threshold_syntax = 1
end

/* Check for valid owner mode syntax.  */
else if (@setflag in (@owner_on, @owner_off))
begin
	select @owner_syntax = 1
end

/* Check for a valid sql replication syntax */
else
begin
	/*
	** Remember we have checked above whether @setflag
	** is a valid substring of 'udi'. If it is, then
	** @sqlrep_syntax has been set to 1, and we need
	** to check that @setmode is also correct. If 
	** @setflag is not a valid substring of 'udi',
	** then @sqlrep_syntax is already 0.
	*/
	if (@setmode is not null)
	begin
		if (lower(@setmode) not in (@on, @off, @never))
		begin
			select @sqlrep_syntax = 0
		end
		else if (lower(@setmode) in (@on, @never))
		begin
			select @set = 1
		end
		else if (lower(@setmode) in (@off))
		begin
			select @set = 0
		end
	end
	else
	begin
		select @sqlrep_syntax = 0
	end
end

/* The current syntax is invalid */
if (@owner_syntax = 0) and (@sqlrep_syntax = 0) and (@threshold_syntax = 0)
begin
	/*
	** 18537 "Usage: sp_setrepdefmode table_name 
	**	  [, owner_on | owner_off | 'udi' [, 'on' | 'off' | 'never']
	**		| 'threshold' [, 'value']]"
	*/
	raiserror 18537
	return (1)
end

/* We are changing the owner status */
if (@owner_syntax = 1)
begin
	/* Get the object's current status.  */
	select @current_status = getrepdefmode(@objid)

	/*
	** Set the mode we want to change. For now only owner mode can be set.
	*/
	select @mode = @setrep_owner

	/*
	** Perform the requested operation on the object.
	*/
	if @setflag in (@owner_on, "owner_on")
	begin
		if (@current_status & @setrep_owner) = @setrep_owner
		begin
			/*
			** 18540: "The replication definition mode for '%1!' is
			**	   already set to '%2!'. Replication definition mode
			**	   for '%3!' does not change."
			*/
			raiserror 18540, @replicate_name, @setflag, @replicate_name
			return(1)
		end
		/* Set the action */
		select @set = 1
	end
	else
	begin

		/*
		** Make sure that no like object with the same name, but a
		** different owner, exists.  We need to do this because
		** the SQL Server does not send owner information along
		** with the object to the Replication Server.  This
		** restriction may be lifted in future versions.
		*/
		if exists (select * from sysobjects
				where name = @object
				and (
					(type = "U ") /* user table */
				or
					(type = "P ") /* stored procedure */
				)
				and (sysstat & @rep_constant) != 0
				and (sysstat2 & @owner_bit) = 0)
		begin
			/*
			** 18541, "An object with the same name but owned by a
			**	   different user is already being replicated
			**	   with the replication definition mode 'owner_off'.
			**	   The replication definition mode for '%1!' is not
			**	   changed."
			*/
			raiserror 18541, @replicate_name
			return(1)
		end

		/* 
		** We are attempting to remove the owner status but it is
		** not set.
		*/
		if ((@current_status & @setrep_owner) = 0)
		begin
			/*
			** 18540: "The replication definition mode for '%1!' is
			**	   already set to '%2!'. Replication definition mode
			**	   for '%3!' does not change."
			*/
			raiserror 18540, @replicate_name, @setflag, @replicate_name
			return(1)
		end

		/* Set the action */
		select @set = 0
	end

	/*
	** Update the object's sysstat column
	**
	** IMPORTANT: The name "rs_logexec is significant and is used by 
	**            Replication Server
	*/
	begin transaction rs_logexec

		/* log the schema first before we update sysobjects */
		select @after_image = 0
		select @mod_versionts = 1
		if (logschema(@objid, @user_tran, @after_image, 
				@mod_versionts) != 1)
		begin
			/*
			** 17968 "The built-in function logschema() failed 
			** for '%1!'." 
			*/
			exec sp_getmessage 17968, @msg output
			print @msg, @replicate_name

			rollback transaction
			return(1)
		end
	 
		/* 
		** Hold a read lock so that the status cannot be
		** changed till we have done.
		*/
		select @current_status = sysstat2
		from sysobjects holdlock
		where id = @objid

		/* Determine the new status depending on the setting */
		if (@set = 0)
		begin
			select @new_status = @current_status & ~@owner_bit
		end
		else 
		if (@set = 1)
		begin
			select @new_status = @current_status | @owner_bit
		end

		/* Set the new status */
		update sysobjects set sysstat2 = @new_status
		where
			id = @objid

		/* log the schema with the after image if we were in a user
		** transaction 
		*/
		if (@user_tran = 1)
		begin
			select @after_image = 1
			select @mod_versionts = 0
			if (logschema(@objid, @user_tran, @after_image, 
					@mod_versionts) != 1)
			begin
				/*
				** 17968 "The built-in function logschema() failed 
				** for '%1!'." 
				*/
				exec sp_getmessage 17968, @msg output
				print @msg, @replicate_name
		
				rollback transaction
				return(1)
			end
		end
	 
		/*
		** Update the object's status in cache.
		*/
		if (setrepdefmode(@objid, @mode, @set) != 1)
		begin
			/*
			** 18542 "Failed to change the replication definition
			**	  mode for '%1!' because of an internal error."
			*/
			raiserror 18542, @replicate_name

			rollback transaction

			return (1)
		end

		/*
		** Write the log record to replicate this invocation 
		** of the stored procedure.
		*/
		if (logexec() != 1)
		begin
			/*
			** 17756, "The execution of the stored procedure
			**         '%1!' in database '%2!' was aborted
			**	    because there was an error in writing
			**	    the replication log record."
			*/
			select @dbname = db_name()
			raiserror 17756, "sp_setrepdefmode", @dbname
		
			rollback transaction rs_logexec
			return(1)
		end

	commit transaction
	/*
	** 18543 ""The replication definition mode for '%1!' is set to '%2!'."
	*/
	exec sp_getmessage 18543, @msg output
	print @msg, @replicate_name, @setflag
	return(0)
end
else /* We are changing the sql replication status */
if (@sqlrep_syntax = 1)
begin
	if (@setmode = @never)
	begin
		select @mode = val
		from   #repdefmode
		where	str = @never
	end
	else
	begin
		select @mode = 0
		select @c1 = substring(@setflag,1,1)
		select @c2 = substring(@setflag,2,1)
		select @c3 = substring(@setflag,3,1)

		select @mode = @mode | val 
		from   #repdefmode
		where str = @c1 and @c1 is not null

		select @mode = @mode | val 
		from   #repdefmode
		where str = @c2 and @c2 is not null

		select @mode = @mode | val 
		from   #repdefmode
		where str = @c3 and @c3 is not null
	end
	
	/* Get the current sql statement setting */
	select @current_status = getrepdefmode(@objid)

	/* 
	** If we are attempting to set but we have already the status
	** just return.
	*/
	if ((@mode = (@current_status & @sqlrep_mask)) and (@set = 1))
	begin
		/*
		** 18540: "The replication definition mode for '%1!' is
		**	   already set to '%2!'. Replication definition mode
		**	   for '%3!' does not change."
		*/
		exec sp_getmessage 18540, @msg output
		if(@setmode = @never)
			print @msg, @replicate_name, @setmode, @replicate_name
		else
			print @msg, @replicate_name, @setflag, @replicate_name
		return(0)
	end

	/*
	** IMPORTANT: The name "rs_logexec is significant and is used by 
	**            Replication Server
	*/
	begin transaction rs_logexec

	if (setrepdefmode(@objid, @mode, @set) != 1)
	begin
		/*
		** 18542 "Failed to change the replication definition
		**	  mode for '%1!' because of an internal error."
		*/
		raiserror 18542, @replicate_name

		rollback transaction

		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure
		**         '%1!' in database '%2!' was aborted
		**	    because there was an error in writing
		**	    the replication log record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_setrepdefmode", @dbname
	
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction
	/*
	** 18543 ""The replication definition mode for '%1!' is set to '%2!'."
	*/
	exec sp_getmessage 18543, @msg output
	if (@setmode = @never) or (@set = 0)
		print @msg, @replicate_name, @setmode
	else
		print @msg, @replicate_name, @setflag
	return(0)
end
else
/*  We are changing the sql replication log threshold */
if (@threshold_syntax = 1) 
begin
	if (@setmode is null)
	begin
		/* Get the current replication threshold */
		select @current_threshold = getrepthreshold(@objid)

		if (@current_threshold < 0)
		begin
       			/*
	        	** "The built-in function getrepthreshold() failed.
			** Please see any other messages printed along with
			** this message."
			*/
			raiserror 18409, "getrepthreshold"
			return (1)
		end

		/*
		** 19932, "The replication threshold for table '%1!'
		** is '%2!'." 
		*/
		exec sp_getmessage 19932, @msg output
		select @outvalue = convert(varchar(10), @current_threshold)
		print @msg, @replicate_name, @outvalue 
		return(0)
	end

	select @threshold_value = convert(int, @setmode)

	if ((@threshold_value < 0) or (@threshold_value > @threshold_max))
	begin
		/*
		** 19934, "The replication threshold provided for
		** 	  table '%1!' is '%2!'. Please choose a 
		** 	  threshold larger than 0 and smaller than '%3!'." 
		*/
		select @outvalue = convert(varchar(10), @threshold_value)
		select @outvalue1 = convert(varchar(10), @threshold_max)
		raiserror 19934, @replicate_name, @outvalue, @outvalue1
	end

	/* Now the threshold value exists and is legal */

	/*
	** IMPORTANT: The name "rs_logexec is significant and is used by 
	**            Replication Server
	*/
	begin transaction rs_logexec

	if (setrepthreshold(@objid, @threshold_value) != 1)
	begin
		/*
		** 18409, "The built-in funtion '%1!' failed. Please see 
		**	   any other messages printed along with this
		**         message."
		*/
		raiserror 18409, "setrepthreshold"
		return (1)

		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec() != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure
		**         '%1!' in database '%2!' was aborted
		**	    because there was an error in writing
		**	    the replication log record."
		*/
		select @dbname = db_name()
		raiserror 17756, "sp_setrepdefmode", @dbname
	
		rollback transaction rs_logexec
		return(1)
	end

	commit transaction

	/* We requested to clear the threshold */
	if (@threshold_value = 0)
	begin
		/*
		** 19948, "The replication threshold for '%1!' has been cleared"
		*/
		exec sp_getmessage 19948,  @msg output
		print @msg, @replicate_name
		return (0)
	end

	/*
	** 19932, 'The replication threshold for '%1!' is '%2!'."
	*/
	exec sp_getmessage 19932, @msg output
	select @outvalue = convert(varchar(10), @threshold_value)
	print @msg, @replicate_name, @outvalue 
	return(0)
end
go
exec sp_procxmode 'sp_sqlrep_check_syntax', 'anymode'
go
grant execute on sp_sqlrep_check_syntax to public
go
exec sp_procxmode 'sp_sqlrep_check_syntax', 'rep_current'
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_setrepdefmode', 'anymode'
go
grant execute on sp_setrepdefmode to public
go
exec sp_procxmode 'sp_setrepdefmode', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_displaylevel')
begin
	drop procedure sp_displaylevel
end
go
print "Installing sp_displaylevel"
go

/* Stored procedure for assigning config display level for a user login.
**
*/

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:16 2006 
*/
/*
** raiserror Messages for displaylevel [Total 5]
**
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
** 18150, "The login '%1!' does not exist."
** 18152, "Invalid display level. The valid values are 'basic', 'intermediate' or 'comprehensive'."
** 18388, "You must be in the master database in order to run '%1!'."
** 18409, "The built-in function '%1!' failed. Please see the other messages printed along with this message."
*/
/*
** sp_getmessage Messages for displaylevel [Total 2]
**
** 18151, "The current display level for login '%1!' is '%2!'."
** 18153, "The display level for login '%1!' has been changed to '%2!'."
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_displaylevel
@loginame	varchar(30) = NULL,	/* login name */
@level		varchar(30) = NULL	/* config display level */
as

declare @userid		int
declare @username	varchar(30)
declare @cur_level_int	int
declare @cur_level_char	varchar(20)
declare @msg 		varchar(1024)

declare @log_for_rep int
declare @db_rep_level_all int
declare @db_rep_level_none int
declare @db_rep_level_l1 int
declare @lt_rep_get_failed int

/*
** Initialize some constants
*/
select @db_rep_level_all = -1,
       @db_rep_level_none = 0,
       @db_rep_level_l1 = 1,
       @lt_rep_get_failed = -2

select @userid = NULL
select @cur_level_int = NULL

/*
** Get the replication status of the 'master' database
*/
select @log_for_rep = getdbrepstat(1) 
if (@log_for_rep = @lt_rep_get_failed)
begin
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Convert the replication status to a boolean
*/
if (@log_for_rep != @db_rep_level_none)
	select @log_for_rep = 1
else
	select @log_for_rep = 0

/*
** If we are logging this system procedure for replication, we must be in
** the 'master' database to avoid creating a multi-database transaction
** which could make recovery of the 'master' database impossible.
*/
if (@log_for_rep = 1) and (db_name() != "master")
begin
	raiserror 18388, "sp_displaylevel"
	return (1)
end

/*
** set the user login name
*/
if (@loginame is NULL)
	select @loginame = suser_name()

/*
** set the user id
*/
select @userid = suser_id(@loginame)

/*
** check for invalid @loginame
*/
if (@userid is NULL)
begin
	/*  18150, "The login '%s' does not exist." */
	raiserror 18150, @loginame
	return(1)
end

/*
** check if user has permission to change the display level
** only the user himself or user has sa role can has the permission
*/
select @username = suser_name()
if (@loginame != @username)
begin
	/* check if user has sa role, proc_role will also do auditing
	** if required. proc_role will also print error message if required.
	*/
	if (proc_role("sa_role") = 0)
		return (1)
end

/*
** if @level are NULL, just display the user config level
*/
if (@level is NULL)
begin
	/*
	** retrieve the user config level from sysattributes
	*/
	select @cur_level_int = int_value from master.dbo.sysattributes where
		class = 4 and
		attribute = 0 and
		object_type = 'L' and
		object = @userid

	if (@cur_level_int = 10)
		select @cur_level_char = "comprehensive"
	else if (@cur_level_int = 5)
		select @cur_level_char = "intermediate"
	else if (@cur_level_int = 1)
		select @cur_level_char = "basic"
	else
		select @cur_level_char = "comprehensive"

	exec sp_getmessage 18151, @msg output
	print @msg, @loginame, @cur_level_char

	return(0)
end

/*
** check if the @level is valid
** the current valid value is 'basic', 'intermediate', and 'comprehensive'.
*/
if (@level = "basic")
	select @cur_level_int = 1
else if (@level = "intermediate")
	select @cur_level_int = 5
else if (@level = "comprehensive")
	select @cur_level_int = 10
else
begin
	/*  18152, "Invalid display level. 
	**	The valid values are '1', '5' or '10'."
	*/
	raiserror 18152
	return(1)
end

if (@log_for_rep = 1)
	begin tran rs_logexec

/*
** Figure out if we need to insert or update from sysattributes. 
*/
if exists (select * from master.dbo.sysattributes where
	class = 4 and
	attribute = 0 and
	object_type = 'L' and
	object = @userid)
begin
	update master.dbo.sysattributes
		set 	int_value = @cur_level_int
		where	class = 4 and
			attribute = 0 and
			object_type = 'L' and
			object = @userid
end
else
begin
	insert into master.dbo.sysattributes 
		(class, attribute, object_type, object, int_value)
		VALUES
		(4,
		 0,
		 'L',
		 @userid,
		 @cur_level_int)
end

if (@log_for_rep = 1)
begin
	/*
	** If the 'master' database is marked for replication, the T-SQL
	** built-in 'logexec()' will log for replication the execution
	** instance of this system procedure.  Otherwise, the T-SQL
	** built-in 'logexec()' is a no-op.
	*/
	if (logexec(1) != 1)
	begin
		raiserror 17756, "sp_displaylevel", "master"

		if (@log_for_rep = 1)
			rollback tran rs_logexec
		return(1)
	end
end

if (@log_for_rep = 1)
	commit tran rs_logexec

exec sp_getmessage 18153, @msg output
print @msg, @loginame, @level

return(0)
go
exec sp_procxmode 'sp_displaylevel', 'anymode'
go
grant execute on sp_displaylevel to public
go
exec sp_procxmode 'sp_displaylevel', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setlockpromote')
begin
	drop procedure sp_setlockpromote
end
go
print "Installing sp_setlockpromote"
go

/* Stored procedure for adding or modifying lock promotion attribute. 
** Database attributes can only be modified when using Master.
*/

/*
** Messages for "sp_setlockpromote"
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17460, "Object must be in the current database."
** 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
** 18090, "The target object does not exist."
** 18158, "At least one of the parameters 'new_lwm', 'new_hwm' or 'new_pct' must be non-NULL to execute this procedure."
** 18159, "You must be in the 'master' database to add, change or drop lock promotion attribute for a user database."
** 18160, "Please specify a non-NULL value for %1, since it has not been set previously with a non-NULL value."
** 18161, "Object name parameter must be NULL for Server-wide lock promotion attributes. Using NULL instead of - %1."
** 18162, "'%1!' is a not a user table.  '%1' can be used only on user tables."
** 18163, "The 'lock promotion LWM' value %1 cannot be greater than the 'lock promotion HWM' value %2."
** 18164, "Invalid value specified for 'scope' parameter. Valid values are 'SERVER','DATABASE' or 'TABLE'."
** 18165, "The 'lock promotion!' attributes of %1 '%2' have been changed. The new values are %3."
** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
*/

create procedure sp_setlockpromote
@obj_type varchar(10),			/* page or row */
@scope varchar(10),			/* table, database or server */
@objname varchar(767) = NULL,		/* table or database name */
@new_lwm int = NULL,			/* Lock promotion lwm value */
@new_hwm int = NULL,			/* Lock promotion hwm value */
@new_pct int = NULL			/* Lock promotion pct value */
as

declare @attrib_objid int		/* object id of the table/db */
declare @object_type varchar(2)		/* object type of the table/db */
declare @attrib int			/* attrib type of the optname */
declare @use_char_value varchar(42)	/* Lock promotion attribute's char_value */
declare @msg varchar(1024)		/* message buffer */
declare @action	int			/* ADD or CHANGE attribute */
declare @ret int 			/* Return value */
declare @tab_type smallint		/* User table ? */
declare @use_lwm int
declare @use_hwm int
declare @use_pct int
declare @update_lwm int
declare @update_hwm int

select @use_lwm = NULL
select @use_hwm = NULL
select @use_pct = NULL

/* If we're in a transaction, disallow this */
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_setpglockpromote"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1

if upper(@obj_type) not in ("PAGE", "ROW")
begin
        /*
        ** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
        */
	raiserror 18338, @obj_type
        return (1)
end

if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
        /*
        ** 17460, "Object must be in the current database."
        */
	raiserror 17460
        return (1)
end

if (upper(@scope) != "DATABASE" and upper(@scope) != "SERVER"
   and upper(@scope) != "TABLE")
begin
	/*
	** 18164, "Invalid value specified for 'scope' parameter 
	** Valid values are 'SERVER','DATBASE' or 'TABLE'."
	*/
	raiserror 18164, @objname
	return (1)
end

if (@new_lwm is NULL and @new_hwm is NULL and @new_pct is NULL)
begin
	/*
	** 18158, "At least one of the parameters 'new_lwm', 'new_hwm' or 
	** 'new_pct' must be non-NULL to execute this procedure."
	*/
	raiserror 18158
	return 1
end

if upper(@obj_type) = "PAGE"
	select @attrib = 0
else
	select @attrib = 1


if (upper(@scope) = "SERVER")
begin
	if @objname is not NULL
	begin
		/*
		** 18161, "Object name parameter must be NULL for Server-wide 
		** lock promotion attributes. Using NULL instead of - %1."
		*/
		raiserror 18161, @objname
	end

	/*
	** For valid attributes we call sp_configure to set the server-wide
	** values. All 3 server-wide values cannot be set in the same tran,
	** since sp_configure cannot be invoked from within a tran.
	*/
	if upper(@obj_type) = "PAGE"
	begin
		select @use_lwm = value from master.dbo.sysconfigures
			where config=253
	
		select @use_hwm = value from master.dbo.sysconfigures
			where config=144
	end
	else
	begin
		select @use_lwm = value from master.dbo.sysconfigures
			where config=324
	
		select @use_hwm = value from master.dbo.sysconfigures
			where config=323
	end

	/* If the new_lwm is NULL, then we're not updating the LWM. */
	if @new_lwm is NULL
	begin
		select @new_lwm = @use_lwm
		select @update_lwm = 0
	end
	else
		select @update_lwm = 1

	/* If the new_hwm is NULL, then we're not updating the HWM. */
	if @new_hwm is NULL
	begin
		select @new_hwm = @use_hwm
		select @update_hwm = 0
	end
	else
		select @update_hwm = 1

	/* Validate that LWM is less than or equal to HWM. */
	if @new_lwm > @new_hwm
	begin
		/*
		** 18163, "The 'lock promotion LWM' value %1 cannot 
		** be greater than the 'lock promotion HWM' value %2."
		**
		*/
		raiserror 18163, @new_lwm, @new_hwm
		return 1
	end

	/* If the the new LWM value is greater than the existing HWM,
	** then configure the HWM value first so that we dont break
	** the validation criterion.
	*/
	if @new_lwm > @use_hwm
	begin
		if @update_hwm = 1
		begin
			if upper(@obj_type) = "PAGE"
				exec @ret = sp_configure "page lock promotion HWM", @new_hwm
			else
				exec @ret = sp_configure "row lock promotion HWM", @new_hwm

			if (@ret != 0)
				return @ret
		end

		if @update_lwm = 1
		begin
			if upper(@obj_type) = "PAGE"
				exec @ret = sp_configure "page lock promotion LWM", @new_lwm
			else
				exec @ret = sp_configure "row lock promotion LWM", @new_lwm

			if (@ret != 0)
				return @ret
		end
	end
	else /* @new_lwm <= @use_hwm */
	begin
		if @update_lwm = 1
		begin
			if upper(@obj_type) = "PAGE"
				exec @ret = sp_configure "page lock promotion LWM", @new_lwm
			else
				exec @ret = sp_configure "row lock promotion LWM", @new_lwm

			if (@ret != 0)
				return @ret
		end

		if @update_hwm = 1
		begin
			if upper(@obj_type) = "PAGE"
				exec @ret = sp_configure "page lock promotion HWM", @new_hwm
			else
				exec @ret = sp_configure "row lock promotion HWM", @new_hwm

			if (@ret != 0)
				return @ret
		end
	end

	if (@new_pct is not NULL)
	begin
		if upper(@obj_type) = "PAGE"
			exec @ret = sp_configure "page lock promotion PCT", @new_pct
		else
			exec @ret = sp_configure "row lock promotion PCT", @new_pct

		if (@ret != 0)
			return @ret
	end
	/* The server wide values have been successfully configured. */
	return(0)
end

/*
**  Only Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/

if (proc_role("sa_role") < 1)
begin
	/* "User must be System Administrator (SA) 
	** to configure lock promotion attributes. 
	*/
	return(1)
end


if (upper(@scope) = "DATABASE")
begin
	/* 
	** If we're configuring lock promotion for a database, 
	** make sure we're currently in master. 
	*/

	select @attrib_objid = db_id()
	if @attrib_objid != 1
	begin
		/*
		** 18159, "You must be in the 'master' database to add, change 
		** or drop lock promotion attribute for a user database."
		*/
		raiserror 18159
		return 1
	
	end

	/* Translate dbname to dbid. */
	select @attrib_objid = 0
	select @attrib_objid = dbid from master.dbo.sysdatabases 
			where name = @objname

	if @attrib_objid = 0
	begin
		/*
		** 17421, "No such database -- run sp_helpdb to list databases."
		*/
		raiserror 17421
		return 1
	end


	select @object_type = 'D '
end

if (upper(@scope) = "TABLE")
begin
	/* Translate objname to objid. */
	select @attrib_objid = 0
	select @attrib_objid = id , @tab_type = sysstat & 7
		from sysobjects where id = object_id(@objname)

	if @attrib_objid = 0
	begin
		/* 
		** 18090, "The target object does not exist."
		*/
		raiserror 18090
                return 1
	
	end

	if @tab_type != 3
	begin
		/*
		** 18162, "'%1!' is a not a user table. '%2' can be 
		** used only on user tables."
		*/
		raiserror 18162, @objname, "sp_setlockpromote"
		return(1)
	end

	select @object_type = 'T '
end


select  @use_lwm = object_info1, @use_hwm = object_info2, 
	@use_pct = object_info3

		 from sysattributes where class = 5
		 and  attribute = @attrib
		 and  object_type = @object_type
		 and  object = @attrib_objid
if @@rowcount != 0
begin

	select @action = 2      /* ATTR_CHANGE */
end
else
begin
	select @action = 1      /* ATTR_ADD */
end


/*
** Validate that if a new attribute value is not specified, then an old one 
** exists for each of LWM, HWM and PCT.
*/

if @new_lwm is not NULL
	select @use_lwm = @new_lwm
if @use_lwm is NULL
begin
	/*
	** 18160, "Please specify a non-NULL value for %1, 
	** since it has not been set previously with a non-NULL value."
	*/
	raiserror 18160, "new_lwm"
	return 1
end

if @new_hwm is not NULL
	select @use_hwm = @new_hwm
if @use_hwm is NULL
begin
	/*
	** 18160, "Please specify a non-NULL value for %1, 
	** since it has not been set previously with a non-NULL value."
	*/
	raiserror 18160, "new_hwm"
	return 1
end

if @new_pct is not NULL
	select @use_pct = @new_pct
if @use_pct is NULL
begin
	/*
	** 18160, "Please specify a non-NULL value for %1, 
	** since it has not been set previously with a non-NULL value."
	*/
	raiserror 18160, "new_pct"
	return 1
end

/* Validate that LWM is less than or equal to HWM. */

if @use_lwm > @use_hwm
begin
	/*
	** 18163, "The 'lock promotion LWM' value %1 cannot 
	** be greater than the 'lock promotion HWM' value %2."
	**
	*/
	raiserror 18163, @use_lwm, @use_hwm
	return 1
end

/*
** Assemble the char_value field for sysattributes. This is needed for
** sp_help and sp_helpdb to display all 3 of LWM, HWM and PCT, even though
** we use an umbrella attribute "row lock promote", or "page lock promote".
*/

select @use_char_value = "PCT = "+ convert(varchar(3),@use_pct) + 
			", LWM = "+ convert(varchar(10),@use_lwm) + 
			", HWM = " + convert(varchar(10),@use_hwm)

begin transaction

	/* Validate boundary conditions for the attributes. */
	select @ret = attrib_valid(5, @attrib, @object_type,
			@attrib_objid, @use_lwm, @use_hwm, @use_pct, NULL,
			NULL, NULL, NULL, NULL, NULL, @action)

	if @ret = 0	/* Validation routine returned false. */
	begin
		rollback tran
		return (1)
	end

	if (@action = 2)	/* ATTR_CHANGE */
	begin
		update sysattributes 
			set char_value = @use_char_value,
			    object_info1 = @use_lwm,
			    object_info2 = @use_hwm, 
			    object_info3 = @use_pct
			where class = 5
				 and  attribute = @attrib
				 and  object_type = @object_type
				 and  object = @attrib_objid

		/*
		** If there was an error, @@error will be non-zero
		*/
		if @@error != 0
		begin
			if @@trancount != 0
				rollback transaction
			return (1)
		end
	end
	else			/* ADD attribute */
	begin

		insert into sysattributes(class, attribute, object_type, object,
					 object_info1, object_info2, 
					 object_info3, char_value)
			values(5, @attrib, @object_type, @attrib_objid, 
						@new_lwm, @new_hwm, @new_pct,
							@use_char_value)

		/*
		** If there was an error, @@error will be non-zero
		*/
		if @@error != 0
		begin
			if @@trancount != 0
				rollback transaction
			return (1)
		end
	end

					
/* Notify */
select @ret = attrib_notify(5, @attrib, @object_type,
		@attrib_objid, @use_lwm, @use_hwm, @use_pct, NULL,
		NULL, NULL, NULL, NULL, NULL, @action)

if @ret = 0	/* Unable to notify ? */
begin
	rollback tran
	return (1)
end
		
commit transaction

/*
** 18165, "The %4! lock promotion attributes of %1, '%2' 
** have been changed. The new values are %3."
*/
exec sp_getmessage 18165, @msg output
print @msg, @scope, @objname, @use_char_value, @obj_type

return (0)
go
exec sp_procxmode 'sp_setlockpromote', 'anymode'
go
grant execute on sp_setlockpromote to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_droplockpromote')
begin
	drop procedure sp_droplockpromote
end
go
print "Installing sp_droplockpromote"
go

/* Stored procedure for dropping lock promotion attributes. 
** Database attributes can only be modified when using Master.
*/

/*
** Messages for "sp_droplockpromote"
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17460, "Object must be in the current database."
** 18090, "The target object does not exist."
** 18159, "You must be in the 'master' database to add, change or drop lock promotion attribute for a user database."
** 18162, "'%1!' is a not a user table. '%2' can be used only on user tables."
** 18166, "Lock promotion attribute does not exist for %1, '%2'. Cannot delete it."
** 18167, "Lock promotion attribute of object '%1!' has been dropped!."
** 18168, "Invalid value '%1', specified for 'scope' parameter. Valid values are 'DATABASE' or 'TABLE'."
** 18169, "Server-wide lock promotion values cannot be dropped. Use 'sp_configure' to restore server-wide defaults.
** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
*/

create procedure sp_droplockpromote
@obj_type varchar(10),			/* page or row */
@scope varchar(10),			/* table, database or server */
@objname varchar(767) = NULL		/* table or database name */
as

declare @attrib_objid int		/* object id of the table/db */
declare @object_type varchar(2)		/* object type of the table/db */
declare @attrib int			/* attrib type of the optname */
declare @msg varchar(1024)		/* message buffer */
declare @action	int			/* DROP sysattributes row */
declare @ret int 			/* Return value of built-in: attrib_notify. */
declare @tab_type smallint		/* User table ? */


if upper(@obj_type) not in ("PAGE", "ROW")
begin
        /*
        ** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
        */
	raiserror 18338, @obj_type
        return (1)
end

if (upper(@scope) = "SERVER")
begin
        /*
        ** 18169, "Server-wide lock promotion values cannot be dropped.
        ** Use 'sp_configure' to restore server-wide defaults.
        */
	raiserror 18169
	return (1)
end

if (upper(@scope) != "DATABASE" and upper(@scope) != "TABLE")
begin
        /*
        ** 18168, "Invalid value '%1', specified for 'scope' parameter
        ** Valid values are 'DATABASE' or 'TABLE'."
        */
	raiserror 18168, @scope
	return (1)
end

/* If we're in a transaction, disallow this */
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_drolockpromote"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1

/*
**  Make sure the @objname is local to the current database.
*/
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
        /*
        ** 17460, "Object must be in the current database."
        */
	raiserror 17460
        return (1)
end

/*
**  Only Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/

if (proc_role("sa_role") < 1)
begin
	/* "User must be System Administrator (SA) 
	** to configure lock promotion attributes. 
	*/
	return(1)
end

if (upper(@scope) = "DATABASE")
begin
	/* If we're dropping lock promotion for a database, 
	**	make sure we're currently in master. */

	select @attrib_objid = db_id()
	if @attrib_objid != 1
	begin
		/*
		** 18159, "You must be in the 'master' database to add, change 
		** or drop lock promotion attribute for a user database."
		*/
		raiserror 18159
		return 1
	
	end

	/* Translate dbname to dbid. */
	select @attrib_objid = 0
	select @attrib_objid = dbid from master.dbo.sysdatabases 
			where name = @objname

	if @attrib_objid = 0
	begin
		/*
		** 17421, "No such database -- run sp_helpdb to list databases."
		*/
		raiserror 17421
		return 1
	end


	select @object_type = 'D '
end

if (upper(@scope) = "TABLE")
begin
	/* Translate objname to objid. */
	select @attrib_objid = 0
	select @attrib_objid = id , @tab_type = sysstat & 7
		from sysobjects where id = object_id(@objname)

	if @attrib_objid = 0
	begin
		/* 
		** 18090, "The target object does not exist."
		*/
		raiserror 18090
                return 1
	
	end

	if @tab_type != 3
	begin
		/*
		** 18162, "'%1!' is a not a user table. '%2'
		**  can be used only on user tables."
		*/
		raiserror 18162, @objname, "sp_dropglockpromote"
		return 1
	end

	select @object_type = 'T '
end

select @action = 3      /* ATTR_DROP */

if upper(@obj_type) = "PAGE"
	select @attrib = 0	/* page lock promotion attribute */
else
	select @attrib = 1	/* row lock promotion attribute */

if not exists(select * from sysattributes where class = 5
			 and  attribute = @attrib
			 and  object_type = @object_type
			 and  object = @attrib_objid)
begin
		/*
                ** 18166, "Lock promotion attribute does not exist for
                ** %1,'%2' . Cannot delete it!"
                */
                raiserror 18166, @scope, @objname
                if @@trancount != 0
                        rollback transaction
                return (1)
end

begin transaction

delete from sysattributes 
	where class = 5
	 and  attribute = @attrib
	 and  object_type = @object_type
	 and  object = @attrib_objid

/*
** If there was an error, @@error will be non-zero
*/
if @@error != 0
begin
	if @@trancount != 0
		rollback transaction
	return (1)
end
					
/* Notify */
select @ret = attrib_notify( 5, @attrib, @object_type,
		@attrib_objid, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL, @action)

if @ret = 0	/* Unable to notify ? */
begin
	rollback tran
	return (1)
end
		
commit transaction

begin
	/*
	** 18167, "Lock promotion attribute of object '%1!' has been dropped!."
	*/
	exec sp_getmessage 18167, @msg output
	print @msg,@objname
end

return (0)
go
exec sp_procxmode 'sp_droplockpromote', 'anymode'
go
grant execute on sp_droplockpromote to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_familylock')
begin
	drop procedure sp_familylock
end
go
print "Installing sp_familylock"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/lock */
/*
** The output of this stored proc is almost identical to the output of
** sp_lock. It differs in that the rows displayed here are a subset of
** the output rows of sp_lock having the parent spid represented by the
** parameters. If sp_familylock is invoked with no parameter it will 
** report information on all processes (belonging to families) that 
** currently hold locks.
**
** Messages for "sp_familylock"
**
** 18052, "The class column will display the cursor name for locks associated
**         with a cursor for the current user and the cursor id for other 
**         users."
*/


create procedure sp_familylock
@fpid1 int = NULL,		/* server family id to check for locks */
@fpid2 int = NULL		/* other family id to check for locks */
as

declare @length int
declare @msg varchar(1024)


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/*  Print warning message about cursor lock info:
**  18052, "The class column will display the cursor name for locks associated
**          with a cursor for the current user and the cursor id for other 
**          users."
*/
exec sp_getmessage 18052, @msg out
print @msg

/* RESOLVE: ensure that fpid1 and fpid2 are not NULL. */
/*
**  Show the locks for both parameters.
*/
if @fpid1 is not NULL
begin
    select @length = max(datalength(db_name(dbid)))
	from master..syslocks
		where fid in (@fpid1, @fpid2)

    /* Print the familyid and context type of the lock and order the output
    ** by fid, spid.
    */
    if (@length > 15)
    begin

	select fid, spid, loid, locktype = v1.name, table_id = l.id, page,
		dbname = db_name(dbid), class, context=v2.name
	from master..syslocks l, master..spt_values v1, master..spt_values v2
		where l.type = v1.number
			and v1.type = "L"
			and (l.context+2048) = v2.number
			and v2.type = "L2"
			and fid in (@fpid1, @fpid2)
			and fid in (select fid from master..sysprocesses
				where fid != 0)
		order by fid, spid, loid, dbname, table_id, locktype, page
    end
    else
	select fid, spid, loid, locktype = v1.name, table_id = l.id, page,
		dbname = convert(char(15), db_name(dbid)), class, context=v2.name
	from master..syslocks l, master..spt_values v1, master..spt_values v2
		where l.type = v1.number
			and v1.type = "L"
			and (l.context+2048) = v2.number
			and v2.type = "L2"
			and fid in (@fpid1, @fpid2)
			and fid in (select fid from master..sysprocesses
				where fid != 0)
		order by fid, spid, loid, dbname, table_id, locktype, page
end

/*
**  No parameters, so show all the locks belonging to family tasks.
*/
else
begin
    select @length = max(datalength(db_name(dbid)))
	from master..syslocks

    if (@length > 15)
	select fid, l.spid, loid, locktype = v1.name, table_id = l.id, page,
		dbname = db_name(l.dbid), class, context=v2.name
	from master..syslocks l, master..spt_values v1, master..spt_values v2
		where l.type = v1.number
			and v1.type = "L"
			and (l.context+2048) = v2.number
			and v2.type = "L2"
			and fid in (select distinct fid from master..sysprocesses
				where fid != 0)
	order by fid, spid, loid, dbname, table_id, locktype, page
    else
	select fid, l.spid, loid, locktype = v1.name, table_id = l.id, page,
		dbname = convert(char(15), db_name(l.dbid)), class, context=v2.name
	from master..syslocks l, master..spt_values v1, master..spt_values v2
		where l.type = v1.number
			and v1.type = "L"
			and (l.context+2048) = v2.number
			and v2.type = "L2"
			and fid in (select distinct fid from master..sysprocesses
				where fid != 0)
	order by fid, spid, loid, dbname, table_id, locktype, page
end

return (0)
go
exec sp_procxmode 'sp_familylock', 'anymode'
go
grant execute on sp_familylock to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setpglockpromote')
begin
	drop procedure sp_setpglockpromote
end
go
print "Installing sp_setpglockpromote"
go

/* Stored procedure for adding or modifying lock promotion attribute. 
** Database attributes can only be modified when using Master.
*/

/*
** Messages for "sp_setpglockpromote"
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17460, "Object must be in the current database."
** 18090, "The target object does not exist."
** 18158, "At least one of the parameters 'new_lwm', 'new_hwm' or 'new_pct' must be non-NULL to execute this procedure."
** 18159, "You must be in the 'master' database to add, change or drop lock promotion attribute for a user database."
** 18160, "Please specify a non-NULL value for %1, since it has not been set previously with a non-NULL value."
** 18161, "Object name parameter must be NULL for Server-wide lock promotion attributes. Using NULL instead of - %1."
** 18162, "'%1!' is a not a user table.  '%1' can be used only on user tables."
** 18163, "The lock promotion LWM value %1 cannot be greater than the lock promotion HWM value %2."
** 18164, "Invalid value specified for 'scope' parameter. Valid values are 'SERVER','DATABASE' or 'TABLE'."
** 18165, "The 'lock promotion!' attributes of %1 '%2' have been changed. The new values are %3."
** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
*/

create procedure sp_setpglockpromote
@scope varchar(10),			/* table, database or server */
@objname varchar(767) = NULL,		/* table or database name */
@new_lwm int = NULL,			/* Lock promotion lwm value */
@new_hwm int = NULL,			/* Lock promotion hwm value */
@new_pct int = NULL			/* Lock promotion pct value */
as

declare @status int

exec @status = sp_setlockpromote "PAGE", @scope, @objname, 
			@new_lwm, @new_hwm, @new_pct
return (@status)
go
exec sp_procxmode 'sp_setpglockpromote', 'anymode'
go
grant execute on sp_setpglockpromote to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropglockpromote')
begin
	drop procedure sp_dropglockpromote
end
go
print "Installing sp_dropglockpromote"
go

/* Stored procedure for dropping lock promotion attributes. 
** Database attributes can only be modified when using Master.
*/

/* NOTE: Any changes to this sproc in /main should actually be made in
** droplockpromote.  this sproc is just a wrapper around droplockpromote.
*/

/*
** Messages for "sp_dropglockpromote"
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17460, "Object must be in the current database."
** 18076, "Could not set curwrite to object level. Set your maxwrite label correctly."
** 18090, "The target object does not exist."
** 18159, "You must be in the 'master' database to add, change or drop lock promotion attribute for a user database."
** 18162, "'%1!' is a not a user table. '%2' can be used only on user tables."
** 18166, "Lock promotion attribute does not exist for %1, '%2'. Cannot delete it."
** 18167, "Lock promotion attribute of object '%1!' has been dropped!."
** 18168, "Invalid value '%1', specified for 'scope' parameter. Valid values are 'DATABASE' or 'TABLE'."
** 18169, "Server-wide lock promotion values cannot be dropped. Use 'sp_configure' to restore server-wide defaults.
** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
*/

create procedure sp_dropglockpromote
@scope varchar(10),			/* table, database or server */
@objname varchar(767) = NULL		/* table or database name */
as

declare @status int

exec @status = sp_droplockpromote "PAGE", @scope, @objname
return (@status)
go
exec sp_procxmode 'sp_dropglockpromote', 'anymode'
go
grant execute on sp_dropglockpromote to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setrowlockpromote')
begin
	drop procedure sp_setrowlockpromote
end
go
print "Installing sp_setrowlockpromote"
go

/* Stored procedure for adding or modifying lock promotion attribute. 
** Database attributes can only be modified when using Master.
*/

/*
** Messages for "sp_setrowlockpromote"
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17460, "Object must be in the current database."
** 18090, "The target object does not exist."
** 18158, "At least one of the parameters 'new_lwm', 'new_hwm' or 'new_pct' must be non-NULL to execute this procedure."
** 18159, "You must be in the 'master' database to add, change or drop lock promotion attribute for a user database."
** 18160, "Please specify a non-NULL value for %1, since it has not been set previously with a non-NULL value."
** 18161, "Object name parameter must be NULL for Server-wide lock promotion attributes. Using NULL instead of - %1."
** 18162, "'%1!' is a not a user table.  '%1' can be used only on user tables."
** 18163, "The lock promotion LWM value %1 cannot be greater than the lock promotion HWM value %2."
** 18164, "Invalid value specified for 'scope' parameter. Valid values are 'SERVER','DATABASE' or 'TABLE'."
** 18165, "The 'lock promotion!' attributes of %1 '%2' have been changed. The new values are %3."
** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
*/

create procedure sp_setrowlockpromote
@scope varchar(10),			/* table, database or server */
@objname varchar(767) = NULL,		/* table or database name */
@new_lwm int = NULL,			/* Lock promotion lwm value */
@new_hwm int = NULL,			/* Lock promotion hwm value */
@new_pct int = NULL			/* Lock promotion pct value */
as

declare @status int

exec @status = sp_setlockpromote "ROW", @scope, @objname, 
			@new_lwm, @new_hwm, @new_pct
return (@status)
go
exec sp_procxmode 'sp_setrowlockpromote', 'anymode'
go
grant execute on sp_setrowlockpromote to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_droprowlockpromote')
begin
	drop procedure sp_droprowlockpromote
end
go
print "Installing sp_droprowlockpromote"
go

/* Stored procedure for dropping lock promotion attributes. 
** Database attributes can only be modified when using Master.
*/

/*
** Messages for "sp_droprowlockpromote"
**
** 17260, "Can't run %1! from within a transaction."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17460, "Object must be in the current database."
** 18090, "The target object does not exist."
** 18159, "You must be in the 'master' database to add, change or drop lock promotion attribute for a user database."
** 18162, "'%1!' is a not a user table. '%2' can be used only on user tables."
** 18166, "Lock promotion attribute does not exist for %1, '%2'. Cannot delete it."
** 18167, "Lock promotion attribute of object '%1!' has been dropped!."
** 18168, "Invalid value '%1', specified for 'scope' parameter. Valid values are 'DATABASE' or 'TABLE'."
** 18169, "Server-wide lock promotion values cannot be dropped. Use 'sp_configure' to restore server-wide defaults.
** 18338, "Invalid obj_type parameter: '%1!'. Please specify 'PAGE' or 'ROW'."
*/

create procedure sp_droprowlockpromote
@scope varchar(10),			/* table, database or server */
@objname varchar(767) = NULL		/* table or database name */
as

declare @status int

exec @status = sp_droplockpromote "ROW", @scope, @objname
return (@status)
go
exec sp_procxmode 'sp_droprowlockpromote', 'anymode'
go
grant execute on sp_droprowlockpromote to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_kernel')
begin
	drop procedure sp_sysmon_kernel
end
go
print "Installing sp_sysmon_kernel"
go

/* This stored procedure produces a report containing a summary of
** SQL Server engine activity.
*/
create procedure sp_sysmon_kernel
	@NumEngines tinyint,	/* number of engines online */
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco char(1),		/* Flag for recommendations */
	@instid smallint = NULL	/* optional SDC instance id */
as

/* --------- declare local variables --------- */
declare @i smallint		/* loop index to iterate through  multi-group
				** counters (engine, disk, & buffer) */
declare @tmp_grp varchar(25)	/* temp var to build group_names
				** ie. engine_N, disk_N */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @cpu_busy real		/* var for cpu busy percentage */
declare @io_busy real		/* var for io busy percentage */
declare @cpu_busy_sum real	/* var for summing cpu busy percentage */
declare @io_busy_sum real	/* var for summing io busy percentage */
declare @cpu_busy_avg real	/* var for averaging cpu busy percentage */
declare @io_busy_avg real	/* var for averaging io busy percentage */
declare @rpsc int           	/* holds cfgvalue for RPSC */
declare @iopc int           	/* holds cfgvalue for I/O polling count */
declare @eng_load_line char(67)	/* string to delimit the engine load lines */
declare @avg1line char(67)	/* string to delimit avg lines on printout */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(67)	/* string to delimit total lines with percent 
				** calc on printout */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted statistics line for print 
				** statement */
declare @section char(80)       /* string to delimit sections on printout */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)	/* Header for tuning recommendation */
declare @recoline char(80)	/* to underline recotxt */
declare @reco_hdr_prn bit	/* to indicate if the recotxt is already printed */
declare @reco_percent_diskio real /* percentage sucessful disk i/o */

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @avg1line   = "  -----------             ---------------          ----------------"
select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="


/* ======================= Kernel Utilization Section =================== */
print @section
print @blankline
print "Kernel Utilization"
print "------------------"
print @blankline

	select @rpsc = value from master..syscurconfigs where config=177

	
select @rptline= "  Your Runnable Process Search Count is set to " 
			+ convert(varchar, @rpsc)
print @rptline


	select @iopc = value from master..syscurconfigs where config=178


select @rptline= "  and I/O Polling Process Count is set to " 
			+ convert(varchar, @iopc)
print @rptline
print @blankline

select 	@i = 0, @cpu_busy_sum = 0, @io_busy_sum = 0, @cpu_busy_avg = 0, 
	@io_busy_avg = 0, @reco_percent_diskio = 0

select @rptline = "  Engine Busy Utilization "+ space(7) 
			+ "CPU Busy" + space(3) 
			+ "I/O Busy" + space(7) 
			+ "Idle"
print @rptline
select @eng_load_line = "  ------------------------" + space(7) 
			+ "--------" + space(3) 
			+ "--------" + space(3) 
			+ "--------"
print @eng_load_line
while @i < @NumEngines                                   /* for each engine */
  begin
	/* build group_name string */
	select @tmp_grp = "engine_" + convert(varchar(3), @i)

	select 	@cpu_busy = isnull(100.0 * convert(real,c.value)/t.value, 0),
		@io_busy = isnull(100.0 * convert(real,i.value)/t.value, 0)
	  from #tempmonitors t, #tempmonitors c, #tempmonitors i
	 where t.group_name = @tmp_grp 
	   and t.group_name = c.group_name
	   and t.group_name = i.group_name
	   and t.field_name = "clock_ticks"
	   and i.field_name = "io_ticks" 
	   and c.field_name = "cpu_ticks" 
	   and t.value > 0

	select 	@cpu_busy_sum = @cpu_busy_sum + @cpu_busy,
		@io_busy_sum = @io_busy_sum + @io_busy

	select @rptline = "    Engine " + convert(char(3), @i) + space(20) 
				+ str(@cpu_busy,5,1) + @psign + space(4) 
				+ str(@io_busy,5,1) + @psign + space(4) 
				+ str(100 - @cpu_busy - @io_busy,5,1) + @psign
	print @rptline
	select @i = @i + 1
  end

if @NumEngines > 1
  begin
	print @eng_load_line
	select @rptline = "  Summary " + space(10) + "Total" +space(7)
				+ str(@cpu_busy_sum,7,1) + @psign + space(2) 
				+ str(@io_busy_sum,7,1) + @psign + space(2) 
				+ str(@NumEngines * 100 - @cpu_busy_sum 
					- @io_busy_sum,7,1) + @psign,
			@cpu_busy_avg = @cpu_busy_sum/@NumEngines,
			@io_busy_avg = @io_busy_sum/@NumEngines
	print @rptline
	select @rptline = space(18) + "Average" + space(9) 
				+ str(@cpu_busy_avg,5,1) + @psign + space(4) 
				+ str(@io_busy_avg,5,1) + @psign + space(4) 
				+ str(100 - @cpu_busy_avg - @io_busy_avg,5,1) 
				+ @psign
	print @rptline
  end

print @blankline
print "  CPU Yields by Engine            per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
        field_name = "engine_sleeps"

if @tmp_total = 0	/* Avoid divide by zero errors - just print zero's */
 begin
	select @rptline = "  Total CPU Yields                    0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp= "engine_" + convert(varchar(3), @i) 
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "engine_sleeps"

		select @rptline = "    Engine " + convert(char(3),@i) + 
					space(15) +
					str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
					+ space(2) +
					str(@tmp_int / convert(real, @NumXacts),12,1) 
					+ space(2) +
					str(@tmp_int, 10) + space(5) +
					str(100.0 * @tmp_int / @tmp_total,5,1) 
					+ @psign
		print @rptline
		select @i = @i + 1
	  end

	if @NumEngines > 1
	  begin
		print @sum2line 
		select @rptline = "  Total CPU Yields " + space(10) +
					str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) 
					+ space(2) +
					str(@tmp_total / convert(real,@NumXacts),12,1) 
					+ space(2) +
					str(@tmp_total,10)
		print @rptline
	  end
  end
print @blankline

print "  Network Checks"

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = "kernel" and
  field_name like "ncheck_%"

if @tmp_total = 0	/* Avoid divide by zero errors - print zero's */
 begin
	select @rptline = "    Total Network I/O Checks          0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
	  		field_name = "ncheck_nonblocking"
	  
	select @rptline = "    Non-Blocking" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1)
				+ @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
	  		field_name = "ncheck_blocking"

	select @rptline = "    Blocking" + space(17) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	print @sum2line 
	select @rptline = "  Total Network I/O Checks " + space(2) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real,@NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "network" and
			field_name like "total_packets_%"

	select @rptline = "  Avg Net I/Os per Check" + space(14) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(convert(real, @tmp_int) / @tmp_total,10,5)+
				space(7) +
				@na_str
	print @rptline
  end
print @blankline

print "  Disk I/O Checks"

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "dcheck_calls"

if @tmp_total = 0	/* Avoid divide by zero errors - print zero's */
 begin
	select @rptline = "      Total Disk I/O Checks           0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	select @rptline = "    Total Disk I/O Checks" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
	print @rptline

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "engine_%" and
			field_name = "dchecks_calling_dpoll"

	select @rptline = "    Checks Returning I/O" + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
 				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int/ @tmp_total,5,1) + @psign
	if @tmp_total != 0
	 begin
		select @reco_percent_diskio = 100.0 * (convert(real, @tmp_int)/ @tmp_total)
	 end

	print @rptline

	/* save checks returning i/o value for average calc below */
	select @tmp_total = @tmp_int

	if @tmp_total != 0
	  begin
		select @tmp_int = SUM(value)
		  from #tempmonitors
		  where group_name like "engine_%" and
				field_name = "total_dpoll_completed_aios"

		select @rptline = "    Avg Disk I/Os Returned" + space(12) +
						@na_str + space(11) +
						@na_str + space(2) +
						str(convert(real, @tmp_int) / 
							@tmp_total,10,5) + 
						space(7) +
						@na_str
		print @rptline
	  end
  end

print @blankline
if @Reco = 'Y'
 begin
	select @recotxt = "  Tuning Recommendations for Kernel Utilization"
	select @recoline = "  ---------------------------------------------"	
	select @reco_hdr_prn = 0

	if @NumEngines > 1
	begin
		/*
		** If the average percentage busy on the engines
		** is > 95% consider increasing the number of engines
		*/
		if (@cpu_busy_avg > 95)
		 begin
			if (@reco_hdr_prn = 0)
			begin
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end

			print "  - Consider bringing more engines online"
			print @blankline
			select @reco_hdr_prn = 1
		 end

		/*
		** If the average percentage busy on the engines is < 5% 
		** consider decreasing the 'runnable process search count' 
		** configuration parameter, if other applications are running
		** on the same machine. 
		** If runnable process search count is already set to 100 or less
		** don't print this recommendation.
		*/
		if (@cpu_busy_avg < 5 and @rpsc > 100)
		 begin
			if (@reco_hdr_prn = 0)
			begin
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end

			print "  - Consider decreasing the 'runnable process search count'"
			print "    configuration parameter if you require the CPU's on"
			print "    the machine to be used for other applications."
			print @blankline
			select @reco_hdr_prn = 1
		 end
		/*
		** If the average cpu busy percentage on the engines
		** is > 70% and the average busy on the engines
		** is < 90% and the percentage diskio is < 5% consider 
		** increasing the 'i/o polling process count' 
		** configuration parameter.
		** Don't print this recommendation if the config param 
		** is already set to 10000 or higher.
		*/
		if (@cpu_busy_avg > 70 AND @cpu_busy_avg < 90 
				AND  @reco_percent_diskio < 5
				AND @iopc < 10000)
		 begin
			if (@reco_hdr_prn = 0)
			begin
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end

			print "  - Consider increasing the 'i/o polling process count'"
			print "    configuration parameter."
			print @blankline
			select @reco_hdr_prn = 1
		 end
	end
 end
print @blankline

return 0
go
exec sp_procxmode 'sp_sysmon_kernel', 'anymode'
go
grant execute on sp_sysmon_kernel to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_wpm')
begin
	drop procedure sp_sysmon_wpm
end
go
print "Installing sp_sysmon_wpm"
go

/* This stored procedure produces a report containing a summary of
** SQL Server worker process activity.
*/
create procedure sp_sysmon_wpm
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco   char(1)         /* Flag for recommendations             */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_int3 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(80)	
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted statistics line for print 
				** statement */
declare @section char(80)       /* string to delimit sections on printout */
/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @sum1line   = " --------------------------  ------------  ------------  ----------"
select @sum2line   = "                             ------------  ------------  ----------  ----------"
select @section = "==============================================================================="

/* ======================= Worker Process Management Section =================== */

/* This subordinate should not appear for pre 11.1 servers */

if not exists (select *
  from #tempmonitors
  where group_name = "kernel" and
        field_name = "wtm_connect_requests")
  begin
	print @blankline
	return 0
  end

print @section
print @blankline
print "Worker Process Management"
print "-------------------------"
print "                                  per sec      per xact       count  %% of total"
print @sum2line
print " Worker Process Requests"


select @tmp_total = value
  from #tempmonitors
  where group_name = "kernel" and
        field_name = "wtm_connect_requests"



if @tmp_total = 0	/* Avoid divide by zero errors - just print zero's */
 begin
	select @rptline = "   Total Requests                     0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
			field_name = "wtm_denied_requests"

	select @tmp_int2 = @tmp_total - @tmp_int

	select @rptline = "  Requests Granted " +  space(10) +
				str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_int2 / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_int2, 10) + space(5) +
				str(100.0 * @tmp_int2 / @tmp_total,5,1) 
				+ @psign
	print @rptline

	select @rptline = "  Requests Denied  " +  space(10) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) 
				+ @psign
	print @rptline

	print @sum1line

	select @rptline = "  Total Requests " +  space(12) +
				str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_total / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_total, 10)
	print @rptline
  
	print @blankline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
			field_name = "wtm_terminations"

	select @rptline = "  Requests Terminated " +  space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) 
				+ @psign
	print @rptline

  end

print @blankline
print " Worker Process Usage"

select @tmp_int = value
	from #tempmonitors
	where group_name = "kernel" and
	field_name = "wtm_thread_requests"

select @rptline = "   Total Used" +  space(17) +
		str(@tmp_int / (@NumElapsedMs / 1000.0),11,1) 
		+ space(3) +
		str(@tmp_int / convert(real, @NumXacts),11,1) 
		+ space(2) +
		str(@tmp_int, 10) + space(7) +
		@na_str
		
print @rptline

select @tmp_int3 = value
  	from #tempmonitors
  	where group_name = "kernel" and
	field_name = "wtm_high_water_mark"

select @rptline = "   Max Ever Used During Sample" +  
		str(@tmp_int3 / (@NumElapsedMs / 1000.0),11,1) 
		+ space(3) +
		str(@tmp_int3 / convert(real, @NumXacts),11,1) 
		+ space(2) +
		str(@tmp_int3, 10) + space(7) +
		@na_str
print @rptline

print @blankline
print " Memory Requests for Worker Processes"

select @tmp_total = value
  from #tempmonitors
  where group_name = "kernel" and
        field_name = "wtm_memory_allocs"

if @tmp_total = 0	/* Avoid divide by zero errors - just print zero's */
 begin
	select @rptline = "   Total Requests                     0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
			field_name = "wtm_memory_allocs_failed"

	select @tmp_int2 = @tmp_total - @tmp_int

	select @rptline = "   Succeeded     " +  space(12) +
				str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_int2 / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_int2, 10) + space(5) +
				str(100.0 * @tmp_int2 / @tmp_total,5,1) 
				+ @psign
	print @rptline

	select @rptline = "   Failed        " +  space(12) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) 
				+ @psign
	print @rptline

	print @sum1line

	select @rptline = "   Total Requests" +  space(12) +
				str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) 
				+ space(2) +
				str(@tmp_total / convert(real, @NumXacts),12,1) 
				+ space(2) +
				str(@tmp_total, 10)
	print @rptline
  

	print @blankline

	if (@tmp_int3 > 0)
	 begin

		select @tmp_int = value
  			from #tempmonitors
 		 	where group_name = "kernel" and
			field_name = "wtm_mem_alloc_hwm"

		select @rptline = " Avg Mem Ever Used by a WP (in bytes)" +space(1) +
			@na_str +
			+ space(11) +
			@na_str +
			+ space(2) +
			str(@tmp_int/convert(real, @tmp_int3), 10,1) + space(7) +
			@na_str
		print @rptline
	 end
  end


/* If requested, print worker process recommendations (if any) */

if (@Reco = 'Y')
 begin
	print @blankline
        select @recotxt =     " Tuning Recommendations for Worker Processes"
        select @recoline = " -------------------------------------------"
        select @reco_hdr_prn = 0

        select @tmp_total = 0
        select @tmp_int = 0
        select @tmp_int2 = 0

	select @tmp_int = convert(integer,value) from #tempconfigures
                        where name like "%number of worker processes%"

	if (@tmp_int > 0)
	 begin
		select @tmp_int2 = value from #tempmonitors
  			where group_name = "kernel" and
			field_name = "wtm_high_water_mark" 

        	select @tmp_total = convert(int,(100.0*a.value/b.value))
                	from #tempmonitors a, #tempmonitors b
                	where   a.group_name = "kernel"
                	and     a.field_name = "wtm_denied_requests"
                	and     b.group_name = "kernel"
                	and     b.field_name = "wtm_connect_requests"
                	and     b.value != 0 

		/*
		** If the number of worker processes configured is less
		** than the high water mark, consider increasing
		** the 'number of worker processes'
		*/
		if ( @tmp_int <= @tmp_int2 and @tmp_total > 80)
         	begin
                        if (@reco_hdr_prn = 0)
                        begin
                                 print @recotxt
                                 print @recoline
                                 select @reco_hdr_prn = 1
                        end
                        print "  - Consider increasing the 'number of worker processes'"
			print "    configuration parameter."
                        print @blankline
         	end
		else 
		if ( (100.0*@tmp_int2/@tmp_int) <= 25  and @tmp_total = 0)
	 	begin
                        if (@reco_hdr_prn = 0)
                        begin
                                 print @recotxt
                                 print @recoline
                                 select @reco_hdr_prn = 1
                        end
                        print "  - Consider decreasing the 'number of worker processes'"
			print "    configuration parameter."
                        print @blankline
         	end
	
	end

        select @tmp_total = 0
        select @tmp_int2 = 0

	select @tmp_int = value from #tempmonitors
  			where group_name = "kernel" and
			field_name = "wtm_high_water_mark" 

	if (@tmp_int > 0)
	  begin		
		select @tmp_int2 = convert(integer,value) from #tempconfigures
                        where name like "%memory per worker process%" 

		if (@tmp_int2 > 0)
	 	begin
			select @tmp_int3 = convert(integer,value/@tmp_int) from #tempmonitors
  				where group_name = "kernel" and
				field_name = "wtm_mem_alloc_hwm" 

        		select @tmp_total = convert(int,(100.0*a.value/b.value))
               		 	from #tempmonitors a, #tempmonitors b
               		 	where   a.group_name = "kernel"
               		 	and     a.field_name = "wtm_memory_allocs_failed"
               		 	and     b.group_name = "kernel"
               		 	and     b.field_name = "wtm_memory_allocs"
               		 	and     b.value != 0 

			/*
			** If the % of times worker thread memory
			** allocations failed to the number of allocations
			** is > 80% then consider increasing the 
			** 'memory per worker process' configuration parameter
			** else consider decreasing the 'memory per worker process'
			** configuration parameter.
			*/
			if ( @tmp_int2 <= @tmp_int3 and @tmp_total > 80)
         		begin
               		         if (@reco_hdr_prn = 0)
               		         begin
               		                  print @recotxt
               		                  print @recoline
               		                  select @reco_hdr_prn = 1
               		         end
               		         print "  - Consider increasing the 'memory per worker process'"
				 print "    configuration parameter."
               		         print @blankline
         		end
			else 
			if ( (@tmp_int2 - @tmp_int3) > 512  and @tmp_total = 0)
	 		begin
                       		 if (@reco_hdr_prn = 0)
                       		 begin
                       		          print @recotxt
                       		          print @recoline
                       		          select @reco_hdr_prn = 1
                       		 end
                       		 print "  - Consider decreasing the 'memory per worker process'"
				 print "    configuration parameter."
               		         print @blankline
         		end
		end
	end
 end 

print @blankline
return 0
go
exec sp_procxmode 'sp_sysmon_wpm', 'anymode'
go
grant execute on sp_sysmon_wpm to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_parallel')
begin
	drop procedure sp_sysmon_parallel
end
go
print "Installing sp_sysmon_parallel"
go

/* This stored procedure produces a report describing the parallel
** features: activity.
**
*/
create procedure sp_sysmon_parallel
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco char(1)		/* Flag for recommendations             */
as

/* --------- declare local variables --------- */
declare @NumTaskSwitch int	/* Total Number of Task Context Switches 
				** across all engines */
declare @KnownTaskSwitch int	/* Count of Number of Task Context Switches 
				** by Known Causes */
declare @i smallint		/* loop index to iterate through multi-group 
				** counters (engine, disk, & buffer) */
declare @tmp_grp varchar(25)	/* temp var for building group_names 
				** ie. engine_N, disk_N */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for integer storage, totals */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(67)	/* string to delimit total lines with percent 
				** calc on printout */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @reco_no_thread_adjusts int
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare @reco_total_waits int
declare @reco_runtime_adjust int
declare @reco_total_queries int	

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

/* ===================== Parallel Query Management Section ============== */

if not exists(select *
		from #tempmonitors
		where group_name = "parallel" and
		field_name = "pll_total_number_parallel_queries")
begin
	print @blankline
	return 0
end

print @section
print @blankline
/*
** ------ 
*/
print "Parallel Query Management"
print "-------------------------"
print @blankline


select @tmp_total = value, @reco_total_queries = value
	from #tempmonitors
	where group_name = "parallel" and
	field_name = "pll_total_number_parallel_queries"

select @reco_no_thread_adjusts = 0
select @reco_runtime_adjust = 0
select @reco_total_waits = 0

print "  Parallel Query Usage            per sec      per xact       count  %% of total"
print @sum1line
select @rptline = "  Total Parallel Queries" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10) + space(7) +
			@na_str
print @rptline
if @tmp_total > 0
begin
	select @tmp_int = value
	from #tempmonitors
	where group_name = "parallel" and
	  	field_name = "pll_runtime_adjust_to_thread_limit"

	select @reco_runtime_adjust = convert(int, 
			100.0 * ((1.0* @tmp_int)/@reco_total_queries))

	select @rptline = "  WP Adjustments Made"
	print @rptline

	select @rptline = "    Due to WP Limit " + space(9) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline


	select @tmp_int = value
	from #tempmonitors
	where group_name = "parallel" and
	  	field_name = "pll_runtime_adjust_dueto_nothreads"

	select @reco_no_thread_adjusts = convert(int, 
			100.0 * ((1.0* @tmp_int)/@reco_total_queries))

	select @rptline = "    Due to No WPs" + space(12) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline
end




print @blankline
select @tmp_total = sum(value)
  from #tempmonitors
  where group_name = "parallel"
	and field_name like "pll_%lock_%"
print "  Merge Lock Requests             per sec      per xact       count  %% of total"
print @sum1line

if @tmp_total = 0
begin
	select @rptline   = "  Total # of Requests                 0.0           0.0           0       n/a"
	print @rptline
end
else
begin
	select @rptline = "    Network Buffer Merge Locks"
	print @rptline

	select @tmp_int = sum(value)
	from #tempmonitors
	where group_name = "parallel" and
		  field_name like "pll_tbm_lock_immed%"

	select @rptline = "      Granted with no wait" + space(3) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline
	select @tmp_int = sum(value)
	from #tempmonitors
	where group_name = "parallel" and
		  field_name like "pll_tbm_lock_waited%"

	select @rptline = "      Granted after wait" + space(5) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline
	print @blankline

	select @rptline = "    Result Buffer Merge Locks"
	print @rptline

	select @tmp_int = sum(value)
	from #tempmonitors
	where group_name = "parallel" and
		  field_name like "pll_rbm_lock_immed%"

	select @rptline = "      Granted with no wait" + space(3) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

	select @tmp_int = sum(value)
	from #tempmonitors
	where group_name = "parallel" and
		  field_name like "pll_rbm_lock_waited%"

	select @rptline = "      Granted after wait" + space(5) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline
	print @blankline

	select @rptline = "    Work Table Merge Locks"
	print @rptline

	select @tmp_int = sum(value)
	from #tempmonitors
	where group_name = "parallel" and
		  field_name like "pll_wkm_lock_immed%"

	select @rptline = "      Granted with no wait" + space(3) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

	select @tmp_int = sum(value)
	from #tempmonitors
	where group_name = "parallel" and
		  field_name like "pll_wkm_lock_waited%"

	select @rptline = "      Granted after wait" + space(5) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

	print @sum2line
	select @rptline = "  Total # of Requests" + space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
end

print @blankline
select @tmp_total = sum(value)
  from #tempmonitors
  where group_name = "parallel"
	and field_name like "pll_pipe_%buf_waited"

if (@reco_total_queries > 0)
begin
select @reco_total_waits = convert(int, 
		100.0 * ((1.0* @tmp_total)/@reco_total_queries))
end

print "  Sort Buffer Waits               per sec      per xact       count  %% of total"
print @sum1line

if @tmp_total = 0
begin
	select @rptline   = "  Total # of Waits                    0.0           0.0           0       n/a"
	print @rptline
end
else
begin
	select @tmp_int = value
	from #tempmonitors
	where group_name = "parallel" and
	  	field_name = "pll_pipe_allocbuf_waited"

	select @rptline = "    Producer Waits" + space(11) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign

	print @rptline
	select @tmp_int = value
	from #tempmonitors
	where group_name = "parallel" and
		  field_name = "pll_pipe_recvbuf_waited"

	select @rptline = "    Consumer Waits" + space(11) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign

	print @rptline
	print @sum2line
	select @rptline = "  Total # of Waits" + space(11) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
end
print @blankline
if @Reco = 'Y'
 begin
        select @recotxt =     "  Tuning Recommendations for Parallel Query Management"
        select @recoline = "  ----------------------------------------------------"
   	select @reco_hdr_prn = 0

	/*
	** If the % of number of thread adjusts due to no threads 
	** to the number of parallel queries run is > 10%, 
	** then consider increasing the 'number of worker processes' 
	** configuration parameter
	*/
        if (@reco_no_thread_adjusts > 10)
        begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end
                print "  - Consider increasing the 'number of worker processes'"
		print "    configuration parameter."
                print @blankline
        end

	/*
	** If the number of thread adjusts due to worker process limit
	** to the number of parallel queries run is > 10% 
	** then consider tuning your session level limits
	*/
	if (@reco_runtime_adjust > 10)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider re-evaluating your session level limts set with"
		print "   'set scan_parallel_degree' or 'set parallel_degree'."
		print @blankline
	end
	/*
	** If the number of waits due to pipe buffers is greater 
	** to the number of parallel queries run in > 5%
	** consider increasing the 'number of sort buffers'
	*/
        if (@reco_total_waits > 5)
        begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end
                print "  - Consider increasing the 'number of sort buffers'"
		print "    configuration parameter."
                print @blankline
	end
  end
return 0
go
exec sp_procxmode 'sp_sysmon_parallel', 'anymode'
go
grant execute on sp_sysmon_parallel to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_taskmgmt')
begin
	drop procedure sp_sysmon_taskmgmt
end
go
print "Installing sp_sysmon_taskmgmt"
go

/* This stored procedure produces a report describing the scheduling
** of user tasks.
**
*/
create procedure sp_sysmon_taskmgmt

	@NumEngines tinyint,	/* number of engines online */
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco	char(1)		/* Flag for recommendations */
as

/* --------- declare local variables --------- */
declare @NumTaskSwitch int	/* Total Number of Task Context Switches 
				** across all engines */
declare @IgnoreTaskSwitch int	/* Total Number of Task Context Switches 
				** which can be ignored */
declare @KnownTaskSwitch int	/* Count of Number of Task Context Switches 
				** by Known Causes */
declare @IgnoreTaskYields int	/* Total Number of Task Yields which can be
				** ignored */
declare @i smallint		/* loop index to iterate through multi-group 
				** counters (engine, disk, & buffer) */
declare @tmp_grp varchar(25)	/* temp var for building group_names 
				** ie. engine_N, disk_N */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_iopacing int	/* temp var for storing the value of I/O pacing */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(67)	/* string to delimit total lines with percent 
				** calc on printout */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare @reco_cache_search_miss real
declare @reco_io_pacing real
declare @reco_lock_contention real
declare @reco_group_commit_sleeps real
declare @reco_device_contention real
declare @reco_network_sent real
declare @reco_network_received real


/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "---------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

/* =========================  Task Management Section ==================== */
print @section
print @blankline
print "Task Management                   per sec      per xact       count  %% of total"
print @sum1line
print @blankline
/*
** ------ Connections Opened (Closed Not Available in counters) ------
*/
select @tmp_int = value
from #tempmonitors
where group_name = "kernel" and
	  field_name = "processes_created"

select @rptline="  Connections Opened" + space(9)
				+ str(@tmp_int/(@NumElapsedMs/1000.0),12,1)
				+ space(2)
				+ str(@tmp_int/convert(real,@NumXacts),12,1)
				+ space(2)
				+ str(@tmp_int, 10) + space(7)
				+ @na_str
print @rptline
print @blankline

/*
** We need to count total number of context switches as sum of total calls
** to upyield() and upsleepgeneric() as we count other counters outside of
** these calls. 'context_switches' is incremented only if there is a real
** context switch. A task doesn't need to go through real context switch
** while calling upyield() or upsleepgenric().
*/
select @NumTaskSwitch = SUM(value)
  from #tempmonitors
  where group_name = "kernel" and 
		field_name in ("yields", "number_of_sleeps")

/*
** Count the number of task switches which can be ignored. For example,
** BCM/CLM daemon may be woken up when ever a request is queued. Once
** the request is serviced, daemons goes back to sleep. Similarly sleeps
** due to garbage collector can also be ignored.
*/
select @IgnoreTaskSwitch = 0

select @tmp_int = value
  from #tempmonitors
  where group_name = "lock" and 
		field_name = "lock_gc_yields"

select @IgnoreTaskSwitch = @IgnoreTaskSwitch + @tmp_int

select @tmp_int = value
  from #tempmonitors
  where group_name = "lock" and 
		field_name = "daemon_context_switches"

select @IgnoreTaskSwitch = @IgnoreTaskSwitch + @tmp_int

select @tmp_int = SUM(value)
  from #tempmonitors
  where group_name = "bcmt" and 
		field_name in ("bcmt_pri_sleeps", "bcmt_sec_sleeps")

select @IgnoreTaskSwitch = @IgnoreTaskSwitch + @tmp_int

select @IgnoreTaskYields = value
  from #tempmonitors
  where group_name = "bcmt" and 
		field_name = "bcmt_sec_empty_scans"

select @NumTaskSwitch = @NumTaskSwitch - @IgnoreTaskSwitch - @IgnoreTaskYields

print "  Task Context Switches by Engine"

if @NumTaskSwitch <= 0	/* Avoid divide by zero errors - print zero's */
 begin
	select @rptline = "      Total Task Switches             0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp = "engine_" + convert(varchar(3), @i)

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
	  			field_name = "context_switches"

		select @rptline = "    Engine "+convert(char(3),@i)+space(15) +
				str(@tmp_int/(@NumElapsedMs/1000.0),12,1) + 
				space(2) +
				str(@tmp_int/convert(real,@NumXacts),12,1) + 
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / (@NumTaskSwitch + 
				 @IgnoreTaskSwitch + @IgnoreTaskYields),5,1) + 
				@psign
		print @rptline
		select @i = @i + 1
	  end	/* while */

	if @NumEngines > 1
	  begin
		print @sum2line 
		select @rptline = "    Total Task Switches:" + space(5) +
			str(@NumTaskSwitch / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@NumTaskSwitch / convert(real,@NumXacts),12,1) + 
			space(2) +
			str(@NumTaskSwitch,10)
		print @rptline
	  end /* if @NumEngines > 1*/
	print @blankline

	/* 
	** Break Down All Task Context Switches by Cause 
	*/
	print "  Task Context Switches Due To:"

	/* init count of known context switches */
	select @KnownTaskSwitch = 0		

	/* 
	** Context Switch Due to Task Yields (Voluntary)
	*/
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
	  		field_name = "yields"

	select @tmp_int = @tmp_int - @IgnoreTaskYields

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int 

	select @rptline = "    Voluntary Yields" + space(9) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/*
	**  Context Switch Due to Cache Search Misses resulting in a read
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name = "bufread_read_waits"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Cache Search Misses" + space(6) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) +
				@psign

	select @reco_cache_search_miss = convert(int, 
			100.0 * ((1.0* @tmp_int) / @NumTaskSwitch))

	print @rptline

	/*  
	**  Context Switch due to exceedint the 'i/o batch size' config limit.
	**
	**  In other words, we started I/O batch and now we are waiting
	**  for them to complete before starting the next batch.  The server 
	**  works in batches to avoid flooding the I/O subsystem.  The size 
	**  of the batch is tuneable via config parameter 'io batch size'.
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name in ("my_start_waits_periobatch")

	select @tmp_iopacing = @tmp_int		
			
	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Exceeding I/O batch size" + space(1) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) +
				@psign

	select @reco_io_pacing = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* 
	** Context Switch Due to Disk Writes 
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name in ("write_waits", "hk_write_waits", 
					"restart_io_waits",
					"my_start_waits_log", 
					"my_start_waits_non-log",
					"my_other_waits_non-log")

	select @tmp_int = @tmp_int - @tmp_iopacing		

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    System Disk Writes" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/*
	** Context Switch Due to DB Lock Contention
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name like "waited_%" and
			field_name not like "waited_%_ADDR"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Logical Lock Contention  " +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) +
				@psign
	
	select @reco_lock_contention = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* 
	** Context Switch Due to Address Lock Contention 
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name like "waited_%_ADDR"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Address Lock Contention  " +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/* 
	** Context Switch Due to Latch Contention 
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "latch" and
			field_name like "waited_%_LATCH"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Latch Contention  " + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	print @rptline

	/* Context Switch Due to Physical lock transition. */
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name like "physical_lock_context_switches"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Physical Lock Transition" + space(1) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	print @rptline

	/* Context Switch Due to Logical Lock Transition. */
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name like "logical_lock_context_switches"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Logical Lock Transition" + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	print @rptline

	/* Context Switch Due to Object Lock Transition. */
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name like "ocm_context_switches"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Object Lock Transition " + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	print @rptline

	/* 
	** Context Switch Due to Blocking on Log Semaphore 
	*/
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "xls" and
			field_name = "log_lock_waited"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Log Semaphore Contention " +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/* 
	** Context Switch Due to Blocking on PLC lock
	*/
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "xls" and
			field_name = "plc_lock_waits"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    PLC Lock Contention " + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/* 
	** Context Switch Due to Group Commit Sleeps 
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name IN ("my_other_waits_log", 
					"log_lastpage_pending_io_sleeps")

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Group Commit Sleeps" + space(6) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	select @reco_group_commit_sleeps = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* 
	** Context Switch Due to Last Log Page Writes 
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name = "last_log_page_writes"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Last Log Page Writes" + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/* Context Switch Due to Modify Conflicts 
	**
	**  In other words, a task wants to perform an operation on a page 
	**  (i.e. write it), but can't because another task is in the middle 
	**  of modifying it.
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and field_name in 
		  ("changing_state_waits", "bufwrite_changing_waits", 
		   "bufpredirty_write_waits", "bufpredirty_changing_waits", 
		   "bufnewpage_changing_waits", "ind_bufguess_changing_waits",
		   "ind_bufguess_writing_waits")

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Modify Conflicts" + space(9) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

	/* 
	** Context Switch Due to Disk Device Contention 
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "disk_%" and
			field_name = "p_sleeps"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    I/O Device Contention" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	select @reco_device_contention = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* 
	** Context Switch Due to Network Packets Received
	*/
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "network" and
			field_name = "network_read_sleeps"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Network Packet Received" + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	select @reco_network_received = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* 
	** Context Switch Due to Network Packets Sent
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "network" and
			field_name = "network_send_sleeps"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Network Packet Sent" + space(6) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	select @reco_network_sent = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* Context Switch Due to CIPC Thread Sleeps. */
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "kernel" and
			field_name like "cipc_context_switches"

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Interconnect Message Sleeps" + space(1) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),9,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign

	print @rptline

	/*  
	**  Context Switch Due to Network services
	*/
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "network%" and
			field_name in ("nserver_sleeps")

	select @KnownTaskSwitch = @KnownTaskSwitch + @tmp_int

	select @rptline = "    Network services" + space(9) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) +
				@psign

	select @reco_io_pacing = convert(int, 
			100.0 * ((1.0* @tmp_int)/@NumTaskSwitch))

	print @rptline

	/* 
	** Context Switch Due to Other Causes
	*/
	select @tmp_int = @NumTaskSwitch - @KnownTaskSwitch
	select @rptline = "    Other Causes" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @NumTaskSwitch,5,1) + 
				@psign
	print @rptline

  end		/* else @NumTaskSwitch != 0 */

print @blankline

if @Reco = 'Y'
 begin
        select @recotxt = "  Tuning Recommendations for Task Management"
        select @recoline = "  ------------------------------------------"
        select @reco_hdr_prn = 0

	/*
	** If the context switches due to cache misses is > 50% 
	** consider tuning your Data Caches
	*/
	if (@reco_cache_search_miss > 50)
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider tuning your Data Caches."
		print "    Look into the Data Cache management section for"
		print "    more details on this."
		print @blankline
		select @reco_hdr_prn = 1
	end

	/*
	** If the context switches due to IO Pacing is > 50% consider tuning 
	** the 'i/o batch size' configuration parameter.
	*/
	if (@reco_io_pacing > 50)
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider tuning the 'i/o batch size' configuration parameter parameter"
		print "	   A value of 100 is generally optimal. Also verify the I/O response times if the 'i/o batch size' tuning does not help"
		print @blankline
		select @reco_hdr_prn = 1
	end

	/*
	** If context switches due to lock contention is > 50% consider using 
	** different lock management strategies such as row level locking
	** for certain objects.
	*/
	if (@reco_lock_contention > 50)
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider identifying objects with high"
		print "    lock contention using the sp_object_stats stored procedure"
		print "    Review the Lock management section for more details."
		print @blankline
		select @reco_hdr_prn = 1
	end
	/*
	** If the context switches due to group commit sleeps is > 50% 
	** consider tuning the log io size
	*/
	if (@reco_group_commit_sleeps > 50)
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end
		print "  - Consider lowering the logio size using sp_logiosize"
		print "    for better transaction commit performance."
		print "    This recommendation is not valid if the logio size is 2K."
		print @blankline
		select @reco_hdr_prn = 1
	end
	/*
	** If the context switches due to device contention is > 50% 
	** consider tuning the disk i/o sub system
	*/
	if (@reco_device_contention > 50)
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider tuning your Disk I/O sub-system."
		print @blankline
		select @reco_hdr_prn = 1
	end
	/*
	** If the context switches due to the network is > 50% 
	** consider tuning the network I/O sub-system
	*/
	if (@reco_network_sent > 50 OR @reco_network_received > 50)
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider tuning your Network I/O sub-system."
		print @blankline
		select @reco_hdr_prn = 1
	end
end
print @blankline

return 0
go
exec sp_procxmode 'sp_sysmon_taskmgmt', 'anymode'
go
grant execute on sp_sysmon_taskmgmt to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_appmgmt')
begin
	drop procedure sp_sysmon_appmgmt
end
go
print "Installing sp_sysmon_appmgmt"
go

/* This stored procedure produces a report describing the scheduling
** of user tasks.
**
*/
create procedure sp_sysmon_appmgmt

        @NumEngines tinyint,    /* number of engines online */
        @NumElapsedMs int,      /* for "per Elapsed second" calculations */
        @NumXacts int,           /* for per transactions calculations */
        @applmon char(14)	/* Application monitoring option */
as

/* --------- declare local variables --------- */
declare @i smallint             /* loop index to iterate through multi-group 
                                ** counters (engine, disk, & buffer) */
declare @tmp_grp varchar(25)    /* temp var for building group_names 
                                ** ie. engine_N, disk_N */
declare @appl_name varchar(80)  /* application name */
declare @tmp_int int            /* temp var for integer storage */
declare @tmp_total int          /* temp var for integer storage, totals */
declare @sum1line char(80)      /* string to delimit total lines without 
                                ** percent calc on printout */  
declare @sum2line char(67)      /* string to delimit total lines with percent 
                                ** calc on printout */
declare @blankline char(1)      /* to print blank line */
declare @psign char(3)          /* hold a percent sign (%) for print out */
declare @na_str char(3)         /* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)       /* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */
declare @subsection char(80)	/* string to delimit sections on printout */
declare @applstr char(24)	/* application report string	*/
/* --------- Setup Environment --------- */
set nocount on                  /* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"              /* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section    = "==============================================================================="
select @subsection = "-------------------------------------------------------------------------------"


/* =========================  Application Management Section ==================== */
if not exists(select *
                from #tempmonitors
                where group_name = "kernel" and
                field_name = "priority_med")
begin
        print @blankline
        return 0
end

print @section
print @blankline
print "Application Management"
print "----------------------"
print @blankline
/*
** ------ 
*/
print "  Application Statistics Summary (All Applications)"
print "  -------------------------------------------------"
print "  Priority Changes                per sec      per xact       count  %% of total"
print @sum1line
select @tmp_total = sum(value)
  from #tempmonitors
  where group_name like "kernel"
        and field_name in ("priority_high", "priority_med", "priority_low")

if @tmp_total = 0       /* Avoid divide by zero errors - just print zero's */
 begin
	select @rptline = "  Total Priority Changes              0.0           0.0           0       n/a"
  	print @rptline
	print @blankline
 end
else
begin

	select @tmp_int = value
		from #tempmonitors
		where group_name = "kernel" and
       		   field_name = "priority_high"

	select @rptline = "    To High Priority" + space(9) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline
	select @tmp_int = value
		from #tempmonitors
		where group_name = "kernel" and
       		   field_name = "priority_med"

	select @rptline = "    To Medium Priority" + space(7) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline
	select @tmp_int = value
	from #tempmonitors
	where group_name = "kernel" and
          field_name = "priority_low"

	select @rptline = "    To Low Priority" + space(10) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign

	print @rptline

	print @sum2line
	select @rptline = "  Total Priority Changes" + space(5) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) + 
                        space(2) +
                        str(@tmp_total,10) 
	print @rptline
	print @blankline
end

select @tmp_total = sum(value)
  		from #tempmonitors
  		where group_name like "kernel"
       		 and field_name in ("tslice_high", "tslice_med", "tslice_low")

print "  Allotted Slices Exhausted       per sec      per xact       count  %% of total"
print @sum1line
if @tmp_total = 0       /* Avoid divide by zero errors - just print zero's */
 begin
	select @rptline = "  Total Slices Exhausted              0.0           0.0           0       n/a"
  	print @rptline
 end
else
begin
        select @tmp_int = value
        from #tempmonitors
        where group_name = "kernel" and
                  field_name = "tslice_high"
        
        select @rptline = "    High Priority" + space(12) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        print @rptline
        select @tmp_int = value
        from #tempmonitors
        where group_name = "kernel" and
                  field_name = "tslice_med"
        
        select @rptline = "    Medium Priority" + space(10) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        print @rptline
        select @tmp_int = value
        from #tempmonitors
        where group_name = "kernel" and
                  field_name = "tslice_low"
        
        select @rptline = "    Low Priority" + space(13) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        print @rptline

	print @sum2line
	select @rptline = "  Total Slices Exhausted  " + space(3) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) + 
                        space(2) +
                        str(@tmp_total,10) 
	print @rptline
end
print @blankline
print "  Skipped Tasks By Engine         per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
        field_name = "incompatible_engine_task"

if @tmp_total = 0       /* Avoid divide by zero errors - just print zero's */
 begin
        select @rptline = "  Total Engine Skips                  0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
        select @i = 0
        while @i < @NumEngines          /* for each engine */
          begin
                /* build group_name string */
                select @tmp_grp= "engine_" + convert(varchar(2), @i) 
                select @tmp_int = value
                  from #tempmonitors
                  where group_name = @tmp_grp and
                                field_name = "incompatible_engine_task"

                select @rptline = "    Engine " + convert(char(2),@i) + 
                                        space(16) +
                                        str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
                                        + space(2) +
                                        str(@tmp_int / convert(real, @NumXacts),12,1) 
                                        + space(2) +
                                        str(@tmp_int, 10) + space(5) +
                                        str(100.0 * @tmp_int / @tmp_total,5,1) 
                                        + @psign
                print @rptline
                select @i = @i + 1
          end

        if @NumEngines > 1
          begin
                print @sum2line 
                select @rptline = "  Total Engine Skips " + space(8) +
                                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) 
                                        + space(2) +
                                        str(@tmp_total / convert(real,@NumXacts),12,1) 
                                        + space(2) + str(@tmp_total,10)
                print @rptline
          end
  end
print @blankline

select @tmp_int = value
from #tempmonitors
where group_name = "kernel" and
          field_name = "calls_to_upsetenginemask"

select @rptline = "  Engine Scope Changes" + space(7) +
                        str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
                        space(2) +
                        str(@tmp_int / convert(real, @NumXacts),12,1) + 
                        space(2) +
                        str(@tmp_int,10) + space(7) +
                        @na_str
print @rptline
print @blankline

/* 
** If application monitoring was not requested
** return, otherwise, create a temporary table
** of application counters, based on application 
** monitoring option
*/

if (@applmon = "no_appl")
 begin
	return 0
 end
else 
 begin
	select field_name,group_name, value
	into #tempappl
	from #tempmonitors
	where 1=2
	
	if (@applmon = "appl_only")
	 begin
		insert into #tempappl
			select isnull(substring(field_name,1,
						patindex("%->%",field_name)-1),
						"Unknown")
				as field_name, group_name, value
          		from #tempmonitors
          		where group_name like "appl_%" and field_name is not null

        	select @applstr = space(2) + "Application: "
	 end

	else if (@applmon = "appl_and_login")
 	 begin
		insert into #tempappl
        		select field_name, group_name, value
          		from #tempmonitors
          		where group_name like "appl_%" and field_name is not null
        	select @applstr = space(2) + "Application->Login: "
	 end
 end

/*
** Declare cursor for fetching application specific statistics
*/
declare appl_stats cursor for
   select distinct field_name
   from #tempappl
   for read only
open appl_stats
fetch appl_stats into @appl_name

while (@@sqlstatus = 0) /* { */
 begin
        print @subsection
        select @rptline = @applstr + @appl_name
        print @rptline
        print @blankline
        print "  Application Activity            per sec      per xact       count  %% of total"
        print @sum2line

        select @tmp_total = sum(value)
                from #tempappl
        where group_name like "appl_%_ticks%"
        and field_name = @appl_name 
	
        if @tmp_total = 0       /* Avoid divide by zero errors - just print zero's */
         begin
                select @rptline = "  Total Activity                      0.0           0.0           0       n/a"
                print @rptline
                print @blankline
         end
	else
	 begin
			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_cpu_ticks%"
          			and field_name = @appl_name   	

       			select @rptline = "    CPU Busy" + space(17) +   
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline
			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_io_ticks%"
          			and field_name = @appl_name   	
       			select @rptline = "    I/O Busy" + space(17) +   
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline
			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_idle_ticks%"
          			and field_name = @appl_name   	
       			select @rptline = "    Idle    " + space(17) +   
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline
	 end

        print @blankline
        select @tmp_int = sum(value)
        from #tempappl
        where group_name like "appl_sched_count%"
        and field_name = @appl_name

        select @rptline = "    Number of Times Scheduled" + 
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                        	str(@tmp_int,10) + space(7) +
                        	@na_str
        print @rptline
        print @blankline

	print "  Application Priority Changes    per sec      per xact       count  %% of total"
	print @sum1line
	select @tmp_total = sum(value)
  	from #tempappl
  	where group_name like "appl_%_pri%"
        and field_name = @appl_name

	if @tmp_total = 0       /* Avoid divide by zero errors - just print zero's */
	 begin
        	select @rptline = "  Total Priority Changes              0.0           0.0           0       n/a"
        	print @rptline
        	print @blankline
 	 end
	else
	 begin

        	select @tmp_int = value
               	 from #tempappl
  			where group_name like "appl_hi_pri%"
        		and field_name = @appl_name

        	select @rptline = "    To High Priority" + space(9) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        	print @rptline
        	select @tmp_int = value
               		 from #tempappl
  			where group_name like "appl_med_pri%"
        		and field_name = @appl_name

        	select @rptline = "    To Medium Priority" + space(7) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        	print @rptline
                select @tmp_int = value
                         from #tempappl
                        where group_name like "appl_low_pri%"
                        and field_name = @appl_name

                select @rptline = "    To Low Priority" + space(10) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
                print @rptline
		print @sum2line
        	select @rptline = "  Total Priority Changes" + space(5) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total,10)
        	print @rptline
        	print @blankline
	 end

        print "  Application I/Os Completed     per sec      per xact       count  %% of total"
        print @sum1line
        select @tmp_total = sum(value)
        from #tempappl
        where group_name like "appl_%io_count%"
        and field_name = @appl_name

        if @tmp_total = 0       /* Avoid divide by zero errors - just print zero's */
         begin
                select @rptline = "  Total I/Os Completed                0.0           0.0           0       n/a"
                print @rptline
                print @blankline
         end
        else
         begin

                select @tmp_int = value
                 from #tempappl
                        where group_name like "appl_disk_io_count%"
                        and field_name = @appl_name

                select @rptline = "    Disk I/Os Completed" + space(6) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
                print @rptline
                select @tmp_int = value
                         from #tempappl
                        where group_name like "appl_net_io_count%"
                        and field_name = @appl_name

                select @rptline = "    Network I/Os Completed" + space(3) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
                print @rptline
                print @sum2line
                select @rptline = "  Total I/Os Completed" + space(7) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total,10)
                print @rptline
                print @blankline

	 end


        print "  Resource Limits Violated	per sec      per xact       count  %% of total"
        print @sum1line

        select @tmp_total = sum(value)
                from #tempappl
        where group_name like "%appl_%_lim_xcd%"
        and field_name = @appl_name 
	
        if (@tmp_total = 0) or (@tmp_total is null)       /* Avoid divide by zero errors - just print zero's */
         begin
                select @rptline = "  Total Limits Violated               0.0           0.0           0       n/a"
                print @rptline
                print @blankline
         end
	else
	 begin

			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_est_io_lim_xcd%"
          			and field_name = @appl_name   	

       			select @rptline = "    IO Limit Violations" 
			print @rptline
       			select @rptline = "      Estimated" + space(14) +   
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline


			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_act_io_lim_xcd%"
          			and field_name = @appl_name   	

       			select @rptline = "      Actual" + space(17) +   
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline
                	print @blankline


			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_batch_et_lim_xcd%"
          			and field_name = @appl_name   	

       			select @rptline = "    Time Limit Violations"
       			print @rptline

                	select @rptline = "      Batch" + space(18) +
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline


			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_xact_et_lim_xcd%"
          			and field_name = @appl_name   	

                	select @rptline = "      Xact" + space(19) +
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline
                	print @blankline


			select @tmp_int = sum(value)
                		from #tempappl
        			where group_name like "appl_rowcount_lim_xcd%"
          			and field_name = @appl_name   	

       			select @rptline = "    RowCount Limit Violations" +
         			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                		space(2) +
                		str(@tmp_int / convert(real, @NumXacts),12,1) +
                		space(2) +
 				str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) + @psign      
			print @rptline

                	print @sum2line
                	select @rptline = "  Total Limits Violated" + space(6) +
                        	str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        	space(2) +
                        	str(@tmp_total / convert(real, @NumXacts),12,1) +
                        	space(2) +
                        	str(@tmp_total,10)
                	print @rptline
                	print @blankline
	 end

	fetch appl_stats into @appl_name
	
 end
return 0
go
exec sp_procxmode 'sp_sysmon_appmgmt', 'anymode'
go
grant execute on sp_sysmon_appmgmt to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_esp')
begin
	drop procedure sp_sysmon_esp
end
go
print "Installing sp_sysmon_esp"
go

/* This stored procedure produces a report containing a summary of
** of how effectively the procedure cache is being utilized.
*/
create procedure sp_sysmon_esp
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int		/* for per transactions calculations */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "---------------------------  ------------  ------------  ----------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline

print "ESP Management                    per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = value
  from #tempmonitors
    where group_name = "access" and
	    field_name = "esp_requests"

select @rptline = "  ESP Requests" + space(15) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
										print @rptline

if @tmp_total !=0
  begin
	select @tmp_int = convert(int,m.value*(convert(float,n.value)/1000000))

	  from #tempmonitors m,#tempconfigures n
	  where m.group_name = "access" and
		m.field_name = "esp_total_exec_ticks" and   
		n.name = "sql server clock tick length"

	select @rptline = "  Avg. Time to Execute an ESP" + 
		str(convert(real,@tmp_int) / @tmp_total,12,5) + 
		" seconds"
	print @rptline

  end

return
go
exec sp_procxmode 'sp_sysmon_esp', 'anymode'
go
grant execute on sp_sysmon_esp to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_hk')
begin
	drop procedure sp_sysmon_hk
end
go
print "Installing sp_sysmon_hk"
go

/* This stored procedure produces a report containing a summary of
** SQL Server housekeeper activities.
*/
create procedure sp_sysmon_hk
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco	char(1),	/* Flag for recommendations */
	@instid smallint = NULL	/* optional SDC instance id */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum2line char(80)	
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted statistics line for print 
				** statement */
declare @section char(80)	/* string to delimit sections on printout */
/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare @char_str varchar(30)
declare @char_trimmed varchar(30)
declare @engines tinyint
declare @eng_count int
declare @tmp_grp_name varchar(80)
declare @reco_avg_busy real     /* Avg cpu busy utilization */
declare @reco_percent real	/* temp var for percentage storage */
declare @reco_idle_ticks real	/* temp var for percentage storage */
declare @reco_clock_ticks real	/* temp var for percentage storage */
declare @reco_dirty real
declare @reco_clean real

declare @i int

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @sum2line   = "                             ------------  ------------  ----------"
select @section = "==============================================================================="

/* ======================= Housekeeper Section =================== */
print @section
print @blankline
print "Housekeeper Task Activity"
print "-------------------------"
print "                                  per sec      per xact       count  %% of total"
print @sum2line

select @tmp_total = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
        field_name = "hk_wash"

if (@tmp_total > 0 )
begin
  select @rptline = "Buffer Cache Washes"
  
  print @rptline
  
  select @tmp_int2 = sum(value)
    from #tempmonitors
    where group_name like "buffer_%" and
          field_name = "hk_washclean"
  
  select @rptline = "  Clean" + space(22) +
  			str(@tmp_int2 / (@NumElapsedMs / 1000.0),11,1) 
  			+ space(2) +
  			str(@tmp_int2 / convert(real, @NumXacts),12,1) 
  			+ space(2) +
                        str(@tmp_int2, 10) + space(5) +
                        str(100.0 * @tmp_int2 / @tmp_total,5,1) + @psign

  select @reco_clean = convert(int, 100.0 * ((1.0* @tmp_int2) / @tmp_total))

  print @rptline
  
  select @tmp_int = @tmp_total - @tmp_int2
  
  select @rptline = "  Dirty" + space(22) +
  			str(@tmp_int / (@NumElapsedMs / 1000.0),11,1) 
  			+ space(2) +
  			str(@tmp_int / convert(real, @NumXacts),12,1) 
  			+ space(2) +
                        str(@tmp_int, 10) + space(5) +
                        str(100.0 * @tmp_int / @tmp_total,5,1) + @psign

  select @reco_dirty = convert(int, 100.0 * ((1.0* @tmp_int2) / @tmp_total))

  print @rptline
  
  print @sum2line
  
  select @rptline = "Total Washes" + space(17) +
  			str(@tmp_total / (@NumElapsedMs / 1000.0),11,1) 
  			+ space(2) +
  			str(@tmp_total / convert(real, @NumXacts),12,1) 
  			+ space(2) +
  			str(@tmp_total, 10)
  print @rptline
  
  print @blankline
end

select @tmp_int = value
  from #tempmonitors
  where group_name = "housekeeper" and
        field_name = "hk_gc_wakes"

select @rptline = "Garbage Collections" +  space(9) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
			+ space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) 
			+ space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = "housekeeper" and
        field_name = "hk_gc_numgoodpages"

select @rptline = "Pages Processed in GC" + space(8) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),11,1) 
			+ space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) 
			+ space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

print @blankline

select @tmp_int = value
  from #tempmonitors
  where group_name = "housekeeper" and
        field_name = "hk_stats_wakes"

select @rptline = "Statistics Updates" + space(11) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),11,1) 
			+ space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) 
			+ space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

print @blankline

if @Reco = 'Y'
 begin
	select @recotxt = "  Tuning Recommendations for Housekeeper"
	select @recoline = "  --------------------------------------"
	select @reco_hdr_prn = 0

	select @i = 0, @eng_count = 0


		select @engines = count(engine)
		from master.dbo.sysengines 
		where status != "offline"

	
	select @reco_clock_ticks = SUM(value)
          	from #tempmonitors
          	where group_name like "engine_%" and
               	 field_name = "clock_ticks" and
               	 value > 0

	select @reco_idle_ticks = SUM(value)
          	from #tempmonitors
          	where group_name like "engine_%" and
               	 field_name = "idle_ticks" and
               	 value > 0

       	select @reco_percent = 
		100.0 * ((@reco_clock_ticks - @reco_idle_ticks)/@reco_clock_ticks)

	if @engines > 1
	 begin
		select @reco_avg_busy = @reco_percent/@engines
	 end

	/*
	** If the average CPU busy is > 95% and if the
	** percentage of masses washed clean by HK is
	** greater than 95%, we have an overactive 
	** housekeeper which could be intruding with
	** user tasks, so reduce the 'housekeeper free write
	** percent' configuration parameter.
	*/
	if @reco_avg_busy > 95 AND @reco_clean > 95
	 begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end

		print "  - Consider decreasing the 'housekeeper free write percent'"
		print "    configuration parameter."
		select @reco_hdr_prn = 1
		print @blankline
	 end

	/*
	** If the average CPU busy is < 5% and if the
	** percentage of masses washed dirty by HK is
	** greater than 50%, we have a lot more washing to do
	** and since we have the cycles to do it, do it.
	*/
	if @reco_avg_busy < 5 AND @reco_dirty > 50
	 begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the 'housekeeper free write percent'"
		print "    configuration parameter."
		select @reco_hdr_prn = 1
		print @blankline
	 end
  end


return 0
go
go
exec sp_procxmode 'sp_sysmon_hk', 'anymode'
go
grant execute on sp_sysmon_hk to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_maccess')
begin
	drop procedure sp_sysmon_maccess
end
go
print "Installing sp_sysmon_maccess"
go

/* This stored procedure produces a report containing a summary of
** SQL Server monitor access.
*/
create procedure sp_sysmon_maccess
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco   char(1)         /* Flag for recommendations             */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum2line char(80)	
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted statistics line for print 
				** statement */
declare @section char(80)	/* string to delimit sections on printout */
/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare @char_str varchar(30)
declare @char_trimmed varchar(30)

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @sum2line   = "                             ------------  ------------  ----------  ----------"
select @section = "==============================================================================="

/* ======================= Monitor Access to Executing SQL Section =================== */
if not exists(select *
                from #tempmonitors
                where group_name = "monitor_access" and
                field_name = "spin_for_plan")
begin
        print @blankline
        return 0
end

print @section
print @blankline
print "Monitor Access to Executing SQL"
print "-------------------------------"
print "                                  per sec      per xact       count  %% of total"
print @sum2line

select @tmp_int = value
  from #tempmonitors
  where group_name = "monitor_access" and
        field_name = "spin_for_plan"

select @rptline = " Waits on Execution Plans" +  space(3) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) 
			+ space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) 
			+ space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = "monitor_access" and
        field_name = "sql_mon_txt_size_overflows"

select @rptline = " Number of SQL Text Overflows" +
			str(@tmp_int / (@NumElapsedMs / 1000.0),11,1) 
			+ space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) 
			+ space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = "monitor_access" and
        field_name = "sql_mon_txt_reqd_hwm"

select @rptline = " Maximum SQL Text Requested" +
			space(10) + @na_str + 
			space(11) + @na_str + 
			space(2) + str(@tmp_int, 10) +
			space(7) + @na_str
print @rptline
select @rptline = "  (since beginning of sample)"
print @rptline

print @blankline

if (@Reco = 'Y')
begin
	print @blankline
        select @recotxt =  " Tuning Recommendations for Monitor Access to Executing SQL"
        select @recoline = " ----------------------------------------------------------"
        select @reco_hdr_prn = 0

        select @tmp_total = 0
        select @tmp_int = 0
        select @tmp_int2 = 0

	select @tmp_int = convert(integer,value) from #tempconfigures
                        where name like "max SQL text monitored"

	if (@tmp_int > 0)
	begin
		select @tmp_int2 = value from #tempmonitors
  			where group_name = "monitor_access" and
			field_name = "sql_mon_txt_reqd_hwm"

		/*
		** If the high water mark for the sql text monitored
		** is greater than 'max SQL text monitored' consider
		** increasing the 'max SQL text monitored' configuration
		** parameter
		*/
		if (@tmp_int2 > @tmp_int)
         	begin
                        if (@reco_hdr_prn = 0)
                        begin
                                 print @recotxt
                                 print @recoline
                                 select @reco_hdr_prn = 1
                        end
			select @char_str = str(@tmp_int + ((@tmp_int2 - @tmp_int)/2))
			select @char_trimmed = ltrim(@char_str)
			print " - Consider increasing the 'max SQL text monitored' parameter "
			print "   to at least %1! (i.e., half way from its current value ", 
				@char_trimmed
			print "   to Maximum SQL Text Requested)."
                        print @blankline
         	end
		else 
		/*
		** If the 'max SQL text monitored' is greater than the
		** high water mark for sql text monitored
		** consider decreasing the 'max SQL text monitored' 
		** configuration parameter
		*/
		if (@tmp_int > @tmp_int2)
	 	begin
                        if (@reco_hdr_prn = 0)
                        begin
                                 print @recotxt
                                 print @recoline
                                 select @reco_hdr_prn = 1
                        end
			select @char_str = str(@tmp_int2 + ((@tmp_int - @tmp_int2)/2))
			select @char_trimmed = ltrim(@char_str)
			print " - Consider decreasing the 'max SQL text monitored' parameter "
			print "   to %1! (i.e., half way from its current value to Maximum ", 
				@char_trimmed
			print "   SQL Text Requested)."
                        print @blankline
         	end
	end
end
return 0
go
go
exec sp_procxmode 'sp_sysmon_maccess', 'anymode'
go
grant execute on sp_sysmon_maccess to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_xactsum')
begin
	drop procedure sp_sysmon_xactsum
end
go
print "Installing sp_sysmon_xactsum"
go

/* This stored procedure produces a report containing a summary of
** the type of activites performed by transactions running during
** the sampling period, including the number of transactions and 
** a summary of insert, update and delete activity.
**
*/
create procedure sp_sysmon_xactsum
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int		/* for per transactions calculations */
as

/* --------- declare local variables --------- */
declare @NumXactOps int		/* total # of rows affected by 
				** inserts/updates/deletes */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(67)	/* string to delimit total lines with percent 
				** calc on printout */
declare @sum3line char(67)	/* string to delimit total lines with percent 
				** calc on printout */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */
/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @sum3line   = "  =========================  ============  ============  =========="
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

/* ================ Transaction Profile Section ================= */
print @section
print @blankline
print "Transaction Profile"
print "-------------------"
print @blankline

/* -------- transaction summary ------------*/
print "  Transaction Summary             per sec      per xact       count  %% of total"
print @sum1line

select @rptline = "    Committed Xacts" + space(10) +
			str(@NumXacts / (@NumElapsedMs / 1000.0),12,1) + 
			space(11) + @na_str + space(2) +
			str(@NumXacts,10) + space(5) +	@na_str
print @rptline
print @blankline
  
/*
** transaction detail
*/

print "  Transaction Detail              per sec      per xact       count  %% of total"
print @sum1line

/* 
**  get total number of Transaction Operations for percentage 
**  calculations on total lines 
*/
select @NumXactOps = SUM(value)
  from #tempmonitors
  where (group_name = 'access' and field_name IN	
			("ncinsert", "cinsert","deferred_update",
			 "direct_inplace_update","direct_notinplace_update",
			 "direct_expensive_update","delete","bulk_fast_insert",
			 "mldml_ncinsert", "mldml_cinsert",
			 "mldml_direct_inplace_update",
			 "mldml_direct_notinplace_update",
			 "mldml_direct_expensive_update","mldml_delete"))
     OR (group_name = 'dolaccess' and field_name IN	
			("dolinsert","dolupdates", "doldelete_total",
			 "mldml_dolinsert","mldml_dolupdates", 
			 "mldml_doldelete_total"))

if @NumXactOps = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "  Total Rows Affected                 0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	print "  Inserts"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where (group_name = 'access' and
			field_name IN ("ncinsert", "cinsert", 
					"bulk_fast_insert", "mldml_ncinsert",
					"mldml_cinsert"))
	     or (group_name = 'dolaccess' and
			field_name IN ("dolinsert", "mldml_dolinsert"))

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total Rows Inserted               0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		print "    Fully Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "ncinsert"

		select @rptline = "      APL Heap Table" + space(9) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "cinsert"

		select @rptline = "      APL Clustered Table" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolinsert"

		select @rptline = "      Data Only Lock Table" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "bulk_fast_insert"

		select @rptline = "      Fast Bulk Insert" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print "    Minimally Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "mldml_ncinsert"

		select @rptline = "      APL Heap Table" + space(9) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "mldml_cinsert"

		select @rptline = "      APL Clustered Table" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_dolinsert"

		select @rptline = "      Data Only Lock Table" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

	  end		/* else */ 

	print @sum1line 
	select @rptline = "  Total Rows Inserted" + space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @NumXactOps,5,1) + @psign
	print @rptline
	print @blankline

	print "  Updates"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where (group_name = 'access' and field_name IN 
		("deferred_update","direct_inplace_update",
		 "direct_notinplace_update","direct_expensive_update",
		 "mldml_deferred_update","mldml_direct_inplace_update",
		 "mldml_direct_notinplace_update",
		 "mldml_direct_expensive_update"))
	     OR (group_name = 'dolaccess' and field_name IN ("dolupdates",
		 "mldml_dolupdates"))

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total Rows Updated                0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		print "    Fully Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "deferred_update"

		select @rptline = "      APL Deferred" + space(11) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "direct_inplace_update"

		select @rptline = "      APL Direct In-place" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) +space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "direct_notinplace_update"

		select @rptline = "      APL Direct Cheap" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "direct_expensive_update"

		select @rptline = "      APL Direct Expensive" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int2 = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolupdate_deferred"

		select @rptline = "      DOL Deferred" + space(11) +
				str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int2 / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int2, 10) + space(5) +
				str(100.0 * @tmp_int2 / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value - @tmp_int2
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolupdates"

		select @rptline = "      DOL Direct" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print "    Minimally Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "mldml_direct_inplace_update"

		select @rptline = "      APL Direct In-place" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) +space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "mldml_direct_notinplace_update"

		select @rptline = "      APL Direct Cheap" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "mldml_direct_expensive_update"

		select @rptline = "      APL Direct Expensive" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline


		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_dolupdates"

		select @rptline = "      DOL Direct" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

	  end

	print @sum1line 
	select @rptline = "  Total Rows Updated" + space(9) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @NumXactOps,5,1) + @psign
	print @rptline
	print @blankline


	print "  Data Only Locked Updates"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = 'dolaccess' and field_name IN 
		("dolupdate_replace", "mldml_dolupdate_shrink",
		 "dolupdate_expand_incfs", "mldml_dolupdate_expand_shift",
		 "dolupdate_expand_after_gc", 
		 "mldml_dolupdate_forward_firstlvl",
		 "dolupdate_forward_secondlvl",
		 "mldml_dolupdate_migrate_rowhome",
		 "mldml_dolupdate_replace", "mldml_dolupdate_shrink",
		 "mldml_dolupdate_expand_incfs", "mldml_dolupdate_expand_shift",
		 "mldml_dolupdate_expand_after_gc",
		 "mldml_dolupdate_forward_firstlvl",
		 "mldml_dolupdate_forward_secondlvl",
		 "mldml_dolupdate_migrate_rowhome")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total Rows Updated                0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin
 
		print "    Fully Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolupdate_replace"

		select @rptline = "      DOL Replace" + space(12) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolupdate_shrink"

		select @rptline = "      DOL Shrink" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolupdate_expand_incfs"

		select @rptline = "      DOL Cheap Expand" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = SUM(value)
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name in ("dolupdate_expand_shift",
				               "dolupdate_expand_after_gc" )

		select @rptline = "      DOL Expensive Expand" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = SUM(value)
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name in ("dolupdate_forward_firstlvl",
				               "dolupdate_forward_secondlvl")

		select @rptline = "      DOL Expand & Forward" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "dolupdate_migrate_rowhome"

		select @rptline = "      DOL Fwd Row Returned" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print "    Minimally Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_dolupdate_replace"

		select @rptline = "      DOL Replace" + space(12) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_dolupdate_shrink"

		select @rptline = "      DOL Shrink" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_dolupdate_expand_incfs"

		select @rptline = "      DOL Cheap Expand" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = SUM(value)
		  from #tempmonitors
		  where group_name = 'dolaccess' and
			field_name in ("dmldml_olupdate_expand_shift",
				       "mldml_dolupdate_expand_after_gc" )

		select @rptline = "      DOL Expensive Expand" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = SUM(value)
		  from #tempmonitors
		  where group_name = 'dolaccess' and
			field_name in ("mldml_dolupdate_forward_firstlvl",
				       "mldml_dolupdate_forward_secondlvl")

		select @rptline = "      DOL Expand & Forward" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_dolupdate_migrate_rowhome"

		select @rptline = "      DOL Fwd Row Returned" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline
	  end

	print @sum1line 
	select @rptline = "  Total DOL Rows Updated" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @NumXactOps,5,1) + @psign
	print @rptline
	print @blankline

	print "  Deletes"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where (group_name = 'access' and
			field_name IN ("delete", "mldml_delete"))
	     or (group_name = 'dolaccess' and
			field_name IN  ("doldelete_total",
					"mldml_doldelete_total"))

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total Rows Deleted                0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		print "    Fully Logged"
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "delete_deferred"

		select @rptline = "      APL Deferred" + space(11) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		/* Calc Direct Deletes as access.delete - access.delete_deferred */

		select @tmp_int2 = value - @tmp_int
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "delete"

		select @rptline = "      APL Direct" + space(13) +
				str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int2 / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int2, 10) + space(5) +
				str(100.0 * @tmp_int2 / @tmp_total,5,1) + @psign
			print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "doldelete_total"

		select @rptline = "      DOL" + space(20) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print "    Minimally Logged"

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'access' and
				field_name = "mldml_delete"

		select @rptline = "      APL Direct" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
			print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = 'dolaccess' and
				field_name = "mldml_doldelete_total"

		select @rptline = "      DOL" + space(20) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total Rows Deleted" + space(9) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @NumXactOps,5,1) + @psign
		print @rptline
	  end

	print @blankline
	print @sum3line 
	select @rptline = "  Total Rows Affected " + space(7) +
			str(@NumXactOps / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@NumXactOps / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@NumXactOps,10)
	print @rptline
	print @sum3line 
  end		/* else @NumXactOps != 0 */

print @blankline
return 0
go
exec sp_procxmode 'sp_sysmon_xactsum', 'anymode'
go
grant execute on sp_sysmon_xactsum to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_xactmgmt')
begin
	drop procedure sp_sysmon_xactmgmt
end
go
print "Installing sp_sysmon_xactmgmt"
go

/* This stored procedure produces a report containing a summary of
** log activity including activity in the user log caches.
*/
create procedure sp_sysmon_xactmgmt

	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco	char(1)		/* Flag for recommendations */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(67)	/* string to delimit total lines with 
				** percent calc on printout */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */
declare @discarded_subcmd int	/* # of ML-DML subcmds successfully discarded */
declare @logged_subcmd int	/* # of ML-DML subcmds which could not be
				** discarded and therefore had to be logged */
declare @fldml_plc_flush_full int /* PLC flushes due to full PLC accounted for
				  ** Fully Logged DML commands. */
declare @mldml_plc_flush_full int /* PLC flushes due to full PLC accounted for
				  ** Minimally Logged DML commands. */
declare @fldml_plc_flush_slr int  /* PLC flushes due to SLR logging accounted
				  ** for Fully Logged DML commands. */
declare @mldml_plc_flush_slr int  /* PLC flushes due to SLR logging accounted
				  ** for Minimally Logged DML commands. */


/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)	/* Header for tuning recommendation */
declare @recoline char(80)	/* to underline recotxt */
declare @reco_hdr_prn bit	/* to indicate if the recotxt is already printed */
declare @reco_by_slr real 	
declare @reco_by_full_ulc real

/* --------- Setup Environment --------- */
set nocount on					/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="


print @section
print @blankline

print "Transaction Management"
print "----------------------"
print @blankline
print "  ULC Flushes to Xact Log         per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = 'xls' and
		(field_name like "plc_flush_%" or 
		field_name like "mldml_plc_flush_%") and
		field_name != "plc_flush_discard" and
		field_name != "mldml_plc_flush_discard"

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "  Total ULC Flushes                   0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	print "  Any Logging Mode DMLs"

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_flush_endxact"

	select @rptline = "    by End Transaction" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_flush_xdeschange"

	select @rptline = "    by Change of Database" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_flush_unpin"

	select @rptline = "    by Unpin" + space(17) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = 'xls' and field_name IN 
		("plc_flush_pmscan")

	select @rptline = "    by Other" + space(17) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline
	print @blankline

	print "  Fully Logged DMLs"

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_flush_full"

	select @fldml_plc_flush_full = @tmp_int

	select @rptline = "    by Full ULC" + space(14) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_flush_slr_xact"

	select @fldml_plc_flush_slr = @tmp_int

	select @rptline = "    by Single Log Record" + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	print @blankline
	print "  Minimally Logged DMLs"

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_plc_flush_full"

	select @mldml_plc_flush_full = @tmp_int

	select @rptline = "    by Full ULC" + space(14) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @reco_by_full_ulc = convert(int, 100.0 *
			((1.0 * (@fldml_plc_flush_full + @mldml_plc_flush_full))
			/ @tmp_total))

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_plc_flush_slr_xact"

	select @mldml_plc_flush_slr = @tmp_int

	select @rptline = "    by Single Log Record" + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @reco_by_slr = convert(int, 100.0 *
			((1.0 * (@fldml_plc_flush_slr + @mldml_plc_flush_slr))
			/ @tmp_total))

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_plc_flush_beginsubcmd"

	select @rptline = "    by Start of Sub-Command" + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_plc_flush_endsubcmd"

	select @logged_subcmd = @tmp_int

	select @rptline = "    by End of Sub-Command" + space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline
	print @sum2line 
	select @rptline = "  Total ULC Flushes" + space(10) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10)
	print @rptline
  end

print @blankline
print "  ULC Flushes Skipped             per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = 'xls' and
                field_name in ("plc_flush_discard", "mldml_plc_flush_discard")

if @tmp_total = 0                       /* Avoid Divide by Zero Errors */
 begin
        select @rptline = "  Total ULC Skips                     0.0           0.0           0       n/a"
        print @rptline
 end
else
  begin
	print "  Fully Logged DMLs"
        select @tmp_int = value
          from #tempmonitors
          where group_name = 'xls' and
                        field_name = "plc_flush_discard"

        select @rptline = "    by ULC Discards" + space(10) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        print @rptline

	print "  Minimally Logged DMLs"
        select @tmp_int = value
          from #tempmonitors
          where group_name = 'xls' and
                        field_name = "mldml_plc_flush_discard"

	select @discarded_subcmd = @tmp_int

        select @rptline = "    by ULC Discards" + space(10) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
        print @rptline

        print @sum2line
        select @rptline = "  Total ULC Flushes Skips" + space(4) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total,10)
        print @rptline

  end

print @blankline
print "  ULC Log Records                 per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = 'xls' and
                field_name in ("plc_logrecs", "mldml_plc_logrecs")

if @tmp_total = 0                       /* Avoid Divide by Zero Errors */
 begin
        select @rptline = "  Total ULC Log Records               0.0           0.0           0       n/a"
        print @rptline
 end
else
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_logrecs"

	select @rptline = "  Fully Logged DMLs" + space(10) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_plc_logrecs"

	select @rptline = "  Minimally Logged DMLs" + space(6) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

        print @sum2line
        select @rptline = "  Total ULC Log Records" + space(6) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total,10)
        print @rptline
  end

print @blankline
print "  Max ULC Size During Sample"
print "  --------------------------"

select @tmp_int = value
  from #tempmonitors
  where group_name = 'xls' and
		field_name = "plc_maxused"

select @rptline = "  Fully Logged DMLs" + space(19) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = 'xls' and
		field_name = "mldml_plc_maxused"

select @rptline = "  Minimally Logged DMLs" + space(15) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline
print @blankline

print "  ML-DMLs Post Commit Scans       per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = 'xls' and
                field_name in ("mldml_pc_plc_scan", "mldml_pc_syslogs_scan")

if @tmp_total = 0                       /* Avoid Divide by Zero Errors */
 begin
        select @rptline = "  Total Post Commit Scans             0.0           0.0           0       n/a"
        print @rptline
 end
else
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_pc_plc_scan"

	select @rptline = "  ULC Scans" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "mldml_pc_syslogs_scan"

	select @rptline = "  Syslogs Scans" + space(14) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

        print @sum2line
        select @rptline = "  Total Post Commit Scans" + space(4) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total,10)
        print @rptline
  end

print @blankline
print "  ML-DMLs ULC Efficiency          per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = @discarded_subcmd + @logged_subcmd
if @tmp_total = 0                       /* Avoid Divide by Zero Errors */
 begin
        select @rptline = "  Total ML-DML Sub-Commands           0.0           0.0           0       n/a"
        print @rptline
 end
else
  begin
	select @tmp_int = @discarded_subcmd

	select @rptline = "  Discarded Sub-Commands" + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

	select @tmp_int = @logged_subcmd

	select @rptline = "  Logged Sub-Commands" + space(8) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
                                str(100.0 * @tmp_int / @tmp_total,5,1) +
                                @psign
	print @rptline

        print @sum2line
        select @rptline = "  Total ML-DML Sub-Commands" + space(2) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total,10)
        print @rptline
  end

print @blankline
print "  ULC Semaphore Requests"

select @tmp_total = value
  from #tempmonitors
  where group_name = 'xls' and
		field_name = "plc_lock_calls"

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "    Total ULC Semaphore Req           0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	select @tmp_int2 = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "plc_lock_waits"

	/* calculate "immediately granted" spinlocks */
	select @tmp_int = @tmp_total - @tmp_int2


	select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int/convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @rptline = "    Waited" + space(19) +
			str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int2 / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int2, 10) + space(5) +
			str(100.0 * @tmp_int2 / @tmp_total,5,1) + 
			@psign
	print @rptline

	print @sum2line 
	select @rptline = "  Total ULC Semaphore Req" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10)


	print @rptline
  end	/* else @tmp_total != 0 */

print @blankline

print "  Log Semaphore Requests"

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = 'xls' and
		field_name IN ("log_lock_granted", "log_lock_waited", "log_objectlock_needwait")

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "    Total Log Semaphore Req           0.0           0.0           0       n/a"
  	print @rptline
 end
else              
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "log_lock_granted"

	select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "log_lock_waited"

	select @rptline = "    Local Waited" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = 'xls' and
			field_name = "log_objectlock_needwait"

	select @rptline = "    Global Waited" + space(12) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	print @sum2line 
	select @rptline = "  Total Log Semaphore Req" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
  end

print @blankline



select @tmp_int = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name = "last_log_page_writes"

select @tmp_int = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name = "log_page_writes"

select @rptline = "  Transaction Log Writes" + space(5) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int2 = value
  from #tempmonitors
  where group_name = "access" and
		field_name = "log_page_allocations"         

select @rptline = "  Transaction Log Alloc" + space(6) +
			str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int2 / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int2, 10) + space(7) +
			@na_str
print @rptline

if @tmp_int2 != 0	/* avoid divide by zero errors */
  begin
	select @rptline = "  Avg # Writes per Log Page" + space(11) +
					@na_str + space(11) +
					@na_str + space(2) + 
					str(convert(real, @tmp_int) / @tmp_int2, 10,5) + space(7) +
					@na_str
	print @rptline
  end

print @blankline

if @Reco = 'Y'
 begin
	select @recotxt = "  Tuning Recommendations for Transaction Management"
	select @recoline = "  -------------------------------------------------"
	select @reco_hdr_prn = 0

	/*
	** If the % of flushes on account of ULC being full is > 20%
	** consider increasing the 'user log cache size'
	*/
	if @reco_by_full_ulc > 20
	 begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end
		
		print "  - Consider increasing the 'user log cache size'"
		print "    configuration parameter."
		print @blankline
		select @reco_hdr_prn = 1	
	 end

	/*
	** If the % of flushes on account of SLR is > 20%
	** and the % of flushes on account of ULC being full
	** is < 20% consider decreasing the user log cache size
	*/
	if @reco_by_slr > 20 and @reco_by_full_ulc < 20
	 begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider decreasing the 'user log cache size'"
		print "    configuration parameter if it is greater than the"
                print "    logical database page size."
		print @blankline
		select @reco_hdr_prn = 1
	 end
 end

return 0
go
exec sp_procxmode 'sp_sysmon_xactmgmt', 'anymode'
go
grant execute on sp_sysmon_xactmgmt to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_index')
begin
	drop procedure sp_sysmon_index
end
go
print "Installing sp_sysmon_index"
go

/* This stored procedure produces a report containing a summary of
** index behavior including deadlocks and page splits.
*/
create procedure sp_sysmon_index
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int		/* for per transactions calculations */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(80)
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */
/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "                             ------------  ------------  ----------"

select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline

print "Index Management"
print "----------------"
print @blankline

print "  Nonclustered Maintenance        per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = value
  from #tempmonitors
  where group_name = 'access' and
		field_name = "ncupdate"

select @rptline = "    Ins/Upd Requiring Maint" + space(2) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = 'access' and
		field_name = "ncupdate_indexes"

select @rptline = "      # of NC Ndx Maint" + space(6) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0
  begin
	select @rptline = "      Avg NC Ndx Maint / Op" + space(11) +
			@na_str + space(11) +
			@na_str +space(2) +
			str(convert(real, @tmp_int) / @tmp_total, 10,5) + 
			space(7) +
			@na_str
	print @rptline
  end

print @blankline

select @tmp_total = value
  from #tempmonitors where
  group_name = 'access' and
  field_name = "ncdelete"

select @rptline = "    Deletes Requiring Maint" + space(2) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = 'access' and
		field_name = "ncdelete_indexes"

select @rptline = "      # of NC Ndx Maint" + space(6) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0
  begin
	select @rptline = "      Avg NC Ndx Maint / Op" + space(11) +
			@na_str + space(11) +
			@na_str +space(2) +
			str(convert(real, @tmp_int) / @tmp_total, 10,5) + 
			space(7) +
			@na_str
	print @rptline
  end

print @blankline

select @tmp_total = value
  from #tempmonitors
  where group_name = 'access' and
		field_name = "ncrid_update"

select @rptline = "    RID Upd from Clust Split " +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = 'access' and
		field_name = "ncrid_update_indexes"

select @rptline = "      # of NC Ndx Maint" + space(6) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0
  begin
	select @rptline = "      Avg NC Ndx Maint / Op" + space(11) +
			@na_str + space(11) +
			@na_str +space(2) +
			str(convert(real, @tmp_int) / @tmp_total, 10,5) + 
			space(7) +
			@na_str
	print @rptline
  end

print @blankline


select @tmp_total = value
  from #tempmonitors
  where group_name = 'dolaccess' and
		field_name = "dolncdelete"

select @rptline = "    Upd/Del DOL Req Maint" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = 'dolaccess' and
		field_name = "dolncdelete_indexes"

select @rptline = "      # of DOL Ndx Maint" + space(5) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0
  begin
	select @rptline = "      Avg DOL Ndx Maint / Op" + space(10) +
			@na_str + space(11) +
			@na_str +space(2) +
			str(convert(real, @tmp_int) / @tmp_total, 10,5) + 
			space(7) +
			@na_str
	print @rptline
  end

print @blankline

select @tmp_total = sum(value)
  from #tempmonitors
  where (group_name = "access" and
		field_name IN ("split_index", "split_root"))
     OR (group_name = "btree" and
		field_name IN ("bt_leafsplit_count", "bt_noleafsplit_count"))

select @rptline = "  Page Splits" + space(16) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0			/* Avoid Divide by Zero Errors */
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "access" and
			field_name = "split_index_retry"

	select @rptline = "    Retries" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "access" and
			field_name = "split_index_deadlock"

	select @rptline = "    Deadlocks" + space(16) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where (group_name = "access" and
			field_name = "add_ind_level")
	     OR (group_name = "btree" and
			field_name = "bt_add_ind_level")

	select @rptline = "    Add Index Level" + space(10) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

  end

print @blankline

select @tmp_total = SUM(value)
  from #tempmonitors
  where (group_name = "access" and
		field_name like "shrink%")
     OR (group_name = "btree" and
		field_name IN ("bt_shrink_bylastdel", "bt_shrink_byscan",
			       "bt_shrink_nonleaf"))

select @rptline = "  Page Shrinks" + space(15) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline


if @tmp_total != 0			/* Avoid Divide by Zero Errors */
  begin
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "access" and
			field_name IN ("am_split_shrink_LOSTP", "am_split_shrink_WDP",
				"am_split_shrink_NWFP", "am_split_shrink_WDC",
				"am_split_shrink_NWFC", "am_split_shrink_WDNXT", 
				"am_split_shrink_NWFNX", "am_split_shrink_WDPRV",
				"am_split_shrink_NWFPRV")


	select @rptline = "    Deadlocks" + space(16) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "access" and
			field_name = "split_shrink_retries_exceeded"

	select @rptline = "    Deadlock Retries Exceeded" + 
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline
  end
if exists(select *
                from #tempmonitors
                where group_name = "access" and
                field_name = "forward_scans")
begin
print @blankline
print "  Index Scans                     per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = sum(value)
  from #tempmonitors
  where (group_name = 'access' and
                field_name in ("forward_scans","backward_scans"))
     OR (group_name = 'btree' and
                field_name in ("bt_forward_scans","bt_backward_scans"))

if @tmp_total = 0
 begin
	select @rptline = "    Total Scans                       0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @tmp_int = value
          from #tempmonitors
          where group_name = "access" and
                        field_name = "forward_scans"

	select @rptline = "    Ascending Scans        " + space(2) +
                        str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_int / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_int, 10) + space(5) +
                        str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
          from #tempmonitors
          where group_name = "btree" and
                        field_name = "bt_forward_scans"

	select @rptline = "    DOL Ascending Scans    " + space(2) +
                        str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_int / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_int, 10) + space(5) +
                        str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
          from #tempmonitors
          where group_name = "access" and
                        field_name = "backward_scans"

	select @rptline = "    Descending Scans       " + space(2) +
                        str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_int / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_int, 10) + space(5) +
                        str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
          from #tempmonitors
          where group_name = "btree" and
                        field_name = "bt_backward_scans"

	select @rptline = "    DOL Descending Scans   " + space(2) +
                        str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_int / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_int, 10) + space(5) +
                        str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	print @sum2line

	select @rptline = "    Total Scans            " + space(2) +
                        str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
                        space(2) +
                        str(@tmp_total / convert(real, @NumXacts),12,1) +
                        space(2) +
                        str(@tmp_total, 10)
	print @rptline

  end
end
print @blankline
return 0
go
exec sp_procxmode 'sp_sysmon_index', 'anymode'
go
grant execute on sp_sysmon_index to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_locks')
begin
	drop procedure sp_sysmon_locks
end
go
print "Installing sp_sysmon_locks"
go

/* This stored procedure produces a report containing a summary of
** of locking characteristics including lock requests and waits.
*/

create procedure sp_sysmon_locks

	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco char(1),
	@NumEngines tinyint	= 1 /* number of engines online */
as

/* --------- declare local variables --------- */

declare @TotalLocks int		/* Count Total Number of Locks */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_access int		/* temp var for integer storage */
declare	@tmp_xls int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(67)	/* string to delimit total lines with 
				** percent calc on printout */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* ------------- Variables for Suggested Recomendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @maxengfreelocks int    /* Value for max engine freelocks */
declare @max_online_engine int  /* Max online engine count */
declare @freelock_tr_blksize char(5) /* Freelock transfer block size */
declare @deadlocks int           /* Deadlock count */
declare @deadlock_search int    /* Deadlock Search count */
declare @tempmaxengfreelocks char(5) /* Temp maxengfreelocks for convert */
declare @curfreelocks int
declare @tot_movefreelock_toengine int
declare @tot_movefreelock_toserver int
declare @newval char(5)
declare @tmp_num_lock_op int
declare @reco_hdr_prn bit
declare @reco_lastpg_wait_percent real
declare @reco_avg_chain_length_pagerow real
declare @spinlock_contention float
declare @reco_tabspin_contention float
declare @reco_addrspin_contention float
declare @reco_fgspin_contention float
declare @totalrequested int
declare @totalretained int
declare @totaldiskreads int
declare @totaldeadlocks int
declare @totalwaits int
declare @totaltransfers int
declare @totallockmgrcalls int
declare @NumElapsedSec real
declare @totalreqs int
declare @totallocalmaster int
declare @totalgrants int
declare @totalbastreqs int


/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @recotxt =   "  Tuning Recommendations for Lock Management"
select @recoline="  ------------------------------------------"
select @section = "==============================================================================="

print @section
print @blankline

print "Lock Management"
print "---------------"
print @blankline
print "  Lock Summary                    per sec      per xact       count  %% of total"
print @sum1line

select @NumElapsedSec = @NumElapsedMs / 1000.0

select @TotalLocks = SUM(value)
  from #tempmonitors
  where group_name = "lock" and
		(field_name like "granted%" or field_name like "waited%")

select @totalretained = SUM(value)
  from #tempmonitors
  where group_name = "lock" and
		field_name like "clm_logical_retained"


select @rptline = "  Total Lock Requests" + space(8) +
			str(@TotalLocks / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@TotalLocks / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@TotalLocks,10) + space(7) +
			@na_str
print @rptline

if @TotalLocks != 0	/* Avoid Divide by Zero Errors after printout */
  begin
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name like "%waited%"

	select @rptline = "  Avg Lock Contention" + space(8) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @TotalLocks,5,1) + 
				@psign
	print @rptline
	select @rptline = "  Cluster Locks Retained" + space(5) +
				str(@totalretained / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@totalretained / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@totalretained, 10) + space(5) +
				str(100.0 * @totalretained / @TotalLocks,5,1) + 
				@psign
	print @rptline

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlocks"

	select @rptline = "  Deadlock Percentage" + space(8) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @TotalLocks,5,1) + 
				@psign
	print @rptline

	print @blankline

	/* 
	** Get spinlock related counters for hashtable spinlock contentions
	*/
	select  P.field_name as name,
		P.value as grabs,
		W.value as waits,
		S.value as spins 
	into #foo
	from #tempmonitors P, #tempmonitors W, #tempmonitors S
	where
			P.group_name = "spinlock_p_0"
		and W.group_name = "spinlock_w_0"
		and S.group_name = "spinlock_s_0"
		and P.field_id = W.field_id
		and P.field_id = S.field_id
		and P.field_name in ( 'fglockspins', 'tablockspins', 'addrlockspins')

	print "  Lock Detail                     per sec      per xact       count  %% of total"
	print @sum1line
	print @blankline

	print "  Table Lock Hashtable"
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "hashtab_lookups_table_lock"

	select @rptline = "    Lookups" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
	print @rptline

	/* Avoid divide by 0 error */
	if ( @tmp_int > 0 )
	begin
	    select @tmp_int2 = value
	      from #tempmonitors
	      where group_name = "lock" and
			    field_name = "hashtab_overflow_table_lock"

	    select @rptline = "    Avg Chain Length" + space(18) +
				    @na_str + space(11) +
				    @na_str + space(2) +
				    str(convert(real, @tmp_int2) / @tmp_int, 10, 5) +
				    space(7) + @na_str
	    print @rptline
	end

	select @spinlock_contention = isnull(avg(100.0*waits/grabs), 0)
	  from #foo
	 where name = 'tablockspins'
	   and grabs > 0

	select @rptline = "    Spinlock Contention" + space(15) +
						@na_str + space(11) +
						@na_str + space(9) +
						@na_str + space(5) +
						str( @spinlock_contention,5,1) 
							+ @psign
			, @reco_tabspin_contention = @spinlock_contention
	print @rptline
	print @blankline

	print "  Exclusive Table"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_EX_TAB" or 
				field_name like "waited%_EX_TAB")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total EX-Table Requests           0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin
		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_EX_TAB"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_EX_TAB"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
		print @sum1line 
		select @rptline = "  Total EX-Table Requests" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + 
			@psign
		print @rptline
        end
	print @blankline

	print "  Shared Table"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
	  (field_name like "granted%_SH_TAB" or field_name like "waited%_SH_TAB")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total SH-Table Requests           0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin
		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_SH_TAB"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_SH_TAB"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total SH-Table Requests" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + 
			@psign
		print @rptline
	  end
	print @blankline

	print "  Exclusive Intent"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_EX_INT" or 
				field_name like "waited%_EX_INT")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total EX-Intent Requests          0.0           0.0           0       n/a"
  		print @rptline
	end
	else
	  begin
		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_EX_INT"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_EX_INT"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total EX-Intent Requests" + space(3) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + 
			@psign
		print @rptline
	  end
	print @blankline

	print "  Shared Intent"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_SH_INT" or 
				field_name like "waited%_SH_INT")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total SH-Intent Requests          0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin
		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_SH_INT"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_SH_INT"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
		print @sum1line 

		select @rptline = "  Total SH-Intent Requests" + space(3) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + 
			@psign
		print @rptline
	end
	print @blankline

	print "  Page & Row Lock HashTable"
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "hashtab_lookups_pagerow_lock"

	select @rptline = "    Lookups" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) + @na_str
	print @rptline

	/* Avoid divide by 0 error */
	if ( @tmp_int > 0 )
	begin
	    select @tmp_int2 = value
	      from #tempmonitors
	      where group_name = "lock" and
			    field_name = "hashtab_overflow_pagerow_lock"

	    select @rptline = "    Avg Chain Length" +space(18)+
				    @na_str + space(11) +
				    @na_str + space(2) +
				    str(convert(real, @tmp_int2) / @tmp_int, 10, 5) +
				    space(7) + @na_str
			, @reco_avg_chain_length_pagerow = convert(real, @tmp_int2)/@tmp_int
	    print @rptline
	end
	else
	begin
	    select @reco_avg_chain_length_pagerow = 0
	end

	select @spinlock_contention = isnull(avg(100.0*waits/grabs), 0)
	  from #foo
	 where name = 'fglockspins'
	   and grabs > 0

	select @rptline = "    Spinlock Contention" + space(15) +
					@na_str + space(11) +
					@na_str + space(9) +
					@na_str + space(5) +
					str( @spinlock_contention,5,1) 
						+ @psign
			, @reco_fgspin_contention = @spinlock_contention
	print @rptline
	print @blankline

	print "  Exclusive Page"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_EX_PAGE" or 
				field_name like "waited%_EX_PAGE")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total EX-Page Requests            0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_EX_PAGE"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_EX_PAGE"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total EX-Page Requests" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
	  end
	print @blankline

	print "  Update Page"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_UP_PAGE" or 
				field_name like "waited%_UP_PAGE")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total UP-Page Requests            0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_UP_PAGE"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_UP_PAGE"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
        	select @rptline = "  Total UP-Page Requests" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
	  end
	print @blankline

	print "  Shared Page"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_SH_PAGE" or 
				field_name like "waited%_SH_PAGE")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total SH-Page Requests            0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_SH_PAGE"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_SH_PAGE"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total SH-Page Requests" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +

			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
		print @blankline
	  end
	print @blankline

	print "  Exclusive Row"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_EX_ROW" or 
				field_name like "waited%_EX_ROW")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total EX-Row Requests             0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_EX_ROW"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_EX_ROW"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total EX-Row Requests" + space(6) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
	  end
	print @blankline

	print "  Update Row"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_UP_ROW" or 
				field_name like "waited%_UP_ROW")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total UP-Row Requests             0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_UP_ROW"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_UP_ROW"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
        	select @rptline = "  Total UP-Row Requests" + space(6) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
	  end
	print @blankline

	print "  Shared Row"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_SH_ROW" or 
				field_name like "waited%_SH_ROW")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total SH-Row Requests             0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_SH_ROW"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_SH_ROW"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total SH-Row Requests" + space(6) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
		print @blankline
	  end
	print @blankline

	print "  Next-Key"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted%_SH_NKL" or 
				field_name like "waited%_SH_NKL")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total Next-Key Requests           0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted%_SH_NKL"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited%_SH_NKL"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total Next-Key Requests" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline
		print @blankline
	  end
	print @blankline

	print "  Address Lock Hashtable"
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "hashtab_lookups_address_lock"

	select @rptline = "    Lookups" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
	print @rptline

	/* Avoid divide by 0 error */
	if ( @tmp_int > 0 )
	begin
	    select @tmp_int2 = value
	      from #tempmonitors
	      where group_name = "lock" and
			    field_name = "hashtab_overflow_address_lock"

	    select @rptline = "    Avg Chain Length" +space(18)+
				    @na_str + space(11) +
				    @na_str + space(2) +
				    str(convert(real, @tmp_int2) / @tmp_int, 10, 5) +
				    space(7) + @na_str
	    print @rptline
	end

	select @spinlock_contention = isnull(avg(100.0*waits/grabs), 0)
	  from #foo
	 where name = 'addrlockspins'
	   and grabs > 0

	select @rptline = "    Spinlock Contention" + space(15) +
					@na_str + space(11) +
					@na_str + space(9) +
					@na_str + space(5) +
					str( @spinlock_contention,5,1) 
						+ @psign
			, @reco_addrspin_contention = @spinlock_contention
	print @rptline
	print @blankline

	print "  Exclusive Address"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted_%EX_ADDR" or 
				field_name like "waited_%EX_ADDR")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total EX-Address Requests         0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted_%EX_ADDR"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited_%EX_ADDR"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total EX-Address Requests  " +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real,@NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline

	  end
	print @blankline

	print "  Shared Address"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "lock" and
			(field_name like "granted_%SH_ADDR" or 
				field_name like "waited_%SH_ADDR")

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total SH-Address Requests         0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "granted_%SH_ADDR"

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @tmp_int = sum(value)
		  from #tempmonitors
		  where group_name = "lock" and
				field_name like "waited_%SH_ADDR"

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		print @sum1line 
		select @rptline = "  Total SH-Address Requests  " +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real,@NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @TotalLocks,5,1) + @psign
		print @rptline

		print @blankline
	  end
	print @blankline

	print "  Last Page Locks on Heaps"

	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = "access" and
		field_name = "locklastpage" 

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "    Total Last Pg Locks               0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int2 = value
		  from #tempmonitors
		  where group_name = "access" and
				field_name = "lklastpg_wait"

		select @tmp_int = @tmp_total - @tmp_int2

		select @rptline = "    Granted" + space(18) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

	    select @reco_lastpg_wait_percent = convert(int, 
				100.0 * ((1.0* @tmp_int2) / @tmp_total))

		select @rptline = "    Waited" + space(19) +
				str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int2 / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int2, 10) + space(5) +
				str(100.0 * @tmp_int2 / @tmp_total,5,1) + @psign
		print @rptline
		print @sum1line 
		select @rptline = "  Total Last Pg Locks"+ space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10) + space(5) +
			str(100.0 * @tmp_total / @tmp_total,5,1) + @psign
		print @rptline
		print @blankline
	  end
	print @blankline
  end


print "  Deadlocks by Lock Type          per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = value
  from #tempmonitors
  where group_name = "lock" and
		field_name = "deadlocks"

select @totaldeadlocks = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name like "physical_lock_deadlock"

select @tmp_access = SUM(value)
  from #tempmonitors
  where group_name = "access" and
                field_name in ("getrootpg_deadlock",
		               "lkindex_TSCK_deadlock",
                               "lkindex_deadlock",
                               "lkindDS_P_deadlock",
                               "lkindDS_C_deadlock",
                               "split_index_deadlock",
                               "log_lock_deadlock")
  
select @tmp_xls = value
  from #tempmonitors
  where group_name = "xls" and
                field_name = "log_lock_deadlock"

select @tmp_total = @tmp_total + @totaldeadlocks + @tmp_access + @tmp_xls

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "  Total Deadlocks                     0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_EX_TAB"

		select @rptline = "    Exclusive Table" + space(10) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_SH_TAB"

	select @rptline = "    Shared Table" + space(13) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_EX_INT"

	select @rptline = "    Exclusive Intent" + space(9) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_SH_INT"

	select @rptline = "    Shared Intent" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_EX_PAGE"

	select @rptline = "    Exclusive Page" + space(11) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_UP_PAGE"

	select @rptline = "    Update Page" + space(14) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_SH_PAGE"

	select @rptline = "    Shared Page" + space(14) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_EX_ROW"

	select @rptline = "    Exclusive Row" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_UP_ROW"

	select @rptline = "    Update Row" + space(15) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_SH_ROW"

	select @rptline = "    Shared Row" + space(15) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_SH_NKL"

	select @rptline = "    Shared Next-Key" + space(10) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline


	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_EX_ADDR"

	select @rptline = "    Exclusive Address" + space(8) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline
	
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_SH_ADDR"

	select @rptline = "    Shared Address" + space(11) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	/* Get the deadlocks for physical lock acquisition */
	select @rptline = "    Physical Locks      " + space(5) +
			str(@totaldeadlocks / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totaldeadlocks / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totaldeadlocks, 10) + space(5) +
			str(100.0 * @totaldeadlocks / @tmp_total,5,1) + @psign
	print @rptline

	/* Get the deadlocks for "access" group */
	select @tmp_access = SUM(value)
	 from #tempmonitors
	 where group_name = "access" and 
			field_name in ("getrootpg_deadlock",
					"lkindex_TSCK_deadlock",
					"lkindex_deadlock",
					"lkindDS_P_deadlock",
					"lkindDS_C_deadlock",
					"split_index_deadlock",
					"log_lock_deadlock") 

	/* Get the deadlocks for "xls" group */ 
	select @tmp_xls = value
	 from #tempmonitors
	 where group_name = "xls" and 
			field_name = "log_lock_deadlock"	

	/* Get the sum of the deadlocks(other than belonging to group locks) */
	select @tmp_int = @tmp_access + @tmp_xls
	
	select @rptline = "    Others" + space(19) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline


	print @sum2line 
	select @rptline = "  Total Deadlocks" + space(12) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
  end

print @blankline
select @tmp_total = value
  from #tempmonitors
  where group_name = "locks" and
                field_name = "clm_deadlocks"

if @tmp_total != 0			/* Avoid Divide by Zero Errors */
begin

	select @rptline = "  Total Cluster Deadlocks" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
end	

print @blankline
print @blankline

select @tmp_int2 = @tmp_total   /* save for deadlock search calc */

print "  Deadlock Detection"

select @tmp_total = value
  from #tempmonitors
  where group_name = "lock" and
		field_name = "deadlock_search"

	select @rptline = "    Deadlock Searches" + space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0			/* Avoid Divide by Zero Errors */
  begin

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "deadlock_alarm_skipped"

	select @rptline = "    Searches Skipped" + space(9) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @rptline = "    Avg Deadlocks per Search" + space(10) +
			@na_str + 
			space(11) +
			@na_str + 
			space(2) +
			str(convert(real,@tmp_int2) / @tmp_total,10,5) + 
			space(7) +
			@na_str
		print @rptline
  end
print @blankline
print @blankline

print "  Lock Promotions"

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name = "lock" and
	(	field_name like "promoted_%_PAGE"
	or      field_name like "promoted_%_ROW"
	or      field_name like "promoted_%_NKL")

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "    Total Lock Promotions             0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "promoted_EX_PAGE"

	select @rptline = "    Ex-Page to Ex-Table" + space(6) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "promoted_SH_PAGE"

	select @rptline = "    Sh-Page to Sh-Table" + space(6) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "promoted_EX_ROW"

	select @rptline = "    Ex-Row to Ex-Table" + space(7) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "promoted_SH_ROW"

	select @rptline = "    Sh-Row to Sh-Table" + space(7) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "promoted_SH_NKL"

	select @rptline = "    Sh-Next-Key to Sh-Table" + space(2) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	print @sum2line 
	select @rptline = "  Total Lock Promotions" + space(6) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
  end
print @blankline
print @blankline

print "  Lock Timeouts by Lock Type      per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = sum(value)
  from #tempmonitors
  where group_name = "lock" and
		field_name like "timedout%"

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
 begin
	select @rptline = "  Total Timeouts                      0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_EX_TAB"

		select @rptline = "    Exclusive Table" + space(10) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_SH_TAB"

	select @rptline = "    Shared Table" + space(13) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_EX_INT"

	select @rptline = "    Exclusive Intent" + space(9) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_SH_INT"

	select @rptline = "    Shared Intent" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_EX_PAGE"

	select @rptline = "    Exclusive Page" + space(11) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_UP_PAGE"

	select @rptline = "    Update Page" + space(14) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_SH_PAGE"

	select @rptline = "    Shared Page" + space(14) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_EX_ROW"

	select @rptline = "    Exclusive Row" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_UP_ROW"

	select @rptline = "    Update Row" + space(15) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_SH_ROW"

	select @rptline = "    Shared Row" + space(15) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_EX_ADDR"

	select @rptline = "    Exclusive Address" + space(8) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_SH_ADDR"

	select @rptline = "    Shared Address" + space(11) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "lock" and
			field_name = "timedout_SH_NKL"

	select @rptline = "    Shared Next-Key" + space(10) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	print @sum2line 

	select @rptline = "  Total Lock Timeouts" + space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
end

print @blankline
print "  Cluster Lock Summary            per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_lock_gc"
select @tmp_int = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_lockgc_target_collected"

if @tmp_total != 0	/* Avoid Divide by Zero Errors after printout */
begin
	print @blankline
	select @rptline = "   Lock Garbage Collection   " +
		str(@tmp_total / @NumElapsedSec,12,1) + 
		space(2) +
		str(@tmp_total / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@tmp_total, 10) + space(7) +
		@na_str
		
	print @rptline
	select @rptline = "     Targeted Collection Sucess" +
		space(7) +
		@na_str +
		space(11) +
		@na_str +
		space(2) +
		str(@tmp_int, 10) + space(5) +
		str(100.0 * @tmp_int/@tmp_total,5,1) + @psign
	print @rptline
	print @blankline
end
	
print @blankline
print "  Physical Locks Summary          per sec      per xact       count  %% of total"
print @sum1line

select @totalrequested = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
	field_name like "physical_lock_acquisition"

select @totalretained = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name like "physical_lock_retented"

select @totalwaits = sum(value)
  from #tempmonitors
  where group_name like "lock" and
		field_name like "physical_lock_waits"

select @totaltransfers = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name like "physical_lock_txrecv"

select @totaldiskreads = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name like "diskread_lockmgr"

select @totallockmgrcalls = sum(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name like "physical_lock_txrecv"

if @totalrequested = 0
begin
	print "No physical locks are acquired"
end
else
begin
	select @rptline = "    Total Lock Requests" + space(6) +
		str(@totalrequested  / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totalrequested  / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totalrequested, 10) + space(5) +
		str(100.0 * @totalrequested / @totalrequested,5,1) + @psign
	print @rptline

	select @rptline = "    Retained Locks    " + space(7) +
		str(@totalretained / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totalretained / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totalretained, 10) + space(5) +
		str(100.0 * @totalretained/@totalrequested,5,1) + @psign
	print @rptline

	select @rptline = "    Non-retained Locks" + space(7) +
		str((@totalrequested - @totalretained) / 
					@NumElapsedSec,12,1) + 
		space(2) +
		str((@totalrequested - @totalretained) / 
					convert(real, @NumXacts),12,1) + 
		space(2) +
		str((@totalrequested - @totalretained), 10) + space(5) +
		str(100.0 * (@totalrequested - @totalretained) / 
					@totalrequested,5,1) + @psign
	print @rptline

	select @rptline = "    Transfers Received  " + space(5) +
		str(@totaltransfers / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totaltransfers / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totaltransfers, 10) + space(5) +
		str(100.0 * @totaltransfers /@totalrequested,5,1) + @psign
	print @rptline

	select @rptline = "    Data Read from Disk" + space(6) +
		str(@totaldiskreads / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totaldiskreads / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totaldiskreads, 10) + space(5) +
		str(100.0 * @totaldiskreads /@totalrequested,5,1) + @psign
	print @rptline

	if (@totalrequested - @totalretained) = 0
	begin
		select @rptline = "    Physical Lock Contention" + space(1) +
			str(0 / @NumElapsedSec,12,1) + 
			space(2) +
			str(0 / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(0, 10) + space(5) +
			str(0.0 ,5,1) +
			@psign
	end
	else
	begin
		select @rptline = "    Physical Lock Contention" + space(1) +
			str(@totalwaits / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalwaits / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalwaits, 10) + space(5) +
			str(100.0 * @totalwaits /
				(@totalrequested - @totalretained),5,1) +
			@psign
		print @rptline
	end

	if @totallockmgrcalls = 0
	begin
		select @rptline = "    Data Location Efficiency" + space(9) +
			" n/a "  + 
			space(9) +
			" n/a "  + 
			space(7) +
			" n/a " + space(4) +
			str(100.0,5,1) + @psign
	end
	else
	begin
		select @rptline = "    Data Location Efficiency" + space(9) +
			" n/a "  + 
			space(9) +
			" n/a "  + 
			space(7) +
			" n/a " + space(4) +
			str(100.0 - (100.0 * @totaltransfers /
				@totallockmgrcalls),5,1) +
			@psign
	end

	print @rptline
end

select @totalreqs = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_physical_lockreqs"
select @totallocalmaster = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_physical_local_master"
select @totalwaits = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_physical_waited"
select @totalgrants = @totalreqs - @totalwaits

print @blankline
if @totalreqs != 0	/* Avoid Divide by Zero Errors after printout */
begin
	select @rptline = "    Cluster Lock Requests    " +
		str(@totalreqs / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totalreqs / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totalreqs, 10) + space(5) +
		str(100.0 * @totalreqs/@totalreqs,5,1) + @psign
	print @rptline
	select @rptline = "    Local Master       " + space(6) +
		str(@totallocalmaster / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totallocalmaster / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totallocalmaster, 10) + space(5) +
		str(100.0 * @totallocalmaster/@totalreqs,5,1) + @psign
	print @rptline
	if @totalreqs != 0
	begin
		select @rptline = "      Lock Granted      " + space(5) +
			str(@totalgrants / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalgrants / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalgrants, 10) + space(5) +
			str(100.0 * @totalgrants/@totalreqs,5,1) + @psign
		print @rptline
		select @rptline = "      Lock Waited       " + space(5) +
			str(@totalwaits  / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalwaits  / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalwaits, 10) + space(5) +
			str(100.0 * @totalwaits/@totalreqs,5,1) + @psign
		print @rptline
	end
end

select @totalbastreqs = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_physical_bast_requests"

if @totalbastreqs != 0	/* Avoid Divide by Zero Errors after printout */
begin
	select @rptline = "    Downgrade Req Recv       " +
		str(@totalbastreqs / @NumElapsedSec,12,1) + 
		space(11) +
		@na_str +
		space(2) +
		str(@totalbastreqs, 10) + 
		space(7) +
		@na_str 
	print @rptline
end

print @blankline
print "  Logical Locks Summary          per sec      per xact       count  %% of total"
print @sum1line
select @totalreqs = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_logical_lockreqs"
select @totallocalmaster = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_logical_local_master"
select @totalwaits = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_logical_waited"
select @totalgrants = @totalreqs - @totalwaits

if @totalreqs != 0	/* Avoid Divide by Zero Errors after printout */
begin
	select @rptline = "    Cluster Lock Requests    " +
		str(@totalreqs / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totalreqs / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totalreqs, 10) + space(5) +
		str(100.0 * @totalreqs/@totalreqs,5,1) + @psign
	print @rptline
	select @rptline = "    Local Master             " +
		str(@totallocalmaster / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totallocalmaster / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totallocalmaster, 10) + space(5) +
		str(100.0 * @totallocalmaster/@totalreqs,5,1) + @psign
	print @rptline
	if @totalreqs != 0
	begin
		select @rptline = "      Lock Granted      " + space(5) +
			str(@totalgrants / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalgrants / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalgrants, 10) + space(5) +
			str(100.0 * @totalgrants/@totalreqs,5,1) + @psign
		print @rptline
		select @rptline = "      Lock Waited       " + space(5) +
			str(@totalwaits / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalwaits / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalwaits, 10) + space(5) +
			str(100.0 * @totalwaits/@totalreqs,5,1) + @psign
		print @rptline
	end
end

select @totalbastreqs = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_logical_bast_requests"

if @totalbastreqs != 0	/* Avoid Divide by Zero Errors after printout */
begin
	select @rptline = "    Downgrade Req Recv       " +
		str(@totalbastreqs / @NumElapsedSec,12,1) + 
		space(11) +
		@na_str +
		space(2) +
		str(@totalbastreqs, 10)  +
		space(7) +
		@na_str 
	print @rptline
end	
	
print @blankline
print "  Object Locks Summary            per sec      per xact       count  %% of total"
print @sum1line

select @totalreqs = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_ocm_lockreqs"
select @totallocalmaster = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_ocm_local_master"
select @totalwaits = sum(value)
  	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_ocm_waited"
select @totalgrants = @totalreqs - @totalwaits

if @totalreqs != 0	/* Avoid Divide by Zero Errors after printout */
begin
	select @rptline = "    Cluster Lock Requests    " +
		str(@totalreqs / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totalreqs / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totalreqs, 10) + space(5) +
		str(100.0 * @totalreqs/@totalreqs,5,1) + @psign
	print @rptline
	select @rptline = "    Local Master             " +
		str(@totallocalmaster / @NumElapsedSec,12,1) + 
		space(2) +
		str(@totallocalmaster / convert(real, @NumXacts),12,1) + 
		space(2) +
		str(@totallocalmaster, 10) + space(5) +
		str(100.0 * @totallocalmaster/@totalreqs,5,1) + @psign
	print @rptline
	if @totalreqs != 0
	begin
		select @rptline = "      Lock Granted      " + space(5) +
			str(@totalgrants / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalgrants / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalgrants, 10) + space(5) +
			str(100.0 * @totalgrants/@totalreqs,5,1) + @psign
		print @rptline
		select @rptline = "      Lock Waited       " + space(5) +
			str(@totalwaits  / @NumElapsedSec,12,1) + 
			space(2) +
			str(@totalwaits  / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@totalwaits, 10) + space(5) +
			str(100.0 * @totalwaits/@totalreqs,5,1) + @psign
		print @rptline
	end
end

select @totalbastreqs = sum(value)
	from #tempmonitors
	where group_name like "lock" and
	field_name like "clm_ocm_bast_requests"
	
if @totalbastreqs != 0	/* Avoid Divide by Zero Errors after printout */
begin
	select @rptline = "    Downgrade Req Recv       " +
		str(@totalbastreqs / @NumElapsedSec,12,1) + 
		space(11) +
		@na_str +
		space(2) +
		str(@totalbastreqs, 10) + 
		space(7) +
		@na_str 
	print @rptline
end

/*****************  Tuning Recommendations  ************************/

if @Reco = 'Y'
begin
	select @reco_hdr_prn = 0
	print @blankline

	select @deadlocks = value from #tempmonitors
			    where group_name = "lock"
			    and field_name ="deadlocks"

	select @deadlock_search = value from #tempmonitors
				  where group_name="lock"
				  and field_name="deadlock_search"

	/*
	** If the number of deadlocks is 0 and the
	** number of times deadlock search was done
	** is greater than 0, consider increasing the
	** 'deadlock checking period' parameter
	*/
	if (@deadlocks = 0 and @deadlock_search >0)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the 'deadlock checking period' parameter"
		print "    by 50 ms." 
		print @blankline
	end
	/*
	** If the number of deadlocks is greated than 0 and the
	** number of times deadlock search was done is 0,
	** consider decreasing the 'deadlock checking period' parameter
	*/
	else if (@deadlocks > 0 and @deadlock_search=0)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider decreasing the 'deadlock checking period' parameter"
		print "    by 50 ms." 
		print @blankline
	end

	/*
	** If the percentage of waits on the last page
	** is > 10% consider partitioning the table or
	** increasing the number of partitions if the
	** table is already partitioned
	*/
	if (@reco_lastpg_wait_percent > 10)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider partitioning the heap tables or increasing the"
		print "    number of partitions on already partitioned heap tables."
		print @blankline
	end

	/*
	** If the average length of overflow chain for page & row lock 
	** hashtable  is > 4 consider increasing the 'lock hashtable size'
	** to the next power of 2 from the current configured value.
	*/
	if (@reco_avg_chain_length_pagerow > 4)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the value of 'lock hashtable size' "
		print "    configuration option. The value for this configuration "
		print "    option must be a power of 2."
		print @blankline
	end

	/*
	** If the number of engines is > 1 report recommendation for lock 
	** manager related spinlock contentions.
	*/
	if (@NumEngines > 1)
	begin /* { */
		/* 
		** if the contention on the fglock hashtable spinlocks 
		** is >= 10%, consider decreasing the 'lock spinlock ratio' 
		** config option.
		*/	
		if (@reco_fgspin_contention >= 10)
		begin
			if (@reco_hdr_prn = 0)
			begin /* { */
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end /* } */
			print "    - Consider reducing the 'lock spinlock ratio'."
			print @blankline
		end
		/* 
		** if the contention on the table lock hashtable spinlocks 
		** is >= 10%, consider decreasing the 'lock table spinlock 
		** ratio' config option.
		*/	
		if (@reco_tabspin_contention >= 10)
		begin
			if (@reco_hdr_prn = 0)
			begin /* { */
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end /* } */
			print "    - Consider reducing the 'lock table spinlock ratio'."
			print @blankline
		end
		/* 
		** if the contention on the address lock hashtable spinlocks 
		** is >= 10%, consider decreasing the 'lock address spinlock 
		** ratio' config option.
		*/	
		if (@reco_addrspin_contention >= 10)
		begin
			if (@reco_hdr_prn = 0)
			begin /* { */
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end /* } */
			print "    - Consider reducing the 'lock address spinlock ratio'."
			print @blankline
		end
	 end /* } */
end
print @blankline
return 0
go
exec sp_procxmode 'sp_sysmon_locks', 'anymode'
go
grant execute on sp_sysmon_locks to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_dcache_dtl')
begin
	drop procedure sp_sysmon_dcache_dtl
end
go
print "Installing sp_sysmon_dcache_dtl"
go

/* This stored procedure produces a report containing a summary of
** of how user defined caches and buffer pools are being used.
*/
if ((select object_id("#cachemap")) is not NULL)
begin
        drop table #cachemap
end
go

create table #cachemap (
        cid smallint,
        name varchar(255),
        group_name varchar(255),
        cache_status            char(24) null,
        cache_type              char(24) null,
        cache_config_size       char(24) null,
        cache_run_size          char(24) null,
        config_replacement      char(24) null,
        run_replacement         char(24) null)

go


if ((select object_id("#pool_detail_per_cache")) is not NULL)
begin
        drop table #pool_detail_per_cache
end
go

create table #pool_detail_per_cache (
          name          varchar(305),
          io_size       char(8)         /* Size of buffer pool as '2', '4',
                                        ** '8', '16' etc.
                                        */
)
go


create procedure sp_sysmon_dcache_dtl
        @NumEngines tinyint,    /* number of engines online */
        @NumElapsedMs int,      /* for "per Elapsed second" calculations */
        @NumXacts int,          /* for per transactions calculations */
        @Reco   char(1)         /* Flag for recommendations             */
as
/* --------- declare local variables --------- */
declare @CacheName varchar(255)  /* Cache Name from cache id lookup */
declare @CacheID smallint       /* Cache ID to map to buffer_N group */
declare @NumCaches smallint     /* Number of Caches to Report On */
declare @TotalSearches int      /* Total Cache Searches on All Caches */
declare @j smallint             /* loop index to iterate through multi-counter
                                ** counters (pool...) */
declare @lrgpool tinyint        /* boolean (0=No, 1=yes) logic to print
                                ** "Lrg Pool Not Used" Msg
                                */
declare @gtlogpgszpool tinyint    /* Boolean set while looking for a pool 
                                **  > logical pagesize in current cache
                                **      0 : Did not find pool
                                **      1 : Did find a pool of current size.
                                */
declare @tmp_grp varchar(25)    /* temp var for build group_name's
                                ** ie. engine_N, disk_N */
declare @cfg_repl varchar(24)   /* configured value of replacement policy */
declare @run_repl varchar(24)   /* run value of replacement policy */
declare @tmp_cntr varchar(35)   /* temp var for build field_name's
                                ** ie. bufgrab_Nk */
				/* temp var for building fieldname for
				** searches found in buffer pool */
declare @srchfound_cntr varchar(35)
declare @tmp_int int            /* temp var for integer storage */
declare @tmp_int2 int           /* temp var for integer storage */
declare @tmp_int3 int           /* temp var for integer storage used to read 
                                ** value of counter 'prefetch_kept_bp' */
declare @tmp_int4 int           /* temp var for integer storage used to read 
                                ** value of counter 'prefetch_cached_bp' */
declare @tmp_int_sum int        /* temp var for integer storage
                                ** @tmp_int_sum = @tmp_int3 + @tmp_int4 */
declare @tmp_total int          /* temp var for summing 'total #s' data */
declare @tmp_total_send int     /* temp var for summing 'total #s' data */
declare @tmp_total_recv int     /* temp var for summing 'total #s' data */
declare @tmp_float float        /* temp var for float storage */
declare @tmp_float2 float       /* temp var for float storage */
declare @numKBperpg int		/* number of kilobytes per logical page */
declare @subsection char(80)    /* string to delimit subsections on printout */
declare @sum1line char(80)      /* string to delimit total lines without
                                ** percent calc on printout */
declare @sum2line char(67)      /* string to delimit total lines with
                                ** percent calc on printout */
declare @blankline char(1)      /* to print blank line */
declare @psign char(3)          /* hold a percent sign (%) for print out */
declare @na_str char(3)         /* holds 'n/a' for 'not applicable' strings */
declare @zero_str char(80)      /* hold an output string for zero "  0.0" for
                                ** printing zero "% of total" */
declare @rptline varchar(530)    /* formatted stats line for print statement */
declare @section char(80)       /* string to delimit sections on printout */
declare @totalrequested int	/* total no of physical locks requested */
declare @totalretained int	/* total no of physical locks retained */
declare @totaldiskreads int	/* total no of diskreads completed for physical
				** lock acquisition.*/
declare @totaldeadlocks int     /* total no of deadlocks occured while taking
				** physical lock. */
declare @totaltransfers int	/* total no. of buffers transferred to this
				** instance. */
declare @totalwaits int		/* totan no. of times tasks had to wait for a
				** transfer to this instance. */
declare @totaldiskwrites int	/* total no of disk writes when a transfer
				** is requested.*/
declare @totallockmgrcalls int	/* total no. of times lock manager was 
				** consulted for physical lock. */
declare @NumElapsedSec real	/* No. of elapsed seconds */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt varchar(300)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare @spinlock_contention float

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @subsection = "-------------------------------------------------------------------------------"
select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"              /* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @zero_str   = "                                      0.0           0.0           0       n/a"
select @section = "==============================================================================="

/*
** Declare cursor to walk temp cache table in cache name
** order to print cache-specific statistics
*/
select @TotalSearches = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
                field_name = "bufsearch_calls"

declare cache_info cursor for
	select cid, name, group_name, 
		ltrim(rtrim(config_replacement)),ltrim(rtrim(run_replacement))
	  from #cachemap
	  order by name
	  for read only

open cache_info
fetch cache_info into @CacheID, @CacheName, @tmp_grp,@cfg_repl,@run_repl

/* 
** Get all Spinlock related counters and cache names
** for printing potential spinlock contention.
*/
select  P.field_name as name,
	P.value as grabs,
	W.value as waits,
	S.value as spins into #foo
from #tempmonitors P, #tempmonitors W, #tempmonitors S
where
	    P.group_name = "spinlock_p_0"
	and W.group_name = "spinlock_w_0"
	and S.group_name = "spinlock_s_0"
	and P.field_id = W.field_id
	and P.field_id = S.field_id
	and P.field_name in ( select name from #cachemap )

/* Create a #temp table to store information on currently configured
** pools for each cache.
*/
 
/* Initilize some variables to avoid divide by zero error */
if @NumElapsedMs = 0
begin
	select @NumElapsedMs = 1
end

if @NumXacts = 0
begin
	select @NumXacts = 1
end

select @NumElapsedSec = @NumElapsedMs / 1000.0

while (@@sqlstatus = 0) /* { */
  begin
	print @subsection
	select @rptline = space(2) + "Cache: " + @CacheName
	print @rptline
	print "                                  per sec      per xact       count  %% of total"
	print @sum1line

	/* Print spinlock contention */

	select @spinlock_contention =
			isnull(avg(100.0*waits/
				(case when grabs > 0 then grabs
				else (power(2.0,32) + grabs) end)), 0)
	  from #foo
	 where name = @CacheName
	   and grabs != 0
 
	select @rptline = "    Spinlock Contention" + space(15) +
						@na_str + space(11) +
						@na_str + space(9) +
						@na_str + space(5) +
						str( @spinlock_contention,5,1) 
							+ @psign
	print @rptline
	print @blankline

	if @TotalSearches != 0
	  begin
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufsearch_calls"

		select @rptline = "    Utilization " + space(22) +
						@na_str + space(11) +
						@na_str + space(9) +
						@na_str + space(5) +
						str(100.0 * @tmp_int / 
							@TotalSearches,5,1) + 
						@psign

		print @rptline
		print @blankline
	  end

	print "    Cache Searches"

	select @tmp_total = value
	  from #tempmonitors
	  where group_name = @tmp_grp and
			field_name = "bufsearch_calls"

	if @tmp_total = 0		/* Avoid Divide by Zero Errors */
 	begin
		select @rptline = "      Total Cache Searches            0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufsearch_finds"

		select @rptline = "      Cache Hits" + space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		/* save hits for wash % and missed calc */
		select @tmp_int2 = @tmp_int

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufsearch_finds_in_wash"
	
		if @tmp_int2 != 0
		begin
			select @rptline = "         Found in Wash" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_int2, 5, 1) + 
				@psign
			print @rptline
		end

		select @tmp_int = @tmp_total - @tmp_int2  /* missed searches */

		select @rptline = "      Cache Misses" + space(11) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
      end	/* else @tmp_total = 0 */

	print @sum2line
	select @rptline = "    Total Cache Searches" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline

	print @blankline


	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = @tmp_grp and
			field_name like "bufgrab_%k" and field_name not like "bufgrab_ref%k"

	select @numKBperpg = @@maxpagesize/1024
	if @tmp_total = 0
 	begin
		select @rptline = "    Pool Turnover                     0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
          begin /* { */
		print "    Pool Turnover"
		/* init loop ctr to loop through all pool sizes */
		select @j = @numKBperpg
                while (@j <= 8*@numKBperpg)        /* { */
		  begin

			/* 
			**  build pool specific counter name, 
			**  bufgrab_Nk (ie bufgrab_16k) 
			*/
			select @tmp_cntr = "bufgrab_" + rtrim(convert(varchar(3), @j)) + "k"

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = @tmp_grp and
					field_name = @tmp_cntr

                        if @tmp_int != 0        /* { */
			  begin

				select @rptline = space(6) + 
					convert(char(3),@j) + "Kb Pool"
				print @rptline

				select @rptline = "          LRU Buffer Grab" +
					space(4) +
					str(@tmp_int / (@NumElapsedMs / 
						1000.0),12,1) + 
					space(2) +
					str(@tmp_int / 
						convert(real, @NumXacts),12,1)+
					space(2) +
					str(@tmp_int, 10) + space(5) +
					str(100.0 * @tmp_int / @tmp_total,5,1)+
					@psign
				print @rptline

				select @tmp_cntr = "bufgrab_locked_" + 
					convert(varchar(3), @j) + "k"

				select @tmp_int2 = value
				  from #tempmonitors
				  where group_name = @tmp_grp and
						field_name = @tmp_cntr

				select @rptline = space(12) + "Grabbed Locked Buffer" +
					space(1) +
					str(@tmp_int2 / (@NumElapsedMs / 
						1000.0),7,1) + 
					space(2) +
					str(@tmp_int2 / 
						convert(real, @NumXacts),12,1)+
					space(2) +
					str(@tmp_int2, 10) + space(5) +
					str(100.0 * @tmp_int2 / @tmp_int,5,1) +
					@psign
				print @rptline

				select @tmp_cntr = "bufgrab_dirty_" + 
					convert(varchar(3), @j) + "k"

				select @tmp_int2 = value
				  from #tempmonitors
				  where group_name = @tmp_grp and
						field_name = @tmp_cntr

				select @rptline = space(12) + "Grabbed Dirty" +
					space(4) +
					str(@tmp_int2 / (@NumElapsedMs / 
						1000.0),12,1) + 
					space(2) +
					str(@tmp_int2 / 
						convert(real, @NumXacts),12,1)+
					space(2) +
					str(@tmp_int2, 10) + space(5) +
					str(100.0 * @tmp_int2 / @tmp_int,5,1) +
					@psign
				print @rptline

                          end   /* } if @tmp_int != 0 */
			  
			/* get next pool size (power of 2) */
			select @j = @j * 2 

                end             /* } while */


		print @sum2line		/* calc cache turnover percent of all caches */
		select @rptline = "    Total Cache Turnover" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
		print @rptline
          end   /* } else @tmp_total != 0 */
	print @blankline

	print "    Cluster Cache Behavior"

	select @totalrequested = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
			field_name like "physical_lock_acquisition"

	select @totalretained = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
				field_name = "physical_lock_retented"

	select @totaldeadlocks = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
				field_name = "physical_lock_deadlock"

	select @totalwaits = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
				field_name = "waited_on_tx"

	select @totaltransfers = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
			field_name = "physical_lock_txrecv"

	select @totaldiskreads = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
				field_name = "diskread_lockmgr"

	select @totaldiskwrites = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
				field_name = "diskwrite"

	select @totallockmgrcalls = sum(value)
		from #tempmonitors
		where group_name = @tmp_grp and
			field_name = "physical_lock_lockmgr"

	if @totalrequested = 0
	begin
		print "      No physical locks are acquired on buffers in this cache"
	end
	else
	begin
		select @rptline = "      Total Lock Requests    " +
			str(@totalrequested / @NumElapsedSec,12,1) +
			space(2) +
			str(@totalrequested / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@totalrequested, 10) + space(5) +
			str(100.0 * @totalrequested / @totalrequested,5,1) +
			@psign
		print @rptline
		
		select @rptline = "      Retained Locks         " +
			str(@totalretained / @NumElapsedSec,12,1) +
			space(2) +
			str(@totalretained / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@totalretained, 10) + space(5) +
			str(100.0 * @totalretained / @totalrequested,5,1) +
			@psign
		print @rptline
		
		select @rptline = "      Non-retained Locks     " +
			str((@totalrequested - @totalretained) / 
					@NumElapsedSec,12,1) +
			space(2) +
			str((@totalrequested - @totalretained) / 
					convert(real, @NumXacts),12,1) +
			space(2) +
			str((@totalrequested - @totalretained), 10) + space(5) +
			str(100.0 * (@totalrequested - @totalretained) / 
					@totalrequested,5,1) +
			@psign
		print @rptline
		
		select @rptline = "      Data Read from Disk    " +
			str(@totaldiskreads / @NumElapsedSec,12,1) +
			space(2) +
			str(@totaldiskreads / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@totaldiskreads, 10) + space(5) +
			str(100.0 * @totaldiskreads / @totalrequested,5,1) +
			@psign
		print @rptline
		
		select @tmp_total_recv = sum(value)
			from #tempmonitors
			where group_name like "buffer_%" and
				field_name = "physical_lock_txrecv"

		if @tmp_total_recv > 0
		begin
			select @rptline = "      Transfers Received     " +
				str(@totaltransfers / @NumElapsedSec,12,1) +
				space(2) +
				str(@totaltransfers / 
					convert(real, @NumXacts),12,1) +
				space(2) +
				str(@totaltransfers, 10) + space(5) +
				str(100.0 * @totaltransfers / 
					@totalrequested,5,1) + 
				@psign
			print @rptline
		end
		else
		begin
			select @rptline = "      Transfers Received     " +
				str(0.0,12,1) +
				space(2) +
				str(0.0,12,1) +
				space(2) +
				str(0.0, 10) + space(5) + 
				str(0.0,5,1) + @psign
			print @rptline
		end

		select @rptline = "      Waited for Data Transfer" +
			str(@totalwaits / @NumElapsedSec,11,1) +
			space(2) +
			str(@totalwaits / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@totalwaits, 10) + space(5) +
			str(100.0 * @totalwaits / @totalrequested,5,1) +
			@psign
		print @rptline
		
		select @rptline = "      Deadlocks              " +
			str(@totaldeadlocks / @NumElapsedSec,12,1) +
			space(2) +
			str(@totaldeadlocks / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@totaldeadlocks, 10) + space(5) +
			str(100.0 * @totaldeadlocks / @totalrequested,5,1) +
			@psign
		print @rptline
		
		select @rptline = "      Data Write to Disk     " +
			str(@totaldiskwrites / @NumElapsedSec,12,1) +
			space(2) +
			str(@totaldiskwrites / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@totaldiskwrites, 10) + space(5) + "  n/a "
		print @rptline
		
		select @tmp_total_send = sum(value)
			from #tempmonitors
			where group_name like "buffer_%" and
				field_name = "physical_lock_txsend"

		if @tmp_total_send > 0
		begin
			select @tmp_int = sum(value)
				from #tempmonitors
				where group_name = @tmp_grp and
					field_name = "physical_lock_txsend"

			select @rptline = "      Transfers Sent         " +
				str(@tmp_int / @NumElapsedSec,12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) + "  n/a "
			print @rptline
		end
		else
		begin
			select @rptline = "      Transfers Sent         " +
				str(0.0,12,1) +
				space(2) +
				str(0.0,12,1) +
				space(2) +
				str(0.0, 10) + space(5) + "  n/a "
			print @rptline
		end

		if (@totallockmgrcalls) = 0
		begin
			select @rptline = "      Data Location Efficiency " +
					space(7) +
					@na_str + space(11) +
					@na_str + space(9) +
					@na_str + space(5) +
					str(100.0,5,1) +
					@psign
		end
		else
		begin
			select @rptline = "      Data Location Efficiency " +
					space(7) +
					@na_str + space(11) +
					@na_str + space(9) +
					@na_str + space(5) +
					str(100.0 - (100.0 * @totaltransfers /
					(@totallockmgrcalls)),5,1) +
					@psign
		end
		print @rptline
	end

	print @blankline

	print "    Buffer Wash Behavior"

	select @tmp_total = value
	  from #tempmonitors
	  where group_name = @tmp_grp and
			field_name = "bufwash_throughput"

	if @tmp_total != 0	/* any buffers move through wash yet? */
	  begin

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufwash_pass_clean"

		select @rptline = "      Buffers Passed Clean" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufwash_pass_writing"

		select @rptline = "      Buffers Already in I/O " +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufwash_write_dirty"

		select @rptline = "      Buffers Washed Dirty   " +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
	  end
	else
		print "      Statistics Not Available - No Buffers Entered Wash Section Yet"

	print @blankline
	
	print "    Cache Strategy"

	/* 
	** Sum all buf unkeeps to look at % of buffers following 
	** MRU vs Discard Strategy 
	*/
	select @tmp_total = SUM(value)
	  from #tempmonitors
	  where group_name = @tmp_grp and
			field_name IN ("bufunkeep_lru", "bufunkeep_mru")

	if @tmp_total != 0
	  begin
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufunkeep_lru"

		select @rptline = "      Cached (LRU) Buffers   " +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "bufunkeep_mru"

		select @rptline = "      Discarded (MRU) Buffers"+
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
	  end
	else
		print "      Statistics Not Available - No Buffers Displaced Yet"

	print @blankline

	print "    Large I/O Usage"	

	select @tmp_total = value
	  from #tempmonitors
	  where group_name = @tmp_grp and
			field_name = "prefetch_req"

	if @tmp_total = 0
 	begin
		select @rptline = "      Total Large I/O Requests        0.0           0.0           0       n/a"
  		print @rptline
 	end
	else
	  begin

		select @tmp_int = SUM(value)
		  from #tempmonitors
		  where group_name = @tmp_grp and field_name IN
			 ("prefetch_as_requested", "prefetch_page_realign", "prefetch_increase")

		select @rptline = "      Large I/Os Performed" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
		print @blankline
		
		select @rptline="      Large I/Os Denied due to"
		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
			field_name = "prefetch_decrease"

		select @tmp_int3 = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
			field_name = "prefetch_kept_bp"

		select @tmp_int4 = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
			field_name = "prefetch_cached_bp"

		select @tmp_int_sum = @tmp_int3 + @tmp_int4
		select @tmp_int = @tmp_int - @tmp_int_sum

		select @rptline = "        Pool < Prefetch Size" + space(1) + 
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline

		select @rptline = "        Pages Requested"
		print @rptline
		select @rptline = "        Reside in Another"
		print @rptline

		select @rptline = "        Buffer Pool" + space(10) + 
				str(@tmp_int_sum / 
					(@NumElapsedMs / 	
					1000.0),12,1) +
					space(2) +
					str(@tmp_int_sum / 
					convert(real, @NumXacts),12,1) +
					space(2) +
					str(@tmp_int_sum, 10) + 
						space(5) +
					str(100.0 * 
						@tmp_int_sum/ 
						@tmp_total,5,1) + 
						@psign
		print @rptline
		print @sum2line 
		select @rptline = "    Total Large I/O Requests " +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_total,10)
		print @rptline
	  end	/* else */

	print @blankline

	print "    Large I/O Detail"

	/*
	**  default to NO large pools found for this cache 
	*/
	select @lrgpool = 0	
	/* 
	** init loop counter to loop through all large I/O pool 
	*/
	select @j = @numKBperpg*2
        while (@j <= 8*@numKBperpg)        /* { */
	  begin

          /* Check that the current cache has a pool configured of size @j */
          select @gtlogpgszpool = count(*)
          from #pool_detail_per_cache pd
          where pd.io_size = convert(varchar(8), @j)
	  and name = @CacheName	
 
          if (@gtlogpgszpool > 0)
          begin                 /* { */
 
                /* Remember that we _did_ find a large I/O pool */
                select @lrgpool = 1

		/* 
		** build pool specific counter name, 
		** bufgrab_Nk (ie bufgrab_16k) 
		*/
		select @tmp_cntr = "bufgrab_" + convert(varchar(3), @j) + "k"

		select @tmp_total = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = @tmp_cntr

                select @rptline = space(5) + convert(char(4),@j) +
			"Kb Pool"
		print @rptline

                if @tmp_total = 0
                begin
                        select @rptline = "        Pages Cached" + space(18) +
                                          ltrim(@zero_str)
                        print @rptline
 
                        select @rptline = "        Pages Used" + space(20) +
                                          ltrim(@zero_str)
                        print @rptline
                end
 
                else
                  begin

			/* turn # of masses into # of logical pages */
			select @tmp_total = @tmp_total * (@j / @numKBperpg)	

			select @rptline = "        Pages Cached" + space(9) +
				str(@tmp_total / 
					(@NumElapsedMs / 1000.0),12,1) + 
				space(2) +
				str(@tmp_total / 
					convert(real, @NumXacts),12,1) + 
				space(2) +
				str(@tmp_total,10) + space(7) +
				@na_str
			print @rptline

			select @tmp_cntr = "bufgrab_ref_" + 
				convert(varchar(3), @j) + "K"

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = @tmp_grp and
					field_name = @tmp_cntr

			select @rptline = "        Pages Used" + space(11) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
			print @rptline
		  end

                end     /* } if @gtlogpgszpool > 0 */

		select @j = @j * 2	/* get next pool size */
	  end /* } @j <= 8*@numKBperpg */

	if @lrgpool = 0		/* No large pools in this cache */
	  begin
		print "      No Large Pool(s) In This Cache"
	  end

        print @blankline

	print "    Dirty Read Behavior"
	
	select @tmp_total = value
	  from #tempmonitors
	  where group_name = @tmp_grp and
			field_name = "level0_bufpredirty"

	select @rptline = "	  Page Requests" + space(6) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10) + space(7) +
			@na_str
	print @rptline
	print @blankline

	if @Reco = 'Y'
 	begin /* { */
		select @recotxt =   "    Tuning Recommendations for Data cache : "+@CacheName
		select @recoline =  "    -------------------------------------"
       	 	select @reco_hdr_prn = 0

		/* recommendations for cache replacement policy */

		select @tmp_float = convert(int, (100.0*a.value/b.value))
		  from #tempmonitors a, #tempmonitors b
		  where a.group_name = @tmp_grp and
		  	b.group_name = @tmp_grp and
			a.group_name = b.group_name and
			a.field_name = "bufsearch_finds" and
			b.field_name = "bufsearch_calls" and
			b.value != 0
		  if (@tmp_float is not null)
		  begin /* { */
			select @tmp_float2 = 0
			select @tmp_float2 = (100.0*a.value)/b.value
	  		 from #tempmonitors a, #tempmonitors b
	  		 where a.group_name = @tmp_grp and
		  		b.group_name = @tmp_grp and
				a.group_name = b.group_name and
				a.field_name = "bufwash_write_dirty" and
				b.field_name = "bufwash_throughput" and
				b.value != 0

			if (@tmp_float2 is null)
				select @tmp_float2 = 0

			/* 
			** If the Cache Hit Rate is greater than 95% and
			** the replacement is less than 5% and if the
			** existing replacement policy is "strict LRU"
			** then consider using "relaxed lru replacement"
			** policy for this cache.
			*/
			if ((@tmp_float >= 95.0 and @tmp_float2 <= 5.0) and
				@NumEngines > 1)
         		begin /* { */
				if (@run_repl = "strict LRU")
				 begin /* { */
                			if (@reco_hdr_prn = 0)
                			begin /* { */
                       				print @recotxt
						print @recoline
                        			select @reco_hdr_prn = 1
                			end /* } */
                			print "    - Consider using 'relaxed LRU replacement policy'"
                			print "      for this cache." 
					print @blankline
				 end /* } */
         		end /* } */
			else
         		begin /* { */
			/* 
			** If the Cache Hit Rate is less than 95% and
			** the replacement is greater than 5% and if the
			** existing replacement policy is "relaxed LRU"
			** then consider using "Strict lru replacement"
			** policy for this cache.
			*/
				if (@run_repl = "relaxed LRU")
			 	begin /* { */
                			if (@reco_hdr_prn = 0)
                			begin /* { */
                       				print @recotxt
						print @recoline
                        			select @reco_hdr_prn = 1
                			end /* } */
                			print "    - Consider using 'strict LRU replacement policy'."
                			print "      for this cache." 
					print @blankline
			 	end /* } */
         		end /* } */
 		end /* } */

		/* recommendations for pool wash size */

		select @tmp_int = SUM(value)
	  		from #tempmonitors
	 		 where group_name = @tmp_grp  and
			field_name like "bufgrab_dirty_%"

		  if (@tmp_int is not null)
		  begin /* { */
			select @j = @numKBperpg
                	while (@j <= 8*@numKBperpg)    
		  	begin    /* { */

				/* 
				**  build pool specific counter name, 
				**  bufgrab_Nk (ie bufgrab_16k) 
				*/
				select @tmp_cntr = "bufgrab_dirty_" + 
						convert(varchar(3), @j) + "k"

				select @tmp_int = value
			  		from #tempmonitors
			  		where group_name = @tmp_grp and
					field_name = @tmp_cntr

                        	if @tmp_int != 0  
				begin /* { */
                			if (@reco_hdr_prn = 0)
                			begin /* { */
                       				print @recotxt
						print @recoline
                        			select @reco_hdr_prn = 1
                			end /* } */
					/*
					** If We grabbed a buffer that was
					** dirty from this pool consider increasing
					** the wash size for this buffer pool
					*/
                			select @rptline = "    - Consider increasing the 'wash size' of the "+ltrim(str(@j,3))+"k pool for this cache."
					print @rptline
					print @blankline

				end /* } */
				/* get next pool size (power of 2) */
				select @j = @j * 2 
			end /* } */	
				
		  end /* } */

		/* recommendations for pool addition */
		if (select value from #tempmonitors
	 		 where group_name = @tmp_grp  and
			field_name like "bufopt_lrgmass_reqd") > 0
                begin /* { */
                        if (@reco_hdr_prn = 0)
                        begin /* { */
                                print @recotxt
				print @recoline
                                select @reco_hdr_prn = 1
                        end /* } */
			/*
			** If the optimizer wanted to do large I/O but could
			** not find a buffer pool configured to be able
			** to do this large I/O consider having a large I/O
			** pool for this cache
			*/
                        print "    - Consider adding a large I/O pool for this cache."
			print @blankline
                end /* } */


		/* recommendations for pool removal */
		select @j = @numKBperpg*2
		select @tmp_cntr = "bufgrab_" + 
					convert(varchar(3), @j) + "k"
		select @srchfound_cntr = "bufsearch_finds_" +
					convert(varchar(3), @j) + "k"

		/*
		** The recommendation to remove a large buffer pool will be
		** printed only when the bufgrabs and bufsearch_finds are 0
		** for the buffer pool. This is to avoid
		** printing this message when the data is entirely cached
		** in the buffer pool and hence not having any grabs.
		*/
		if ((select value from #tempmonitors
	 		 where group_name = @tmp_grp  and
			field_name like @tmp_cntr) = 0
		   and (select value from #tempmonitors
			where group_name = @tmp_grp  and
			field_name like @srchfound_cntr) = 0
         	   and exists (select * from #pool_detail_per_cache 
          		where io_size = convert(varchar(8), @j)
          		and name = @CacheName))
		begin /* { */
			if (@reco_hdr_prn = 0)
			begin /* { */
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end /* } */
			/*
			** If there are no grabs for this buffer pool
			** consider removing this buffer pool.
			*/
                	select @rptline = "    - Consider removing the "+ltrim(str(@j,3))+"k pool for this cache."
			print @rptline
			print @blankline
		end /* } */

		select @j = @j*2
		select @tmp_cntr = "bufgrab_" + convert(varchar(3), @j) + "k"
		select @srchfound_cntr = "bufsearch_finds_" +
					convert(varchar(3), @j) + "k"

		if ((select value from #tempmonitors
	 		 where group_name = @tmp_grp  and
			field_name like @tmp_cntr) = 0
		   and (select value from #tempmonitors
			where group_name = @tmp_grp  and
			field_name like @srchfound_cntr) = 0
         	   and exists (select * from #pool_detail_per_cache 
          		where io_size = convert(varchar(8), @j)
          		and name = @CacheName))
		begin /* { */
			if (@reco_hdr_prn = 0)
			begin /* { */
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end /* } */
			/*
			** If there are no grabs for this buffer pool
			** consider removing this buffer pool.
			*/
                	select @rptline = "    - Consider removing the "+ltrim(str(@j,3))+"k pool for this cache."
			print @rptline
			print @blankline
		end /* } */

		select @j = @j*2
		select @tmp_cntr = "bufgrab_" + convert(varchar(3), @j) + "k"
		select @srchfound_cntr = "bufsearch_finds_" +
					convert(varchar(3), @j) + "k"

		if ((select value from #tempmonitors
	 		 where group_name = @tmp_grp  and
			field_name like @tmp_cntr) = 0
		   and (select value from #tempmonitors
			where group_name = @tmp_grp  and
			field_name like @srchfound_cntr) = 0
         	   and exists (select * from #pool_detail_per_cache 
          		where io_size = convert(varchar(8), @j)
          		and name = @CacheName))
		begin /* { */
			if (@reco_hdr_prn = 0)
			begin /* { */
				print @recotxt
				print @recoline
				select @reco_hdr_prn = 1
			end /* } */
			/*
			** If there are no grabs for this buffer pool
			** consider removing this buffer pool.
			*/
                	select @rptline = "    - Consider removing the "+ltrim(str(@j,3))+"k pool for this cache."
			print @rptline
			print @blankline
		end /* } */

		/* recommendations for cache splitting  */
	
		/*
		** If the number of engines is > 1 
		** and if the contention on the buffer
		** manager spinlock is > 10%
		** consider using cache partitions or named caches
		** or both
		** Also there are potential conditions where the waits or
		** grabs might go negative because of the counter overflowing
		** what an integer can hold; Cover for those cases as well.
		*/	
		if (@NumEngines > 1 and (@spinlock_contention >= 10  or
					@spinlock_contention < 0))
		 begin /* { */
                	if (@reco_hdr_prn = 0)
                	begin /* { */
                    		print @recotxt
				print @recoline
                     		select @reco_hdr_prn = 1
               		end /* } */
            		print "    - Consider using Named Caches or Cache partitions or both."
			print @blankline
		 end /* } */
	end /* } */

	fetch cache_info into @CacheID, @CacheName, @tmp_grp,@cfg_repl,@run_repl
  end  /* } while @@sqlstatus */

close cache_info
deallocate cursor cache_info

return 0
go
exec sp_procxmode 'sp_sysmon_dcache_dtl', 'anymode'
go
grant execute on sp_sysmon_dcache_dtl to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_dcache_sum')
begin
	drop procedure sp_sysmon_dcache_sum
end
go
print "Installing sp_sysmon_dcache_sum"
go

/* This stored procedure produces a report containing a summary of
** of how user defined caches and buffer pools are being used.
*/

if ((select object_id("#pool_detail_per_cache")) is not NULL)
begin
        drop table #pool_detail_per_cache
end
go

create table #pool_detail_per_cache (
          name          varchar(80),
          io_size       char(8)         /* Size of buffer pool as number of 
	  				** logical pages */
)
go

create procedure sp_sysmon_dcache_sum
        @NumEngines tinyint,    /* number of engines online */
        @NumElapsedMs int,      /* for "per Elapsed second" calculations */
        @NumXacts int,          /* for per transactions calculations */
        @Reco   char(1),        /* Flag for recommendations             */
	@instid smallint = NULL	/* optional SDC instance id */

as

/* --------- declare local variables --------- */
declare @TotalSearches int	/* Total Cache Searches on All Caches */
declare @j smallint		/* loop index to iterate through multi-counter 
				** counters (pool...) */
declare @tmp_cntr varchar(35)	/* temp var for build field_name's 
				** ie. bufgrab_Nk */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_int3 int           /* temp var for integer storage used to read 
                                ** value of counter 'prefetch_kept_bp' */
declare @tmp_int4 int           /* temp var for integer storage used to read
                                ** value of counter 'prefetch_cached_bp' */
declare @tmp_int_sum int        /* temp var for integer storage
                                ** @tmp_int_sum = @tmp_int3 + @tmp_int4 */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @tmp_float float        /* temp var for float storage */
declare @tmp_float2 float       /* temp var for float storage */
declare @sum2line char(67)	/* string to delimit total lines with 
				** percent calc on printout */
declare @numKBperpg int		/* number of kilobytes per logical page */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @zero_str char(80)	/* hold an output string for zero "  0.0" for 
				** printing zero "% of total" */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare	@ecache_size	int	/* configured size of extended cache */
declare @ecache_searches int	/* total number of searches in ecache */

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @zero_str   = "                                      0.0           0.0           0       n/a"
select @section = "==============================================================================="

print @section
print @blankline
print "Data Cache Management"
print "---------------------"
print @blankline
print "  Cache Statistics Summary (All Caches)"
print "  -------------------------------------"
print "                                  per sec      per xact       count  %% of total"
print "                             ------------  ------------  ----------  ----------"
print @blankline
print "    Cache Search Summary"

/*
** get total cache searches on all caches 
*/
select @TotalSearches = SUM(value)	
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name = "bufsearch_calls" 

select @tmp_int = SUM(value)		/* get cache hits on all caches */
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name = "bufsearch_finds"

select @tmp_int2 = @TotalSearches - @tmp_int  /* calc total cache misses */

/* Initilize some variables to avoid divide by zero error */
if @NumElapsedMs = 0
begin
	select @NumElapsedMs = 1
end

if @NumXacts = 0
begin
	select @NumXacts = 1
end

if @TotalSearches = 0			/* Avoid Divide by Zero Errors */
	print @zero_str
else
  begin

	select @rptline = "      Total Cache Hits" + space(7) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @TotalSearches,5,1) + 
			@psign
	print @rptline

	select @rptline="      Total Cache Misses" + space(5) +
			str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int2 / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int2, 10) + space(5) +
			str(100.0 * @tmp_int2 / @TotalSearches,5,1) + 
			@psign
	print @rptline

	print @sum2line 
	select @rptline = "    Total Cache Searches" + space(5) +
			str(@TotalSearches / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@TotalSearches / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@TotalSearches, 10)
	print @rptline
  end

/* Print extended cache statistics if extended cache is configured */
if (@instid is NULL)
	select @ecache_size = value
		from master.dbo.sysconfigures
		where comment = 'extended cache size'
else
begin
	select @ecache_size = value
		from master.dbo.sysconfigures
		where comment = 'extended cache size'


	if (@ecache_size is NULL)
		select @ecache_size = value
			from master.dbo.sysconfigures
			where comment = 'extended cache size'

end

if @ecache_size > 0
begin /* { */
	print @blankline
	print "    Secondary Cache Search Summary"

	/*
	** Ecache hit % = (ecache_read / ecache_srchcalls) * 100
	*/

	/* extended cache search calls */	
	select @ecache_searches = value
	  from #tempmonitors
	  where group_name = "ecache" and
			field_name = "ecache_srchcalls"

	/* extended cache search hits */	
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "ecache" and
			field_name = "ecache_read"

	/* extended cache misses */	
	select @tmp_int2 = @ecache_searches - @tmp_int

	if @ecache_searches = 0		/* Avoid Divide by Zero Errors */
		print @zero_str
	else
	  begin
		select @rptline="      Total Cache Hits" + space(7) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @ecache_searches,5,1) + 
				@psign
		print @rptline

		select @rptline="      Total Cache Misses" + space(5) +
				str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int2 / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int2, 10) + space(5) +
				str(100.0 * @tmp_int2 / @ecache_searches,5,1) + 
				@psign
		print @rptline

		print @sum2line 
		select @rptline="    Total Cache Searches" + space(5) +
				str(@ecache_searches / (@NumElapsedMs / 1000.0),12,1) + 
				space(2) +
				str(@ecache_searches / convert(real, @NumXacts),12,1) + 
				space(2) +
				str(@ecache_searches, 10)
		print @rptline
	  end
end /* } */
print @blankline

print "    Cache Turnover"

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name like "bufgrab_%k" and
		field_name not like "bufgrab_ref%k"

select @rptline = "      Buffers Grabbed" + space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0			/* Avoid Divide by Zero Errors */
  begin

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name like "bufgrab_dirty_%"

	select @rptline = "      Buffers Grabbed Dirty" + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline
  end
print @blankline

print "    Cache Strategy Summary"

/*
** Sum all buf unkeeps to look at % of buffers following 
** MRU vs Discard Strategy 
*/

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name IN ("bufunkeep_lru", "bufunkeep_mru")

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
	print @zero_str
else
  begin

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name = "bufunkeep_lru"

	select @rptline = "      Cached (LRU) Buffers" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name = "bufunkeep_mru"

	select @rptline = "      Discarded (MRU) Buffers" +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline
  end
print @blankline

print "    Large I/O Usage"

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name = "prefetch_req"

if @tmp_total = 0			/* Avoid Divide by Zero Errors */
	print @zero_str
else
  begin

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and field_name IN
		 ("prefetch_as_requested", "prefetch_page_realign", "prefetch_increase")

	select @rptline = "      Large I/Os Performed" + space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline
	print @blankline

	select @rptline="      Large I/Os Denied due to"
	print @rptline

	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
		field_name = "prefetch_decrease"

        select @tmp_int3 = value
          from #tempmonitors
          where group_name like "buffer_%" and
                field_name = "prefetch_kept_bp"

        select @tmp_int4 = value
          from #tempmonitors
                where group_name like "buffer_%" and
                        field_name = "prefetch_cached_bp"

	select @tmp_int_sum = @tmp_int3 + @tmp_int4

        select @tmp_int = @tmp_int - @tmp_int_sum

	select @rptline = "        Pool < Prefetch Size" + space(1) + 
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + 
			@psign
	print @rptline

        select @rptline = "        Pages Requested"
        print @rptline
        select @rptline = "        Reside in Another"
        print @rptline

        select @rptline = "        Buffer Pool" + space(10) +
                        str(@tmp_int_sum / 
				(@NumElapsedMs / 
				1000.0),12,1) +
                        	space(2) +
                        	str(@tmp_int_sum / 
					convert(real, @NumXacts),12,1) +
                        	space(2) +
                        	str(@tmp_int_sum, 10) + 
				space(5) +
                        	str(100.0 * 
					@tmp_int_sum / 	
					@tmp_total,5,1) +
                        		@psign
        print @rptline

	print @sum2line 
	select @rptline = "    Total Large I/O Requests " +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10)
	print @rptline
  end

print @blankline

print "    Large I/O Effectiveness"

/*
**  calc total # of (logical) pages brought into all caches from all 
**  large I/Os ( > logical pagesize)
*/

/*
**  init loop var's to loop through all possible pool sizes 
*/
select @numKBperpg = @@maxpagesize/1024
select @tmp_total = 0, @j = 2*@numKBperpg

while (@j <= 8*@numKBperpg)
  begin

	/* build pool specific counter name, bufgrab_Nk (ie bufgrab_16k) */
	select @tmp_cntr = "bufgrab_" + convert(varchar(3), @j) + "k"

	select @tmp_total = @tmp_total + (SUM(value) * (@j / @numKBperpg))
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name = @tmp_cntr

	select @j = @j * 2
  end
  
select @rptline = "      Pages by Lrg I/O Cached" +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10) + space(7) +
			@na_str
print @rptline

select @tmp_cntr = "bufgrab_ref_" + convert(varchar(3), @numKBperpg) + "K"

if @tmp_total != 0	/* Avoid Divide by Zero Errors after printout */
  begin
	select @tmp_int = SUM(value)
	  from #tempmonitors
	  where group_name like "buffer_%" and
			field_name like "bufgrab_ref_%K" and
			field_name != @tmp_cntr

	select @rptline = "      Pages by Lrg I/O Used" + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
	print @rptline
  end
print @blankline


if exists(select *
                from #tempmonitors
                where group_name = "access" and
                field_name like "apf%")
begin /*{*/


		print "    Asynchronous Prefetch Activity"

		select @tmp_total= sum(value)
		  from #tempmonitors
		  where group_name = "access" and
				field_name in ("apf_IOs_issued", "apf_could_not_start_IO_immediately",
						"apf_configured_limit_exceeded", "apf_unused_read_penalty",
						"apf_found_in_cache_with_spinlock", "apf_found_in_cache_wo_spinlock")

		if @tmp_total = 0                       /* Avoid Divide by Zero Errors */
			print @zero_str
		else
		  begin
			select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_IOs_issued"

			select @rptline = "      APFs Issued" + space(12) +
						str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
						space(2) +
						str(@tmp_int / convert(real, @NumXacts),12,1) +
						space(2) +
						str(@tmp_int, 10) + space(5) +
						str(100.0 * @tmp_int / @tmp_total,5,1) +
						@psign
			print @rptline

			select @rptline = "      APFs Denied Due To" 
			print @rptline


			select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_could_not_start_IO_immediately"
			
			select @rptline = "        APF I/O Overloads " + space(3) +
					       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
					       space(2) +
					       str(@tmp_int / convert(real, @NumXacts),12,1) +
					       space(2) +
					       str(@tmp_int, 10) + space(5) +
					       str(100.0 * @tmp_int / @tmp_total,5,1) +
					       @psign
			print @rptline

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_configured_limit_exceeded"

			select @rptline = "        APF Limit Overloads " + space(1) +
					       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
					       space(2) +
					       str(@tmp_int / convert(real, @NumXacts),12,1) +
					       space(2) +
					       str(@tmp_int, 10) + space(5) +
					       str(100.0 * @tmp_int / @tmp_total,5,1) + 
					       @psign
			print @rptline

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_unused_read_penalty"
			
			select @rptline = "        APF Reused Overloads " + 
					       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
					       space(2) +
					       str(@tmp_int / convert(real, @NumXacts),12,1) +
					       space(2) +
					       str(@tmp_int, 10) + space(5) +
					       str(100.0 * @tmp_int / @tmp_total,5,1) +
					       @psign
			print @rptline

			select @rptline = "      APF Buffers Found in Cache" 
			print @rptline

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_found_in_cache_with_spinlock"
			
			select @rptline = "        With Spinlock Held" + space(3) +
					       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
					       space(2) +
					       str(@tmp_int / convert(real, @NumXacts),12,1) +
					       space(2) +
					       str(@tmp_int, 10) + space(5) +
					       str(100.0 * @tmp_int / @tmp_total,5,1) +
					       @psign
			print @rptline

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_found_in_cache_wo_spinlock"
			
			select @rptline = "        W/o Spinlock Held " + space(3) +
					       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
					       space(2) +
					       str(@tmp_int / convert(real, @NumXacts),12,1) +
					       space(2) +
					       str(@tmp_int, 10) + space(5) +
					       str(100.0 * @tmp_int / @tmp_total,5,1) +
					       @psign
			print @rptline

			print @sum2line
			select @rptline = "    Total APFs Requested " + space(4) +
					str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) +
					space(2) +
					str(@tmp_total / convert(real, @NumXacts),12,1) +
					space(2) +
					str(@tmp_total,10)
			print @rptline
		  end

		print @blankline

		print "    Other Asynchronous Prefetch Statistics"

		select @tmp_int = value
			  from #tempmonitors
			  where group_name = "access"
			  and field_name = "apf_IOs_used"

		select @rptline = "      APFs Used" + space(14) +
						str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
						space(2) +
						str(@tmp_int / convert(real, @NumXacts),12,1) +
						space(2) +
						str(@tmp_int, 10) + space(7) +
						@na_str
		print @rptline

		select @tmp_int = value
			from #tempmonitors
			where group_name = "access"
			and field_name = "apf_waited_for_IO_to_complete"

		select @rptline = "      APF Waits for I/O" + space(6) +
			       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			       space(2) +
			       str(@tmp_int / convert(real, @NumXacts),12,1) +
			       space(2) +
			       str(@tmp_int, 10) + space(7) +
			       @na_str
		print @rptline

		select @tmp_int = sum(value)
			from #tempmonitors
			where field_name like "apf%discard%"

		select @rptline = "      APF Discards" + space(11) +
			       str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			       space(2) +
			       str(@tmp_int / convert(real, @NumXacts),12,1) +
			       space(2) +
			       str(@tmp_int, 10) + space(7) +
			       @na_str
		print @rptline
end /*}*/
print @blankline


print "    Dirty Read Behavior"
	
select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "buffer_%" and
		field_name = "level0_bufpredirty"

select @rptline = "      Page Requests" + space(10) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total,10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0	/* Avoid Divide by Zero Errors after printout */
  begin

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "access" and
			field_name = "dirty_read_restarts"

	if @tmp_int != 0
	 begin
		select @rptline = "      Re-Starts" + space(10) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + 
				@psign
		print @rptline
	 end
  end
print @blankline

/*
** If requested, print global cache recommendations (if any)
*/

if @Reco = 'Y'
 begin
	select @recotxt =     "  Tuning Recommendations for All Caches"
	select @recoline = "  -------------------------------------"
        select @reco_hdr_prn = 0
        /* recommendations for apf */
        select @tmp_float = convert(int, (100.0*a.value/b.value))
        	from #tempmonitors a, #tempmonitors b
        	where   a.group_name = "access"
        	and     a.field_name = "apf_IOs_issued"
        	and     b.group_name = "access"
        	and     b.field_name in ("apf_IOs_issued", "apf_could_not_start_IO_immediately",
                                        "apf_configured_limit_exceeded", "apf_unused_read_penalty",
                                        "apf_found_in_cache_with_spinlock", "apf_found_in_cache_wo_spinlock")
		and 	b.value != 0 
	 if (@tmp_float is not null)
	 begin
        	select @tmp_int = value
        	from #tempmonitors
        	where   group_name = "access"
        	and     field_name = "apf_configured_limit_exceeded"

		/*
		** If the number of APF I/O's issued is greater
		** than 80% and if the APF configured limit 
		** exceeded 0 during the sampling interval
		** consider increasing the apf limits for the
		** pool or globally for all the pools
		*/
        	if (@tmp_float > 80.0 and @tmp_int > 0)
         	begin
               	 	if (@reco_hdr_prn = 0)
               	 	begin
                       		 print @recotxt
                       		 print @recoline
                       	 	 select @reco_hdr_prn = 1
                	end
                	print "  - Consider increasing the 'global asynchronous prefetch limit' parameter"
                	print "    (and the 'local asynchronous prefetch limit' parameter for each pool " 
                	print "    for which this was overidden) by 10%%." 
                	print @blankline
         	end
 	 end
 end

return 0
go
exec sp_procxmode 'sp_sysmon_dcache_sum', 'anymode'
go
grant execute on sp_sysmon_dcache_sum to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_dcache')
begin
	drop procedure sp_sysmon_dcache
end
go
print "Installing sp_sysmon_dcache"
go

/* This stored procedure produces a report containing a summary of
** of how user defined caches and buffer pools are being used.
*/

create procedure sp_sysmon_dcache
	@NumEngines tinyint,	/* number of engines online */
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
        @Reco   char(1),        /* Flag for recommendations             */
	@instid smallint = NULL	/* optional SDC instance id */

as

exec sp_sysmon_dcache_sum @NumEngines, @NumElapsedMs, @NumXacts, @Reco, @instid

exec sp_sysmon_dcache_dtl @NumEngines, @NumElapsedMs, @NumXacts, @Reco  

return 0
go
exec sp_procxmode 'sp_sysmon_dcache', 'anymode'
go
grant execute on sp_sysmon_dcache to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_pcache')
begin
	drop procedure sp_sysmon_pcache
end
go
print "Installing sp_sysmon_pcache"
go

/* This stored procedure produces a report containing a summary of
** of how effectively the procedure cache is being utilized.
*/
create procedure sp_sysmon_pcache
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco	char(1)		/* Flag for recommendations */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @tmp_reco_total int	/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)       /* Header for tuning recommendation */
declare @recoline char(80)      /* to underline recotxt */
declare @reco_hdr_prn bit       /* to indicate if the recotxt is already printed */
declare @reco_phdr_read_from_disk real

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "---------------------------  ------------  ------------  ----------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline

print "Procedure Cache Management        per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "procedure_requests"

select @rptline = "  Procedure Requests" + space(9) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total !=0
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "procmgr" and
			field_name = "procedure_reads"

	select @rptline = "  Procedure Reads from Disk" + space(2) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

    select @reco_phdr_read_from_disk = 
			convert(int, 100.0 * ((1.0* @tmp_int) / @tmp_total))

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "procmgr" and
			field_name = "procedure_writes"

	select @rptline = "  Procedure Writes to Disk" + space(3) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "procmgr" and
			field_name = "procedure_removes"

	select @rptline = "  Procedure Removals" + space(9) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

	print @rptline

	select @tmp_reco_total = sum(value)
	  from #tempmonitors
	  where group_name = "procmgr" and
			field_name in ("proc_recompilation_exec",
				"proc_recompilation_comp",
				"proc_recompilation_exec_curs",
				"proc_recompilation_redef")

	select @rptline = "  Procedure Recompilations" + space(3) +
			str(@tmp_reco_total / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_reco_total / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_reco_total, 10) + space(7) +
			@na_str

	print @rptline

	if (@tmp_reco_total != 0)
	  begin
		print @blankline

		print "  Recompilations Requests:"

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recompilation_exec"

		select @rptline = "    Execution Phase" + space(10) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_reco_total,5,1) + @psign

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recompilation_comp"

		select @rptline = "    Compilation Phase" + space(8) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_reco_total,5,1) + @psign

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recompilation_exec_curs"

		select @rptline = "    Execute Cursor Execution" + space(1) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_reco_total,5,1) + @psign

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recompilation_redef"

		select @rptline = "    Redefinition Phase" + space(7) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_reco_total,5,1) + @psign

		print @rptline

		print @blankline

		print "  Recompilation Reasons:"

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_tabmissing"

		select @rptline = "    Table Missing" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		 print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_tempmissing"

		select @rptline = "    Temporary Table Missing" + space(2) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_schemacount"

		select @rptline = "    Schema Change" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_idxchange"

		select @rptline = "    Index Change" + space(13) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_isolevel"

		select @rptline = "    Isolation Level Change" + space(3) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_permissions"

		select @rptline = "    Permissions Change" + space(7) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		print @rptline

		select @tmp_int = value
		  from #tempmonitors
		  where group_name = "procmgr" and
			field_name = "proc_recomp_cursor_perm"

		select @rptline = "    Cursor Permissions Change" +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str

		print @rptline
	  end
  end

print @blankline

print "  SQL Statement Cache:"

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "proc_ssql_procs_available"

select @rptline = "    Statements Cached" + space(8) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "proc_ssql_found"

select @rptline = "    Statements Found in Cache" +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "proc_ssql_not_found"

select @rptline = "    Statements Not Found" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "proc_ssql_dropped"

select @rptline = "    Statements Dropped" + space(7) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "proc_ssql_restored"

select @rptline = "    Statements Restored" + space(6) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

select @tmp_total = value
  from #tempmonitors
  where group_name = "procmgr" and
		field_name = "proc_ssql_notcached"

select @rptline = "    Statements Not Cached" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

print @blankline
if @Reco = 'Y'
 begin
	select @recotxt = "  Tuning Recommendations for Procedure cache management"
	select @recoline = "  -----------------------------------------------------"
	select @reco_hdr_prn = 0

	/*
	** If % of the number of times a procedure was read from disk is
	** is > 10% consider increasing the procedure cache size
	*/	
	if @reco_phdr_read_from_disk > 10
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider increasing the 'procedure cache size'"
		print "    configuration parameter."
		print @blankline
	end
 end


print @blankline
return
go
exec sp_procxmode 'sp_sysmon_pcache', 'anymode'
go
grant execute on sp_sysmon_pcache to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_memory')
begin
	drop procedure sp_sysmon_memory
end
go
print "Installing sp_sysmon_memory"
go

/* This stored procedure produces a report containing a summary of
** memory use within the SQL server's pool of available memory.
*/
create procedure sp_sysmon_memory
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int		/* for per transactions calculations */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @sum1line char(80)	/* string to delimit total lines without 
				percent calc on printout */	
declare @blankline char(1)	/* to print blank line */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "---------------------------  ------------  ------------  ----------  ----------"
select @blankline  = " "
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline

print "Memory Management                 per sec      per xact       count  %% of total"
print @sum1line

select @tmp_int = value
  from #tempmonitors
  where group_name = "memory" and
		field_name = "mempages_alloced"

select @rptline = "  Pages Allocated" + space(12) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @tmp_int = value
  from #tempmonitors
  where group_name = "memory" and
		field_name = "mempages_freed"

select @rptline = "  Pages Released" + space(13) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

print @blankline
return 0
go
exec sp_procxmode 'sp_sysmon_memory', 'anymode'
go
grant execute on sp_sysmon_memory to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_recovery')
begin
	drop procedure sp_sysmon_recovery
end
go
print "Installing sp_sysmon_recovery"
go

/* This stored procedure produces a report containing a summary of
** checkpoint and housekeeper activity.
*/
create procedure sp_sysmon_recovery
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int		/* for per transactions calculations */
as

/* --------- declare local variables --------- */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)       /* string to delimit sections on printout */

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline

print "Recovery Management"
print "-------------------"
print @blankline

print "  Checkpoints                     per sec      per xact       count  %% of total"
print @sum1line

select @tmp_int = value
  from #tempmonitors
  where group_name = "access" and
		field_name = "normal_database_checkpoints"

select @tmp_int2 = value
  from #tempmonitors
  where group_name = "housekeeper" and
		field_name = "free_database_checkpoints"

select @tmp_total = @tmp_int + @tmp_int2

if @tmp_total = 0 
 begin
	select @rptline = "  Total Checkpoints                   0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @rptline = "    # of Normal Checkpoints" + space(2) +
			str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
			space(2) +
			str(@tmp_int / convert(real, @NumXacts),12,1) +
			space(2) +
			str(@tmp_int, 10) + space(5) +
			str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline

	select @rptline = "    # of Free Checkpoints" + space(4) +
			str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int2 / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int2, 10) + space(5) +
			str(100.0 * @tmp_int2 / @tmp_total,5,1) + @psign
	print @rptline

	print @sum2line
	select @rptline = "  Total Checkpoints" + space(10) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) 
	print @rptline
	print @blankline
	
	select @tmp_total = value
	  from #tempmonitors
	  where group_name = "access" and
			field_name = "time_todo_normal_checkpoints"


	if @tmp_int != 0	/* any normal checkpoints ? */
	  begin
		select @rptline = "  Avg Time per Normal Chkpt" + space(2) +
				str(convert(real,@tmp_total) / @tmp_int,12,5) +
				" seconds"
		print @rptline
	  end

	select @tmp_total = value
	  from #tempmonitors
	  where group_name = "housekeeper" and
			field_name = "time_todo_free_checkpoints"


	if @tmp_int2 != 0	/* any housekeeper checkpoints ? */
	  begin
		select @rptline = "  Avg Time per Free Chkpt" + space(4) +
			str(convert(real,@tmp_total) / @tmp_int2,12,5) + 
			" seconds"
		print @rptline
	  end
  end

print @blankline
return 0
go
exec sp_procxmode 'sp_sysmon_recovery', 'anymode'
go
grant execute on sp_sysmon_recovery to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_diskio')
begin
	drop procedure sp_sysmon_diskio
end
go
print "Installing sp_sysmon_diskio"
go

/* This stored procedure produces a report containing a summary of
** of disk activity.
*/
create procedure sp_sysmon_diskio
	@NumEngines tinyint,	/* number of engines online */
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco	char(1)		/* Flag for recommendations */
as

/* --------- declare local variables --------- */
declare @SybDiskName varchar(265) /* cursor var for logical disk name - 
				** sysdevices.name */
declare @PhyDiskName varchar(127) /* cursor var for physical disk name - 
				  ** sysdevices.phyname */

declare @i smallint		/* loop index to iterate through multi-group
				**  counters (engine, disk, & buffer) */
declare @tmp_grp varchar(25)	/* temp var for build group_name's - ie., 
				** engine_N, disk_N */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_int3 int           /* temp var for integer storage */
declare @tmp_int4 int           /* temp var for integer storage */
declare @tmp_total int          /* temp var for summing 'total #s' data */
declare @tmp_total_async int    /* temp var for summing total #s of
                                ** asynchronous IOs completed */
declare @tmp_total_sync int     /* temp var for summing total #s of synchronous
                                ** IOs completed */
declare @tmp_total_ios int      /* temp var for summing total #s of IOs
                                ** completed.
                                ** @tmp_total_ios = @tmp_total_async + 
				** @tmp_total_sync
                                */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @subsection char(80)	/* delimit disk sections */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)       /* string to delimit sections on printout */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)       /* Header for tuning recommendation */
declare @recoline char(80)      /* to underline recotxt */
declare @reco_hdr_prn bit       /* to indicate if the recotxt is already printed */
declare @reco_total_diskio int
declare @reco_diskio_struct_delay int
declare @reco_maxaio_server int
declare @reco_maxaio_engine int
declare @reco_aio_os_limit int

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @subsection = "  -----------------------------------------------------------------------------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline
print "Disk I/O Management"
print "-------------------"
print @blankline
print "  Max Outstanding I/Os            per sec      per xact       count  %% of total"
print @sum1line

select @tmp_int = value
  from #tempmonitors
  where group_name = "kernel" and
		field_name = "max_outstanding_AIOs_server"

select @rptline = "    Server" + space(28) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline

select @i = 0
while @i < @NumEngines		/* for each engine */
  begin
	/* build group_name string */
	select @tmp_grp = "engine_" + convert(varchar(3), @i)
  
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = @tmp_grp and
            field_name = "max_outstanding_AIOs_engine"
  
	select @rptline = "    Engine " + convert(char(3), @i) + space(24) +
					@na_str + space(11) +
					@na_str + space(2) +
					str(@tmp_int, 10) + space(7) +
					@na_str
	print @rptline

	select @i = @i + 1
  end

print @blankline
print @blankline
print "  I/Os Delayed by"

select @tmp_int = value, @reco_diskio_struct_delay = value
  from #tempmonitors
  where group_name = "kernel" and
		field_name = "udalloc_sleeps"

select @rptline = "    Disk I/O Structures" + space(15) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline

select @tmp_int = SUM(value), @reco_maxaio_server = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "AIOs_delayed_due_to_server_limit"

select @rptline = "    Server Config Limit" + space(15) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline

select @tmp_int = SUM(value), @reco_maxaio_engine = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "AIOs_delayed_due_to_engine_limit"

select @rptline = "    Engine Config Limit" + space(15) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline

select @tmp_int = SUM(value), @reco_aio_os_limit = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "AIOs_delayed_due_to_os_limit"

select @rptline = "    Operating System Limit" + space(12) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_int, 10) + space(7) +
				@na_str
print @rptline

print @blankline
print @blankline

select @tmp_int = value , @reco_total_diskio = value
  from #tempmonitors
  where group_name = "kernel" and
		field_name = "udalloc_calls"

select @rptline = "  Total Requested Disk I/Os" + space(2) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) 
print @rptline
print @blankline
print "  Completed Disk I/O's"

select @tmp_total_async = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "total_dpoll_completed_aios"

print "    Asynchronous I/O's"
if @tmp_total_async = 0
 begin
	select @rptline = "      Total Completed I/Os            0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp = "engine_" + convert(varchar(3), @i)
  
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "total_dpoll_completed_aios"
  
		select @rptline = "      Engine " + convert(char(3), @i) + 
				space(13) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total_async,5,1) + @psign
		print @rptline

		select @i = @i + 1
	  end	/* while loop */
  end	/* else */

  select @tmp_total_sync = value
  from #tempmonitors
  where group_name like "kernel" and
		field_name = "total_sync_completed_ios"

print "    Synchronous I/O's"
if @tmp_total_sync = 0
 begin
	select @rptline = "      Total Completed I/Os            0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
		select @rptline = "      Total Completed I/Os   " +
				str(@tmp_total_sync / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_total_sync / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_total_sync, 10) + space(5) +
				str(100.0,5,1) + @psign
		print @rptline
  end	/* else */

print @sum2line

select @tmp_total_ios = @tmp_total_async + @tmp_total_sync

select @rptline = "  Total Completed I/Os" + space(7) +
			str(@tmp_total_ios / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total_ios / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total_ios, 10)
print @rptline
print @blankline
print @blankline
print "  Device Activity Detail"
print "  ----------------------"
print @blankline

/* get total number of I/Os to all devices to calc each device's percentage */
select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "disk_%" and
		(field_name = "total_reads" or field_name = "total_writes")

if @tmp_total = 0
  begin
	print "    No Disk I/O in Given Sample Period"
	print @blankline
  end
else
  begin
        declare disk_info cursor for
                select name, phyname,group_name 
                  from #devicemap
                  order by phyname
                  for read only

	open disk_info
	fetch disk_info into @SybDiskName, @PhyDiskName, @tmp_grp

	while (@@sqlstatus = 0)
	  begin

		select @rptline = "  Device:"
		print @rptline
		select @rptline = space(4) + substring(@PhyDiskName, 1, 76)
		print @rptline
		select @rptline = space(4) + convert(char(25), 
			substring(@SybDiskName, 1, 25)) + 
			"     per sec      per xact       count  %% of total"
		print @rptline

		print @sum1line

		select @tmp_int2 = SUM(value)
		  from #tempmonitors
		  where group_name = @tmp_grp and
				(field_name = "total_reads" or 
					field_name = "total_writes")

		if @tmp_int2 = 0
 		begin
			select @rptline = "  Total I/Os                          0.0           0.0           0       n/a"
  			print @rptline
 		end
		else
		  begin
			select @tmp_int = value
			  from #tempmonitors
			  where group_name = @tmp_grp and
					field_name = "total_reads"
			if not exists(select * 
					from #tempmonitors
					where group_name = @tmp_grp and 
					field_name="apf_physical_reads")

			begin /*{ begin to check existence of apf counters*/
	                       select @rptline = "    Reads" + space(20) +
                                str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int, 10) + space(5) +
                                str(100.0 * @tmp_int / @tmp_int2,5,1) + @psign
       		                 print @rptline
			end /*} end for apf counter check*/
			
			else
			begin	/*{begin in case apf counters exist*/
                        	select @tmp_int3 = value
                          	from #tempmonitors
                          	where group_name = @tmp_grp and
                                        field_name = "apf_physical_reads"

                        	select @tmp_int4 = @tmp_int - @tmp_int3

                        	select @rptline = "    Reads"
                        	print @rptline

                        	select @rptline = "      APF" + space(20) +
                                str(@tmp_int3 / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int3 / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int3, 10) + space(5) +
                                str(100.0 * @tmp_int3 / @tmp_int2,5,1) + @psign
                        	print @rptline

                        	select @rptline = "      Non-APF" + space(16) +
                                str(@tmp_int4 / (@NumElapsedMs / 1000.0),12,1) +
                                space(2) +
                                str(@tmp_int4 / convert(real, @NumXacts),12,1) +
                                space(2) +
                                str(@tmp_int4, 10) + space(5) +
                                str(100.0 * @tmp_int4 / @tmp_int2,5,1) + @psign
                        	print @rptline
			end /*} end in case where apf counters exist*/

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = @tmp_grp and
					field_name = "total_writes"

			select @rptline = "    Writes" + space(19) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_int2,5,1) + @psign
			print @rptline

		  end	/* else @tmp_int2 != 0 */

		print @sum1line

		select @rptline = "  Total I/Os" + space(17) +
			str(@tmp_int2 / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_int2 / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_int2, 10) + space(5) +
			str(100.0 * @tmp_int2 / @tmp_total,5,1) + @psign
		print @rptline
		print @blankline

		select @tmp_int2 = SUM(value)
		  from #tempmonitors
		  where group_name = @tmp_grp and
			(field_name = "p_hits" or field_name = "p_misses")

		if @tmp_int2 != 0
		  begin

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = @tmp_grp and
					field_name = "p_hits"

			select @rptline = "  Mirror Semaphore Granted" + 
				space(3) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_int2,5,1) + @psign
			print @rptline

			select @tmp_int = value
			  from #tempmonitors
			  where group_name = @tmp_grp and
					field_name = "p_misses"

			select @rptline = "  Mirror Semaphore Waited" + 
				space(4) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_int2,5,1) + @psign
			print @rptline
		  end	/* else @tmp_int2 != 0 */ 

		print @blankline
		print @subsection
		print @blankline

		fetch disk_info into @SybDiskName, @PhyDiskName, @tmp_grp

	  end	/* while @@sqlstatus */

	close disk_info 
	deallocate cursor disk_info

  end	/* else @tmp_total != 0 */

print @blankline

if (@Reco = 'Y' and @reco_total_diskio != 0)
 begin
	select @recotxt = "  Tuning Recommendations for Disk I/O Management"
	select @recoline = "  ----------------------------------------------"
	select @reco_hdr_prn = 0

	select @reco_diskio_struct_delay = convert(int, 
		(100.0 * ((1.0 *@reco_diskio_struct_delay)/@reco_total_diskio)))
	select @reco_maxaio_server = convert(int,
		(100.0 * ((1.0 *@reco_maxaio_server)/@reco_total_diskio)))
	select @reco_maxaio_engine = convert(int,
		(100.0 * ((1.0 *@reco_maxaio_engine)/@reco_total_diskio)))
	select @reco_aio_os_limit = convert(int,
		(100.0 * ((1.0 *@reco_aio_os_limit)/@reco_total_diskio)))

	/*
	** If the % of I/O's delayed on account of
	** number of disk I/O structures is > 5%
	** consider increasing the number of disk i/o
	** structures
	*/
	if @reco_diskio_struct_delay > 5
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end
		
		print "  - Consider increasing the 'disk i/o structures'"
		print "    configuration parameter."
		print @blankline
		select @reco_hdr_prn = 1
	end

	/*
	** If the % of the number of I/O's delayed on account of
	** the server limit is > 5
	** consider increasing the 'max async I/Os per server'
	** configuration parameter 
	*/
	if @reco_maxaio_server > 5
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider increasing the 'max async I/Os per server'"
		print "    configuration parameter."
		print @blankline
		select @reco_hdr_prn = 1
	end

	/*
	** If the % of the number of I/O's delayed on account of
	** the engine limit is > 5
	** consider increasing 'max async I/Os per engine'
	*/
	if @reco_maxaio_engine > 5
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider increasing the 'max async I/Os per engine'"
		print "    configuration parameter."
		print @blankline
		select @reco_hdr_prn = 1
	end

	/*
	** If the % of the number of I/O's delayed on account of
	** operating system parameters governing async I/O
	** is greater than 5, then consider increasing that
	** parameter.
	*/
	if @reco_aio_os_limit > 5
	begin
                if (@reco_hdr_prn = 0)
                begin
                        print @recotxt
                        print @recoline
                        select @reco_hdr_prn = 1
                end

		print "  - Consider increasing the operating system parameter"
		print "    governing the number of asynchronous I/O's."
		print @blankline
		select @reco_hdr_prn = 1
	end

 end

print @blankline

return 0
go
exec sp_procxmode 'sp_sysmon_diskio', 'anymode'
go
grant execute on sp_sysmon_diskio to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_netio')
begin
	drop procedure sp_sysmon_netio
end
go
print "Installing sp_sysmon_netio"
go

/* This stored procedure produces a report containing a summary of
** network activity.
*/
create procedure sp_sysmon_netio
	@NumEngines tinyint,	/* number of engines online */
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int		/* for per transactions calculations */
as

/* --------- declare local variables --------- */
declare @i smallint		/* loop index to iterate through multi-group 
				** counters (engine, disk, & buffer) */
declare @tmp_grp varchar(25)	/* temp var for build group_names 
				** ie. engine_N, disk_N */
declare @tmp_int int		/* temp var for integer storage */
declare @tmp_int2 int		/* temp var for integer storage */
declare @tmp_total int		/* temp var for summing 'total #s' data */
declare @sum1line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @sum2line char(80)	/* string to delimit total lines without 
				** percent calc on printout */	
declare @subsection char(80)	/* delimit disk sections */
declare @blankline char(1)	/* to print blank line */
declare @psign char(3)		/* hold a percent sign (%) for print out */
declare @na_str char(3)		/* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	/* formatted stats line for print statement */
declare @section char(80)	/* string to delimit sections on printout */

/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @sum2line   = "  -------------------------  ------------  ------------  ----------"
select @subsection = "  -----------------------------------------------------------------------------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

print @section
print @blankline
print "Network I/O Management"
print "----------------------"
print @blankline

select @tmp_total = value
  from #tempmonitors
  where group_name = "kernel" and
		field_name = "ksalloc_calls"

select @rptline = "  Total Network I/O Requests " + 
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10) + space(7) +
			@na_str
print @rptline

if @tmp_total != 0
  begin
	select @tmp_int = value
	  from #tempmonitors
	  where group_name = "kernel" and
			field_name = "ksalloc_sleeps"

	select @rptline = "    Network I/Os Delayed" + space(5) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
	print @rptline
  end
print @blankline
print @blankline

print "  Total TDS Packets Received      per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "no_packets_received"

if @tmp_total = 0
 begin
	select @rptline = "  Total TDS Packets Rec'd             0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp = "engine_" + convert(varchar(2), @i)
  
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "no_packets_received"
  
		select @rptline = "    Engine " + convert(char(2), @i) + 
				space(16) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @i = @i + 1
	  end	/* while loop */

	print @sum2line

	select @rptline = "  Total TDS Packets Rec'd" + space(4) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10)
	print @rptline
  end
print @blankline
print @blankline

/* 
** save total packets rec'd for avg bytes / pkt calc 
*/ 
select @tmp_int2 = @tmp_total	

print "  Total Bytes Received            per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "no_bytes_received"

if @tmp_total = 0
 begin
	select @rptline = "  Total Bytes Rec'd                   0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp = "engine_" + convert(varchar(2), @i)
  
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "no_bytes_received"
  
		select @rptline = "    Engine " + convert(char(2), @i) + 
				space(16) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @i = @i + 1
	  end	/* while loop */

	print @sum2line

	select @rptline = "  Total Bytes Rec'd" + space(10) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10)
	print @rptline
  end	/* else */
print @blankline
print @blankline

if @tmp_int2 != 0		/* Avoid divide by zero. */
  begin
	select @rptline = "   Avg Bytes Rec'd per Packet" + space(10) +
				@na_str + space(11) +
				@na_str + space(2) +
				str(@tmp_total / @tmp_int2, 10) + space(7) +
				@na_str
	print @rptline
	print @blankline
  end
print @subsection
print @blankline

print "  Total TDS Packets Sent          per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "no_packets_sent"

if @tmp_total = 0
 begin
	select @rptline = "  Total TDS Packets Sent              0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp = "engine_" + convert(varchar(2), @i)
  
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "no_packets_sent"
  
		select @rptline = "    Engine " + convert(char(2), @i) + 
				space(16) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @i = @i + 1
	  end	/* while loop */

	print @sum2line

	select @rptline = "  Total TDS Packets Sent" + space(5) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10)
	print @rptline
  end	/* else */
print @blankline
print @blankline

/* save total packets sent for avg bytes / pkt calc */ 
select @tmp_int2 = @tmp_total

print "  Total Bytes Sent                per sec      per xact       count  %% of total"
print @sum1line

select @tmp_total = SUM(value)
  from #tempmonitors
  where group_name like "engine_%" and
		field_name = "no_bytes_sent"

if @tmp_total = 0
 begin
	select @rptline = "  Total Bytes Sent                    0.0           0.0           0       n/a"
  	print @rptline
 end
else
  begin
	select @i = 0
	while @i < @NumEngines		/* for each engine */
	  begin
		/* build group_name string */
		select @tmp_grp = "engine_" + convert(varchar(2), @i)
  
		select @tmp_int = value
		  from #tempmonitors
		  where group_name = @tmp_grp and
				field_name = "no_bytes_sent"
  
		select @rptline = "    Engine " + convert(char(2), @i) + 
				space(16) +
				str(@tmp_int / (@NumElapsedMs / 1000.0),12,1) +
				space(2) +
				str(@tmp_int / convert(real, @NumXacts),12,1) +
				space(2) +
				str(@tmp_int, 10) + space(5) +
				str(100.0 * @tmp_int / @tmp_total,5,1) + @psign
		print @rptline

		select @i = @i + 1
	  end	/* while loop */

	print @sum2line

	select @rptline = "  Total Bytes Sent" + space(11) +
			str(@tmp_total / (@NumElapsedMs / 1000.0),12,1) + 
			space(2) +
			str(@tmp_total / convert(real, @NumXacts),12,1) + 
			space(2) +
			str(@tmp_total, 10)
	print @rptline
  end	/* else */
print @blankline
print @blankline

if @tmp_int2 != 0 		/* Avoid divide by zero. */
  begin
	select @rptline = "  Avg Bytes Sent per Packet" + space(11) +
					@na_str + space(11) +
					@na_str + space(2) +
					str(@tmp_total / @tmp_int2, 10) + 
					space(7) +
					@na_str
	print @rptline
	print @blankline
  end

return 0
go
exec sp_procxmode 'sp_sysmon_netio', 'anymode'
go
grant execute on sp_sysmon_netio to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_repagent')
begin
	drop procedure sp_sysmon_repagent
end
go
print "Installing sp_sysmon_repagent"
go


/*
** ===========================================================================
** Generated by spgenmsgs.pl on Sun Jan 29 13:21:05 2006 
** 
** raiserror Messages for sysmon_repagent [Total 0]
** 
** sp_getmessage Messages for sysmon_repagent [Total 0]
** 
** End spgenmsgs.pl output.
*/

create procedure sp_sysmon_repagent
as
declare @dbid 		int		/* dbid of the database 	 */
declare @dbname		varchar(255)	/* Database name 		 */
declare @dblist		varchar(480)	/* List of databases using slot 0*/
declare @group_name	varchar(255)	/* Counter group name		 */
declare @rptline	varchar(305)	/* Formatted info for print stmt */
declare @rptline1	varchar(305)	/* Formatted info for print stmt */
declare @rptline2	varchar(305)	/* Formatted info for print stmt */
declare @section	char(80)	/* String to delimit sections    */
declare @blankline	char(1)		/* To print blank line 		 */
declare @tmp_int	int
declare @tmp_total	int		/* Used to calculate average     */
declare @tmp_cnt	int		/* Used to calculate average     */
declare @na_str 	char(3)		/* 'n/a' for 'not applicable'    */
declare @tmp_avg	varchar(10)	/* Used to stored average 	 */
declare @nslots		int		/* Number of slots on mon table  */

set nocount on

/* Check if ASE is configured to use Replication Agent threads */
if is_rep_agent_enabled() =0
begin
	/* There is nothing to print if Replication Agent is not enable */
	return (0)
end

select @blankline = " "
select @na_str = "n/a"
select @rptline  = space(34) + "per sec      per xact       count  %% of total"
select @rptline1 = space(29) + "------------  ------------  ----------  ----------"

print "==============================================================================="
print @blankline
print "Replication Agent"
print "-----------------"
print @blankline

/*
** Create a temp table of all databases.  Do not include databases that do
** not support RepAgent Thread (i.e. 'tempdb' (2), 'model' (3),
** 'sybsystemdb' (31513), 'sybsystemprocs' (31514)), and local tempdbs
** (status3 & 536870912).
*/
select  dbid, 
        name, 
        "repagent_" + convert(char(3), dbid) as group_name
        into #tempdatabases
        from master.dbo.sysdatabases
        where name not in ('tempdb', 'model', 'sybsystemdb', 'sybsystemprocs')
	and   ((status3 & 536870912) = 0)
	and   is_rep_agent_enabled(dbid) = 1

/*
** If slot0 has any values greater than zero, counters for repagents whose
** dbid is out of range with regards to counter array, will have used slot 0.
*/
if exists (select value from #tempmonitors
	   where group_name = "repagent_0" and value > 0)
begin
	/*
	** Slot 0 contains the accumulation of RepAgent counters
	** that were out of range of the statically allocated
	** monitor table.
	*/
 	insert into #tempdatabases values
		(0,"Rep Agent Global Counters for:","repagent_0")
end

/* 
** Calculate the number of slots that can be used to store counters for
** individual replication agents.
*/
select @nslots = count(*) from #tempmonitors
			  where group_name like "repagent_%" 
			  and   field_name = "ra_log_records_scanned"

select @dblist = null

/* Start processing for each database stored in tempdatabases */
declare db_info cursor
for select dbid, name, group_name from #tempdatabases

open db_info
fetch db_info into @dbid, @dbname, @group_name
while (@@sqlstatus = 0)
begin

	/*
	** If the database used slot zero to store its counters, we cannot
	** print anything now, but update the databases list using this slot.
	*/
	if (@dbid >= @nslots)
	begin
		if @dblist is null
			select @dblist = @dblist + @dbname
		else
			select @dblist = @dblist + ", " + @dbname

		fetch db_info into @dbid, @dbname, @group_name
		continue

	end

	if (@dbid = 0)
		select @rptline2 = @dbname + @dblist
	else
		select @rptline2 = "Replication Agent:  " + @dbname

	print @rptline2

	if (@dbid != 0)
	begin
		select @rptline2 = "Replication Server: " +
				   rep_agent_config(@dbid, "config", "rs servername")
		print @rptline2
	end
	print @blankline
	print @rptline
	print @rptline1
	print "Log Scan Summary"

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name
	and    field_name = "ra_log_records_scanned"

	select @rptline2 = "    Log Records Scanned"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name 
	and    field_name = "ra_log_records_processed"

	select @rptline2 = "    Log Records Processed"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name
	and    field_name = "ra_log_scans"

	select @rptline2 = "    Number of Log Scans"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2
	select @tmp_cnt = @tmp_int

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name
	and    field_name = "ra_sum_log_scan"
	select @rptline2 = "    Amount of Time for Log Scans (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2
	select @tmp_total = @tmp_int

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name
	and field_name = "ra_longest_log_scan"
	select @rptline2 = "    Longest Time for Log Scan (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str +      space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @rptline2 = "    Average Time per Log Scan (ms)"
	if (@tmp_cnt >0)
	begin
		select @tmp_avg = str(1.0 * @tmp_total / @tmp_cnt, 10,1)
	end
	else	select @tmp_avg = str(1.0 * 0,10,1)
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str + space(2) + @tmp_avg +
			   space(7) + @na_str
	print @rptline2

	print @blankline
	print "Log Scan Activity"

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name and field_name = "ra_xupdate_processed"

	select @rptline2 = "    Updates"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name and field_name = "ra_xinsert_processed"
	select @rptline2 = "    Inserts"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
	from   #tempmonitors
	where  group_name = @group_name and field_name = "ra_xdelete_processed"
	select @rptline2 = "    Deletes"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_xexec_processed"
	select @rptline2 = "    Store Procedures"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_xcmdtext_processed"
	select @rptline2 = "    DDL Log Records"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_xwrtext_processed"
	select @rptline2 = "    Writetext Log Records"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_xrowimage_processed"
	select @rptline2 = "    Text/Image Log Records"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_xclr_processed"
	select @rptline2 = "    CLRs"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select	@tmp_int = value
	from	#tempmonitors
	where	group_name = @group_name and field_name = "ra_xckpt_processed"
	select	@rptline2 = "    Checkpoints Processed"
	select 	@rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                            @na_str + space(11) + @na_str + space(2) +
                            str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select	@tmp_int = value
	from	#tempmonitors	
	where	group_name = @group_name and field_name = "ra_sqldml_processed"
	select	@rptline2 = "    SQL Statements Processed"
	select 	@rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                            @na_str + space(11) + @na_str + space(2) +
                            str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2


	print @blankline
	print "Transaction Activity"

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_open_xact"
	select @rptline2 = "    Opened"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_commit_xact"
	select @rptline2 = "    Commited"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_abort_xact"
	select @rptline2 = "    Aborted"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_prepared_xact"
	select @rptline2 = "    Prepared"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

        select @rptline2 = "    Delayed Commit"
        select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_delayed_commit_xact"
        select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_maintuser_xact"
	select @rptline2 = "    Maintenance User"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2
	print @blankline

	print "Log Extension Wait"
	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_log_waits"
	select @rptline2 = "    Count"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2
	select @tmp_cnt = @tmp_int

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_sum_log_wait"
	select @rptline2 = "    Amount of time (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2
	select @tmp_total = @tmp_int

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_longest_log_wait"
	select @rptline2 = "    Longest Wait (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) + 
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @rptline2 = "    Average Time (ms)"
	if (@tmp_cnt >0)
	begin
		select @tmp_avg = str(1.0 * @tmp_total / @tmp_cnt, 10,1)
	end
	else	select @tmp_avg = str(1.0 * 0,10,1)
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str + space(2) + @tmp_avg +
			   space(7) + @na_str

	print @rptline2
	print @blankline

	print "Schema Cache"
	print " Usage"
	select @rptline2 = "    Max Ever Used"
	if (@dbid != 0)
	begin
		select @tmp_int = convert(int, 
					  rep_agent_config(@dbid, 
							   "schema cache", 
							   "max"))
	end
	else
	begin
		select @tmp_int = 0
	end
	select @rptline2 = @rptline2 + 
			   space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_schema_reuse"
	select @rptline2 = "    Schemas reused"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
			   @na_str + space(11) + @na_str + space(2) +
			   str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2

	print " Forward Schema Lookups"
	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_forward_schema"
	select @rptline2 = "    Count"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
	print @rptline2
	select @tmp_cnt = @tmp_int

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_sum_forward_wait"
	select @rptline2 = "    Total Wait (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2
	select @tmp_total = @tmp_int

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_longest_forward_wait"
	select @rptline2 = "    Longest Wait (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @rptline2 = "    Average Time (ms)"
	if (@tmp_cnt >0)
	begin
		select @tmp_avg = str(1.0 * @tmp_total / @tmp_cnt, 10,1)
	end
	else	select @tmp_avg = str(1.0 * 0,10,1)
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) + @tmp_avg +
                           space(7) + @na_str
        print @rptline2
	print " Backward Schema Lookups"
	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_backward_schema"
        select @rptline2 = "    Count"
        select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2
        select @tmp_cnt = @tmp_int

        select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_sum_bckward_wait"
        select @rptline2 = "    Total Wait (ms)"
        select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2
        select @tmp_total = @tmp_int

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_longest_bckward_wait
"
        select @rptline2 = "    Longest Wait (ms)"
        select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @rptline2 = "    Average Time (ms)"
	if (@tmp_cnt >0)
	begin
		select @tmp_avg = str(1.0 * @tmp_total / @tmp_cnt, 10,1)
	end
	else	select @tmp_avg = str(1.0 * 0,10,1)
        select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) + @tmp_avg +
                           space(7) + @na_str
        print @rptline2
	print @blankline
	print "Truncation Point Movement"

	select @tmp_int = value
        from   #tempmonitors
        where  group_name = @group_name and field_name = "ra_truncpt_moved"
	select @rptline2 = "    Moved"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_truncpt_gotten"
	select @rptline2 = "    Gotten from RS"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2
	print @blankline
	print "Connections to Replication Server"

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_rs_connect"
	select @rptline2 = "    Success"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_fail_rs_connect"
	select @rptline2 = "    Failed"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2
	print @blankline
	print "Network Packet Information"	

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_packets_sent"
	select @rptline2 = "    Packets Sent"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2
	select @tmp_cnt = @tmp_int

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_full_packets_sent"
	select @rptline2 = "    Full Packets Sent"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_largest_packet"
	select @rptline2 = "    Largest Packet"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2

	select @tmp_int = value
        from   #tempmonitors   
        where  group_name = @group_name and field_name = "ra_sum_packet"
	select @rptline2 = "    Amount of Bytes Sent"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2
	select @tmp_total = @tmp_int

	select @rptline2 = "    Average Packet"
	if (@tmp_cnt >0)
	begin
		select @tmp_avg = str(1.0 * @tmp_total / @tmp_cnt, 10,1)
	end
	else	select @tmp_avg = str(1.0 * 0,10,1)
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) + @tmp_avg +
                           space(7) + @na_str
	print @rptline2
	print @blankline
	print "I/O Wait from RS"

	select @tmp_int = sum(value)
        from   #tempmonitors   
        where  group_name = @group_name 
	and (field_name = "ra_io_send" or field_name = "ra_io_recv")
	select @rptline2 = "    Count"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2
        select @tmp_cnt = @tmp_int

	select @tmp_int = sum(value)
        from   #tempmonitors   
        where  group_name = @group_name
	and (field_name = "ra_sum_io_send_wait" 
	     or field_name = "ra_sum_io_recv_wait")
	select @rptline2 = "    Amount of Time (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2
	select @tmp_total = @tmp_int

	select @tmp_int = max(value)
        from   #tempmonitors   
        where  group_name = @group_name 
	and (field_name = "ra_longest_io_send_wait"
	     or field_name = "ra_longest_io_recv_wait")
	select @rptline2 = "    Longest Wait (ms)"
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +     
                           @na_str + space(11) + @na_str +      space(2) +
                           str(@tmp_int , 10) + space(7) + @na_str     
        print @rptline2

	select @rptline2 = "    Average Wait (ms)"
	if (@tmp_cnt >0)
	begin
		select @tmp_avg = str(1.0 * @tmp_total / @tmp_cnt, 10,1)
	end
	else	select @tmp_avg = str(1.0 * 0,10,1)
	select @rptline2 = @rptline2 + space(38 - datalength(@rptline2)) +
                           @na_str + space(11) + @na_str + space(2) + @tmp_avg +
                           space(7) + @na_str
        print @rptline2
        print @blankline
	
	select @rptline2 = replicate('-',80)
	print @rptline2

	fetch db_info into @dbid, @dbname, @group_name
	
end
close db_info
deallocate cursor db_info

return 0
go
exec sp_procxmode 'sp_sysmon_repagent', 'anymode'
go
grant execute on sp_sysmon_repagent to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addengine')
begin
	drop procedure sp_addengine
end
go
print "Installing sp_addengine"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_addengine"
**
** 17260, "Can't run %1! from within a transaction."
** 18248, "Validation of Engine Group modification failed. Check server
**	   errorlog for any additional information."
** 18249, "Name '%1!' is not valid."
** 18250, "Failed to add engine '%1!' to engine group '%2!'. Check server
**	   errorlog for any additional information. List of engines in
**	   engine group unchanged.
** 18251, "Cannot modify pre-defined engine groups."
** 19703, "Instance id '%1!' is not valid under instance system view."
*/

create procedure sp_addengine
@engine_number int,			/* engine number of engine */
@engine_group varchar(255),         	/* group that engine belongs to */
@instanceid smallint = NULL		/* instance id */
as

declare @attrib_id 	int,
	@action		int,
	@engine_name	varchar(5),
	@object_type	varchar(2),
	@new_list	varchar(768),
	@engine_list	varchar(768),
	@upcase_str	varchar(255)

select @action = 1		/* add or modify entry */
select @attrib_id = 1  		/* attribute is ENGINE_GROUP */
select @object_type = 'EG'
select @engine_list = NULL	/* var to hold list of engines in group */

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_addengine"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do "Dirty Reads" */
set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/

/* first convert any system defined engine group name to upper case */
select @upcase_str = upper(@engine_group)
IF ((@upcase_str = "ANYENGINE") OR (@upcase_str = "LASTONLINE"))
	select @engine_group = @upcase_str

/* Cannot add to pre-defined groups */
if (@engine_group = "ANYENGINE" OR @engine_group = "LASTONLINE")
BEGIN
        /*
	** 18251, "Cannot modify pre-defined engine groups."        
        */
	raiserror 18251
        return (1)
END

IF ((@engine_group != "ANYENGINE") AND (@engine_group != "LASTONLINE"))
BEGIN
	IF valid_name(@engine_group, 30) = 0
	BEGIN
		/*
		 ** 18249, "Name '%1!' is not valid."
		 */
		 raiserror 18249, @engine_group
		 return (1)
	END
END

/* For SDC, use @@instanceid if NULL is specified */
if (@@clustermode = "shared disk cluster")
BEGIN
	if ((@@system_view = "instance") AND
		(@instanceid != NULL) AND
		(@instanceid != @@instanceid))
	BEGIN
		/*
		** 19703, "Instance id '%1!' is not valid under instance 
		**	   system view."
		*/
		raiserror 19703, @instanceid
		return (1)
	END
 
	if (@instanceid = NULL)
		select @instanceid = @@instanceid
END
else
	select @instanceid = NULL

/*
** The validation routine checks that the supplied engine is not
** already in the group and that it is a valid engine number
*/ 
IF attrib_valid(6, @attrib_id, @object_type, NULL, NULL, NULL,
            	@instanceid, @engine_group, @engine_number, NULL, NULL, 
		NULL, "", @action ) = 0
BEGIN
        /*
	** 18248, "Validation of Engine Group modification failed. Check
	**	   server errorlog for any additional information."
        */
	raiserror 18248
        return (1)
END
 
IF ((@engine_group != "ANYENGINE") AND (@engine_group != "LASTONLINE"))
BEGIN
	/*
	** The list of engines belonging to an engine
	** group are kept in the format -
	** engine # : engine # : ....
	** So add the new engine in the correct format
	*/
	select @engine_name = str(@engine_number, 5)
	IF exists(select * from master..sysattributes where
			class = 6 AND
			attribute = 1 AND
			object_type = 'EG' AND
			object_cinfo = @engine_group AND
			object_info3 = @instanceid)
	BEGIN
		select @engine_list = (select char_value 
			from master..sysattributes where
			class = 6 AND
			attribute = 1 AND
			object_type = 'EG' AND
			object_cinfo = @engine_group AND
			object_info3 = @instanceid)

		select @new_list = (@engine_list +
					@engine_name + ":" )

		update master..sysattributes
			set char_value = @new_list
				where 	class = 6 AND
				attribute = 1 AND
				object_type = 'EG' AND
				object_cinfo = @engine_group AND
				object_info3 = @instanceid
	END
	ELSE
	BEGIN
		select @new_list = (@engine_name + ":")
		insert master..sysattributes
		(class, attribute, object_type, object_info3, object_cinfo,char_value)
		values(6, @attrib_id, @object_type, @instanceid, @engine_group, @new_list)
	END
END

if (attrib_notify(6, @attrib_id, @object_type, NULL, @engine_number, NULL,
            	@instanceid, @engine_group, NULL, NULL, NULL, NULL, "", 
		@action)) = 0
BEGIN
	/*
	** 18250, "Failed to add engine '%1!' to engine group '%2!'. Check
	**	   server errorlog for any additional information. List of
	**	   engines in engine group unchanged."
	*/
	IF (@engine_list is not NULL)
		update master..sysattributes
			set char_value = @engine_list
				where class = 6 AND
				attribute = 1 AND
				object_type = 'EG' AND
				object_cinfo = @engine_group AND
				object_info3 = @instanceid
	ELSE
		delete master..sysattributes where
			class = 6 AND
			attribute = 1 AND 
			object_type = 'EG' AND
			object_cinfo = @engine_group AND
			object_info3 = @instanceid

	raiserror 18250, @engine_number, @engine_group
	return(1)
END

return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addexeclass')
begin
	drop procedure sp_addexeclass
end
go
print "Installing sp_addexeclass"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_addexeclass"
**
** 17260, "Can't run %1! from within a transaction."
** 18249, "Name '%1!' is not valid."
** 18252, "'%1!' value '%2!' is not valid."
** 18253, "No specification for engine group '%1!' exists"
** 18254, "Failed to update attributes of objects assigned to class '%1!'.
**	   Check server errorlog for any additional information."
** 18522, "Execution Class '%1!' is a system defined class. This class
**	   cannot be created or changed."
*/

create procedure sp_addexeclass
@classname varchar(255),			/* name of class */
@priority varchar(10),			/* priority of task */
@timeslice int,				/* time quantum of task */
@engine_group varchar(255),         	/* engine group task belongs to */
@instanceid smallint = NULL		/* instance id  for SDC */

as

declare	@attrib_id 	int,
	@action		int,
	@ts_str		varchar(10),
	@upcase_str	varchar(255),
	@instid		smallint

declare @retstat  int

/* For timeslice, use 0 if NULL is specified */
if (@timeslice is NULL)
	select @timeslice = 0

select @ts_str = str(@timeslice)
select @action = 1
select @attrib_id = 2  /* attribute is USERCLASS_DEFN */

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_addexeclass"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Don't do "Dirty Reads" */
set transaction isolation level 1

/* convert all system defined values to upper case as needed */
select @upcase_str = upper(@classname)
IF ((@upcase_str = "EC0") OR (@upcase_str = "EC1") OR
	(@upcase_str = "EC2") OR (@upcase_str = "EC3"))
	select @classname = @upcase_str

select @upcase_str = upper(@priority)
IF ((@upcase_str = "HIGH") OR (@upcase_str = "MEDIUM") OR
	(@upcase_str = "LOW"))
	select @priority = @upcase_str

select @upcase_str = upper(@engine_group)
IF ((@upcase_str = "ANYENGINE") OR (@upcase_str = "LASTONLINE"))
	select @engine_group = @upcase_str

/*
** Check to see that the input params are correct
*/
IF valid_name(@classname, 30) = 0
BEGIN
	/*
	** 18249, "Name '%1!' is not valid."
	*/
        raiserror 18249, @classname
        return (1)
END
ELSE
BEGIN
	IF ((@classname = "EC0") OR (@classname = "EC1") OR 
		(@classname = "EC2") OR (@classname = "EC3"))
	BEGIN
		/*
		** 18522, "Execution Class '%1!' is a system defined
		** 	   class. This class cannot be created or changed."
		*/
		raiserror 18522, @classname
		return (1)
	END
END

IF ((@priority != "HIGH")
	and (@priority != "MEDIUM") 
	and (@priority != "LOW"))
BEGIN
	/*
	** 18252, "'%1!' value '%2!' is not valid."
	*/
	raiserror 18252, "Priority", @priority
	return (1)
END
 
/* For SDC, use @@instanceid if NULL is specified */
if (@@clustermode = "shared disk cluster")
BEGIN
	if (@instanceid = NULL)
		select @instanceid = @@instanceid
END
else
	select @instanceid = NULL

/* 
** For SDC, valid @engine_group must be local user-defined engine group or 
**	ANYENGINE or LASTONLINE
*/
IF ((@engine_group != "ANYENGINE") AND (@engine_group != "LASTONLINE"))
BEGIN
	IF valid_name(@engine_group, 30) = 0
	BEGIN
		/*
		** 18249, "Name '%1!' is not valid."
		*/
        	raiserror 18249, @engine_group
        	return (1)
	END
	IF not exists(select * from master..sysattributes where
		class = 6 AND
		attribute = 1 AND
		object_type = 'EG' AND
		object_info3 = @instanceid AND
		object_cinfo = @engine_group)
	BEGIN
		/*
		** 18253, "No specification for engine group '%1!' exists"
		*/
		raiserror 18253, @engine_group
		return(1)
	END
END

/* 
** Now hook up with Sysattributes Table...
** The execution attribute values are stored in the format:
** "priority value : time slice value : engine group name"
*/

IF exists(select * from master..sysattributes where
	class = 6 AND
	attribute = @attrib_id AND
	object_type = 'UC' AND
	object_cinfo = @classname)
BEGIN
	
	/*
	** For SDC,  force classname to be unique clusterwise
	*/
	select @instid=object_info3 from master..sysattributes where
		class = 6 AND
		attribute = @attrib_id AND
		object_type = 'UC' AND
		object_cinfo = @classname

	if ((@instid != NULL) AND
		(@instid != @instanceid))
	BEGIN
		/*
		** RESOLVE: change error to new message:
		** "Class '%1!' is bound to instance '%2!'."
		*/
		raiserror 19659, @classname, @instid
		return (1)
	END
 

	update master..sysattributes
		set char_value = 
			(@priority + ":" + @ts_str + ":" + @engine_group),
		    object_info3 = @instanceid
		where class = 6 AND
		attribute = @attrib_id AND
		object_type = 'UC' AND
		object_cinfo = @classname

	/*
	** If there are any objects bound to this class, then change 
	** the execution attributes of those objects based on the new class
	** attributes. 
	** For stored procs, this is an attr_change operation.
	** for others its an attr_add. Since bindings may
	** exist in any database for sp, we let attrib_notify
	** search in all databases for bindings simply given the object_type
	** (PR) and class name and do the necessary update.
	*/
	IF attrib_notify(6, 0, 'PR', NULL,
			NULL, NULL, @instanceid, NULL, NULL,
			@classname, NULL, NULL, "", 2) = 0
	BEGIN
		/*
		** 18254, "Failed to update attributes
		** of objects assigned to class '%1!'.
		** Check server errorlog for any 
		** additional information."
		*/
		raiserror 18254, @classname
		return(1)
	END

	/*
	** for logins and applications, we will look only
	** in master. Update the execution attributes of these objects
	** that are bound (@attr = 0) to this class.
	*/

	DECLARE object_info cursor for
	select attribute, object_type, object, object_info1, object_cinfo, 
	char_value
	from master..sysattributes where (class = 6)

	DECLARE @attr		smallint,
		@obj_t		varchar(2),
		@obj  		int,
		@objinfo1	int,
		@objcinfo	varchar(30),
		@class		varchar(30)

	OPEN object_info
	FETCH object_info into @attr, @obj_t, @obj, @objinfo1, @objcinfo,@class
	WHILE (@@sqlstatus != 2)
	BEGIN
		IF ((@class = @classname) AND (@attr = 0) AND
		((@obj_t = 'LG') OR (@obj_t = 'AP')))
		BEGIN
			IF attrib_notify(6, @attr, @obj_t, @obj, @objinfo1,
					NULL, @instanceid, @objcinfo, NULL,
					@classname, NULL, NULL, "", 1) = 0
			BEGIN
				CLOSE object_info
				deallocate cursor object_info

				/*
				** 18254, "Failed to update attributes
				** of objects assigned to class '%1!'.
				** Check server errorlog for any 
				** additional information."
				*/
				raiserror 18254, @classname
				return(1)
			END
		END

		IF ((@class = @classname) AND (@attr = 0) AND (@obj_t = 'DF'))
		BEGIN
			IF attrib_notify(6, @attr, @obj_t, NULL,
					NULL, NULL, @instanceid, NULL, NULL,
					@classname, NULL, NULL, "", 1) = 0
			BEGIN
				CLOSE object_info
				deallocate cursor object_info

				/*
				** 18254, "Failed to update attributes
				** of objects assigned to class '%1!'.
				** Check server errorlog for any
				** additional information."
				*/
				raiserror 18254, @classname
				return(1)
			END
		END

		/* Fetch the next row from sysattributes table */
		FETCH object_info into @attr, @obj_t, @obj, @objinfo1, 
			@objcinfo, @class
	END

	CLOSE object_info
	deallocate cursor object_info
END
ELSE
BEGIN
	insert master..sysattributes
	(class, attribute, object_type, object_info3, object_cinfo, char_value)
		values(6, @attrib_id, 'UC', @instanceid, @classname,
			(@priority + ":" + @ts_str + ":" + @engine_group))
END

return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_bindexeclass')
begin
	drop procedure sp_bindexeclass
end
go
print "Installing sp_bindexeclass"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_bindexeclass"
** 17260, "Can't run %1! from within a transaction."
** 18255, "%1! cannot be NULL."
** 18256, "%1! is not a valid object type for this stored procedure."
** 18257, "No definition for classname '%1!' exists."
** 18259, "No login with the specified name '%1!' exists."
** 18260, "Validation of execution class binding failed. Check server
**	   errorlog for any additional information."
** 18261, "Failed to bind '%1!' to execution class '%2!'. Check server
**	   errorlog for any additional information."
** 18535, "Permission denied: 'sybase_ts_role' is required for binding 
**	   with execution class 'EC0'.
** 18551, "Stored procedure %1!, owned by %2!, does not exist in this database.
** 18552, "%1! is not a valid user of this database.
** 18291, "The parameter value '%1!' is invalid."
*/

create procedure sp_bindexeclass
@object_name varchar(255),		/* name of object */
@object_type varchar(2),		/* Type of object */
@scope varchar(30),         		/* user scope of binding */
@classname varchar(255)			/* class name assigned */
as

declare		@attrib_id 	int,
		@user_id	int,
		@action		int,
		@role		int,
		@sp_objid	int,
		@owner_id	int,
		@upcase_str	varchar(255),
		@instanceid	int

select @action = 1
select @user_id = NULL /* Id of user from Syslogins table */

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_bindexeclass"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do "Dirty Reads" */
set transaction isolation level 1

/* convert to upper case, system supported types and names */
select @upcase_str = upper(@classname)
IF ((@upcase_str = "EC0") OR (@upcase_str = "EC1") OR
	(@upcase_str = "EC2") OR (@upcase_str = "EC3"))
	select @classname = @upcase_str

select @upcase_str = upper(@object_type)
IF ((@upcase_str = "LG") OR (@upcase_str = "AP") OR
	(@upcase_str = "PR") OR (@upcase_str = "DF"))
	select @object_type = @upcase_str

/*
** Check to see that the input params are correct
*/
IF ((@object_name is NULL) AND (@object_type != 'DF'))
BEGIN
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "Object name"
	return (1)
END

IF ((@object_type = 'PR') AND (@scope is NULL))
BEGIN
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "Scope"
	return (1)
END

/* For object_type DF the object name and scope should be NULL */
IF ((@object_type = 'DF') AND ((@object_name is not NULL) 
				OR (@scope is not NULL)))
BEGIN
	/*
	** 18291, "The parameter value '%1!' is invalid."
	*/
	raiserror 18291, "Object name or scope"
	return (1)
END


/* check that @object_type value specified is valid */
IF ((@object_type != 'LG') and (@object_type != 'AP')
	and (@object_type != 'PR') and (@object_type != 'DF'))
BEGIN
	/*
	** 18256, "%1! is not a valid object type for this stored procedure."
	*/
        raiserror 18256, @object_type
        return (1)
END

/* in case of stored procs, check that the object exists */
IF (@object_type = "PR")
BEGIN
	/* get owner id from scope param */
	IF not exists (select uid from sysusers
			where (name = @scope))
	BEGIN
		/*
		** 18552 "%1! is not a valid user of this database."
		*/
		raiserror 18552, @scope
		return(1)
	END
	ELSE
		select @owner_id = (select uid from sysusers
					where (name = @scope))

	IF not exists (select id from sysobjects
			where ((name = @object_name) AND (uid = @owner_id)))
	BEGIN
		/*
		** 18551 "Stored procedure %1!, owned by %2!, does not exist 
		**        in this database.
		*/
		raiserror 18551, @object_name, @scope
		return(1)
	END
	ELSE
		select @sp_objid = (select id from sysobjects
			where ((name = @object_name) AND (uid = @owner_id)))
END

select @attrib_id = 2 /* attribute is class definition */

/* check the class name passed in */
IF ((@classname != "EC0")
	AND (@classname != "EC1") 
	AND (@classname != "EC2")
	AND (@classname != "EC3"))
BEGIN
	IF not exists(select object_cinfo from master..sysattributes
		where class = 6 AND
		attribute = @attrib_id AND
		object_type = 'UC' AND
		object_cinfo = @classname)
	BEGIN
		/*
		** 18257, "No definition for classname '%1!' exists."
		*/
        	raiserror 18257, @classname
        	return (1)
	END

	
	/*
	** For SDC, binding only to local execution class
	*/
	IF (@@clustermode = "shared disk cluster")
	BEGIN
		select @instanceid=object_info3 from master..sysattributes 
		where class = 6 AND
		attribute = @attrib_id AND
		object_type = 'UC' AND
		object_cinfo = @classname

		if ((@instanceid != NULL) AND
			(@instanceid != @@instanceid))
		BEGIN
			/*
			** RESOLVE: change error to new message:
			** "Class '%1!' is bound to instance '%2!'."
			*/
			/* raiserror 17260, "sp_bindexeclass" */
			raiserror 19659, @classname, @instanceid
			return (1)
		END
	END
END

/* check that for class EC0, caller has sybase_ts_role. */
IF (@classname = "EC0")
BEGIN
	select @role = proc_role("sybase_ts_role")
	IF (@role = 0)
	BEGIN
		/*
		** 18535, "Permission denied: 'sybase_ts_role' is required 
		**         for binding with execution class EC0"
		*/
		raiserror 18535
        	return (1)
	END
END

/* Now convert user name to user id after checking its existence */
IF (@object_type = "LG")
BEGIN
	IF not exists(select suid from master..syslogins 
			where (name = @object_name))
	BEGIN
		/*
		** 17231, "No login with the specified name '%1!' exists"
		*/
		raiserror 17231, @object_name
		return(1)
	END

	select @user_id = (select suid from master..syslogins 
				where (name = @object_name))
END
ELSE IF ((@object_type = "AP") and (@scope is not NULL))
BEGIN
	IF not exists(select suid from master..syslogins where (name = @scope))
	BEGIN
		/*
		** 18259, "No login with specified name '%1!' exists"
		*/
	        raiserror 18259, @scope
		return(1)
	END

	select @user_id = (select suid from master..syslogins 
				where (name = @scope))
END

/*
** Now hook up with Sysattributes Table..
** Verify that the attributes passed to sysattributes is correct.
** Note that for stored procedures, the sysattributes table in the current 
** database is used. For other objects, the sysattributes table in master 
** is used.
*/

select @attrib_id = 0

IF (@object_type = "LG")
BEGIN
	IF attrib_valid(6, @attrib_id, @object_type, @user_id, NULL, NULL, 
	    NULL, @scope, NULL, @classname, NULL, NULL, "", @action ) = 0
	BEGIN
		/*
		** 18260, "Validation of execution class binding failed.
		**	   Check server errorlog for any additional 
		**	   information."
		*/
		raiserror 18260
		return(1)
	END
	ELSE
	BEGIN
		IF exists(select * from master..sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object = @user_id AND
			object_cinfo = @scope)
		BEGIN
			update master..sysattributes
				set char_value = @classname
				where class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object = @user_id AND
				object_cinfo = @scope
		END
		ELSE
		BEGIN
			insert master..sysattributes
				(class, attribute, object_type, object, 
				 object_cinfo, char_value)
				values(6,@attrib_id, @object_type, @user_id, 
					@scope, @classname)
		END

		IF attrib_notify(6, @attrib_id, @object_type, @user_id,
			NULL, NULL, NULL, @scope, NULL, @classname,
			NULL, NULL, "", @action) = 0
		BEGIN
			/*
			** 18261, "Failed to bind '%1!' to execution class 
			**	   '%2!'. Check server errorlog for any
			**	   additional information."
			*/
			delete master..sysattributes where (class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object = @user_id AND
				object_cinfo = @scope)
	        	raiserror 18261, @object_name, @classname
			return(1)
		END
	END
END
ELSE IF (@object_type = "AP")
BEGIN
	IF attrib_valid(6, @attrib_id, @object_type, NULL, @user_id, NULL, 
	    	NULL, @object_name, NULL, @classname, NULL, NULL, "",
		@action ) = 0
	BEGIN
		/*
		** 18260, "Validation of execution class binding failed.
		**	   Check server errorlog for any additional
		**	   information."
		*/
		raiserror 18260
		return(1)
	END
	ELSE
	BEGIN
		IF exists(select * from master..sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object_info1 = @user_id AND
			object_cinfo = @object_name)
		BEGIN
			update master..sysattributes
				set	char_value = @classname
				where	class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @user_id AND
				object_cinfo = @object_name
		END
		ELSE
		BEGIN
			insert master..sysattributes
				(class, attribute, object_type, object_info1, 
				 object_cinfo, char_value)
				values(6,@attrib_id, @object_type, @user_id, 
				@object_name, @classname)
		END

		IF attrib_notify(6, @attrib_id, @object_type, NULL,
			@user_id, NULL, NULL, @object_name, NULL, @classname,
			NULL, NULL, "", @action) = 0
		BEGIN
			/*
			** 18261, "Error on binding '%1!' to execution class 
			**	   '%2!'. Check server errorlog for any 
			**	   additional information."
			*/
			delete master..sysattributes where (class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @user_id AND
				object_cinfo = @object_name)
	        	raiserror 18261, @object_name, @classname
			return(1)
		END
	END
END
ELSE IF (@object_type = "DF")
BEGIN
	IF attrib_valid(6, @attrib_id, @object_type, NULL, NULL, NULL,
		NULL, NULL, NULL, @classname, NULL, NULL, "",
		@action) = 0

	BEGIN
		/*
		** 18260, "Validation of execution class binding failed.
		**         Check server errorlog for any additional
		**         information."
		*/
		raiserror 18260
		return(1)
	END
	ELSE
	BEGIN
		IF exists(select * from master..sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type) 
		BEGIN
			update master..sysattributes
			set	char_value = @classname
			where   class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type 
		END
		ELSE
		BEGIN
			insert master..sysattributes
				(class, attribute, object_type, char_value)
				values(6,@attrib_id, @object_type, @classname)
		END

		IF attrib_notify(6, @attrib_id, @object_type, NULL, NULL, NULL,
			NULL, NULL, NULL, @classname, NULL, NULL, "",
			@action) = 0
		BEGIN
			/*
			** 18261, "Error on binding '%1!' to execution class
			**         '%2!'. Check server errorlog for any
			**         additional information."
			*/
			delete master..sysattributes where (class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				char_value = @classname)
			raiserror 18261, @object_name, @classname
			return(1)
		END
	END
END
ELSE 	/* object is of type "PR" */
BEGIN
	/* For stored procs, we store the owner id and object id of the sp in 
	** sysattributes. 
	*/
	IF attrib_valid(6, @attrib_id, @object_type, @sp_objid, @owner_id, 
	    	NULL, NULL, @object_name, NULL, @classname, NULL, NULL, "",
		@action ) = 0
	BEGIN
		/*
		** 18260, "Validation of execution class binding failed.
		**	   Check server errorlog for any additional
		**	   information."
		*/
		raiserror 18260
		return(1)
	END
	ELSE
	BEGIN
		IF exists(select * from sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object = @sp_objid AND
			object_info1 = @owner_id AND
			object_cinfo = @object_name)
		BEGIN
			update sysattributes
				set	char_value = @classname
				where	class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object = @sp_objid AND
				object_info1 = @owner_id AND
				object_cinfo = @object_name
		END
		ELSE
		BEGIN
			insert sysattributes
				(class, attribute, object_type, object, 
				 object_info1, object_cinfo, char_value)
				values(6, @attrib_id, @object_type, @sp_objid, 
					@owner_id, @object_name, @classname)
		END
		IF attrib_notify(6, @attrib_id, @object_type, @sp_objid,
			NULL, NULL, NULL, @object_name, NULL, @classname,
			NULL, NULL, "", @action) = 0
		BEGIN
			/*
			** 18261, "Failed to bind '%1!' to execution class 
			**	   '%2!'. Check server errorlog for any
			**	   additional information."
			*/
			delete sysattributes where (class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object = @sp_objid AND
				object_info1 = @owner_id AND
				object_cinfo = @object_name)
	        	raiserror 18261, @object_name, @classname
			return(1)
		END
	END	
END
return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_clearpsexe')
begin
	drop procedure sp_clearpsexe
end
go
print "Installing sp_clearpsexe"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_clearpsexe"
** 17260, "Can't run %1! from within a transaction."
** 18262, "A non-SA user can not modify attributes of another task."
** 18263, "A non-SA user can only modify its priority value."
** 18265, "No specification for the specified process exists."
** 18266, "'%1!' is not a valid execution attribute"
** 18267, "Failed to clear value of attribute '%1!' for spid '%2!'. Check
**	   server errorlog for any additional information."
*/

create procedure sp_clearpsexe
@spid		 int,			/* name of class */
@exeattr	 varchar(12)		/* name of execution attribute */
as

declare @attrib_id 	int,
	@user_id	int,
	@action		int,
	@my_suid	int,
	@object_type	varchar(2),
	@dummy		int,
	@loc		int,
	@role		int,
	@attr_val	varchar(255)

select @action = 3
select @user_id = NULL /* Id of user from Syslogins table */

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_clearpsexe"
	return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do "Dirty Reads" */
set transaction isolation level 1


/* Find out if the caller has sa_role. Note that 'sa_role'
** string may be embedded in a user defined role name and
** users with these roles should be checked for permissions.
*/
select @role = 1
select @loc = charindex("sa_role", show_role())
IF ( @loc > 0)
BEGIN
	IF (@loc != 1)
	BEGIN
		/* check for space just before 'sa_role' string */
		IF (ascii(substring(show_role(), (@loc -1), 8)) != 32)
			select @role = 0
	END

	/* check if role string ends in space */
	IF ((@role = 1) AND 
	    (char_length(substring(show_role(), @loc, 
			(char_length(show_role()) - (@loc-1)))) != 7) AND
		(ascii(substring(show_role(), (@loc+7), 1)) != 32))

		select @role = 0
END
ELSE
	select @role = 0

	
/* check that user has sa role or modifying self */
IF (@role = 0)
BEGIN
	select @my_suid = (select suid from master..sysprocesses 
				where spid = @spid)
	IF (@my_suid != suser_id())
	BEGIN
		/*
	 	** 18262, "A non-SA user can not modify attributes of another
		** process."
       		*/
		raiserror 18262
		return (1)
	END
	ELSE IF @exeattr != "priority"
	BEGIN
       	/*
       	** 18263, "A non-SA user can only modify its priority value"
       	*/
		raiserror 18263
		return (1)
	END
END
ELSE
	/* validate that this guy is really the sa */
	IF (proc_role("sa_role") = 0)
		return 1

/* check that @exeattr value specified is valid */
IF ((@exeattr != 'priority')
	and (@exeattr != 'timeslice')
	and (@exeattr != 'enginegroup'))
BEGIN
	/*
	** 18266, "'%1!' is not a valid execution attribute"
	*/
	raiserror 18266, @exeattr
	return (1)
END



/* Check that an entry exists in the sysattributes table */
select @attr_val = (select char_value from master..sysattributes where
			(class = 6 AND
			attribute = 3 AND
			object_type = "PS" AND
			object_info1 = @spid AND
			object_cinfo = @exeattr))
IF (@attr_val is NULL)
BEGIN
	/*
	** 18265, "No specification for the specified process exists."
	*/
	raiserror 18265
	return (1)
END

/* Now hook up with Sysattributes Table */

select @attrib_id = 3
select @object_type = "PS"
BEGIN
	delete master..sysattributes
			where class = 6 AND
			attribute = 3 AND
			object_type = "PS" AND
			object_info1 = @spid AND
			object_cinfo = @exeattr

	IF attrib_notify(6, @attrib_id, @object_type, NULL, @spid,
			NULL, NULL, @exeattr, NULL, NULL,
			NULL, NULL, "", @action) = 0
	BEGIN
		insert master..sysattributes
		(class, attribute, object_type, object_info1, object_cinfo,
		 char_value)
		values (6, 3, 'PS', @spid, @exeattr, @attr_val)

		/*
		** 18267, "Failed to clear value of attribute '%1!' for
		**	   spid '%2!'. Check server errorlog for any
		**	   additional information."
		*/
		raiserror 18267, @exeattr, @spid
		return (1)
	END
END
return(0)
go
exec sp_procxmode 'sp_clearpsexe', 'anymode'
go
grant execute on sp_clearpsexe to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropengine')
begin
	drop procedure sp_dropengine
end
go
print "Installing sp_dropengine"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_dropengine"
**
** 17260, "Can't run %1! from within a transaction."
** 18251, "Cannot modify pre-defined engine groups."
** 18248, "Validation of Engine Group modification failed. Check server
**	   errorlog for any additional information."
** 18268, "Internal Error: Wrong engine list format in sysattributes." 
** 18269, "Cannot drop engine group used in class definition."
** 18270, "Failed to drop engine '%1!' from engine group '%2!'. Check server
**	   errorlog for any additional information. List of engines in
**	   engine group unchanged."
** 18271, "Cannot drop engine group bound to a SQL Server process."
** 19703, "Instance id '%1!' is not valid under instance system view."
*/

create procedure sp_dropengine
@engine_number int,			/* engine number of engine */
@engine_group	varchar(255),		/* engine group name */
@instanceid	smallint = NULL		/* instance id for SDC */
as

declare 	@attrib_id 	int,
	@action		int,
	@engine_name	varchar(5),
	@object_type	varchar(2),
	@engine_list	varchar(255),
	@upcase_str	varchar(255),
	@scope		varchar(32)	/* SDC command execution scope */

declare @retstat  int

select @action = 3		/* drop operation */
select @attrib_id = 1  		/* attribute is ENGINE_GROUP */
select @object_type = 'EG'
 
/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_dropengine"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Don't do "Dirty Reads" */
set transaction isolation level 1

/* first convert any system defined engine group name to upper case */
select @upcase_str = upper(@engine_group)
IF ((@upcase_str = "ANYENGINE") OR (@upcase_str = "LASTONLINE"))
	select @engine_group = @upcase_str

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/

IF ((@engine_group = "ANYENGINE") OR (@engine_group = "LASTONLINE"))
BEGIN
	/*
	** 18251, "Can't modify pre-defined engine groups."
	*/
	raiserror 18251
	return (1)
END

/* For SDC, use @@instanceid if NULL is specified */
if (@@clustermode = "shared disk cluster")
BEGIN
	if ((@@system_view = "instance") AND
		(@instanceid != NULL) AND
		(@instanceid != @@instanceid))
	BEGIN
		/*
		** 19703, "Instance id '%1!' is not valid under instance
		**         system view."
		*/
		raiserror 19703, @instanceid
		return (1)
	END

	if (@instanceid = NULL)
		select @instanceid = @@instanceid
END
else
	select @instanceid = NULL

/*
** Select the engine list for the given engine group name. Then parse
** the engine list to grab the engine we are looking for and then
** drop the engine from the list.
*/
select @engine_list = (select char_value
			from master..sysattributes where
			class = 6 AND
			attribute = 1 AND
			object_type = 'EG' AND
			object_cinfo = @engine_group AND
			object_info3 = @instanceid)

/* local vars needed to parse the engine list */
DECLARE	@length		int,
	@new_list	varchar(255),
	@term		int,
	@curlen		int,
	@tengine_name	varchar(5),	/* trimmed engine name */
	@engine		int

/*
** The engine list for a given group is kept in the format -
** engine # : engine # : engine # : ...
** Each element is of fixed length. After selecting an engine name,
** trim it to delete spaces and convert the engine name to an integer.
*/	
select @length = char_length(@engine_list)
select @term = charindex(":", @engine_list)
select @curlen = 0

IF ((@engine_list is not NULL) AND (@term = 0))
BEGIN
	/*
	** 18268, "Internal Error: Wrong engine list format in sysattributes" 
	*/
	raiserror 18268
	return(1)
END
ELSE
BEGIN
	IF attrib_valid(6, @attrib_id, @object_type, NULL, NULL, NULL, 
			@instanceid, @engine_group, @engine_number, NULL, 
			NULL, NULL, "", @action ) = 0
	BEGIN
		/*
		** 18248, "Validation of Engine Group modification failed.Check
		**	   server errorlog for any additional information."
		*/
		raiserror 18248
		return(1)
	END

	WHILE (@curlen < @length)
	BEGIN
		select @engine_name = substring(@engine_list, (@curlen + 1), 
						(@term -1))
		select @tengine_name = ltrim(@engine_name)
		select @engine = convert(integer, @tengine_name)

		/* Build the engine list, ignoring the engine to be dropped */
		IF (@engine != @engine_number)
		BEGIN
			IF (@curlen = 0)
				select @new_list = @engine_name + ':'
			ELSE
				select @new_list = @new_list + @engine_name 
									+ ':'
		END

		select @curlen = @curlen + @term
	END
END

IF (char_length(@new_list) > 0)

	/*
	** This is not the last engine in the group, so simply
	** update the engine list
	*/
	update master..sysattributes
		set char_value = @new_list
		where class = 6 AND
		attribute = 1 AND
		object_type = 'EG' AND
		object_cinfo = @engine_group AND
		object_info3 = @instanceid
ELSE
BEGIN
	/*
	** Check that no user defined class is using this engine group 
	** that is about to be deleted.
	*/

	DECLARE engine_info cursor for
			(select char_value from 
			master..sysattributes where
			(class = 6 AND
			attribute = 2 AND
			object_type = 'UC' AND
			object_info3 = @instanceid))

	DECLARE @class_str	varchar(255),
		@groupname  	varchar(255),
		@len		int,
		@spid		int

	OPEN engine_info

	FETCH engine_info into @class_str
        WHILE (@@sqlstatus != 2)
	BEGIN
		/*
		** The list of attributes for a given execution
		** class is in the format -
		** <priority> : <timeslice> : <enginegroup>
		** with 10/10/30 length fields respectively in addition
		** to the delimitors ':'
		*/
		select @len = char_length(@class_str)
		select @term = charindex(":", @class_str)

		/* select engine group field from class string */
		IF @term != 0
			select @groupname = 
			substring(@class_str,(@term+10+2),(@len - @term - 11))

		IF (@groupname = @engine_group)
		BEGIN
			/* Engine group is used by a class */
			CLOSE engine_info
			deallocate cursor engine_info

			/*
			** 18269, "Cannot drop engine group used in class 
			**	   definition."
			*/
			raiserror 18269
			return(1)
		END
		FETCH engine_info into @class_str
	END

	CLOSE engine_info
	deallocate cursor engine_info

	/* Check that no sessions are using this engine group */

	/* SDC only, check clusterwide sysprocesses */ 
	if (@@clustermode = "shared disk cluster")
	BEGIN	
		select @scope=@@system_view
		set system_view cluster
	END

	DECLARE engine_info cursor for
			(select char_value, object_info1 from 
			master..sysattributes where
			(class = 6 AND
			attribute = 3 AND
			object_cinfo = 'enginegroup' AND
			object_type = 'PS'))

	OPEN engine_info

	FETCH engine_info into @groupname, @spid
        WHILE (@@sqlstatus != 2)
	BEGIN
		IF ((@spid != NULL) AND
			exists (select * from master..sysprocesses
					where spid = @spid) AND
			(@groupname = @engine_group))
		BEGIN
			/* Engine group is used by a session */
			CLOSE engine_info
			deallocate cursor engine_info

			/*
			** 18271, "Cannot drop engine group bound to a 
			**	   SQL Server process"
			*/
			raiserror 18271
			return(1)
		END
		FETCH engine_info into @groupname, @spid
	END

	CLOSE engine_info
	deallocate cursor engine_info

	/* SDC only: restore previous system_view scope */
	if (@@clustermode = "shared disk cluster")
	BEGIN
		set system_view @scope
	END

	delete master..sysattributes
		where class = 6 AND
		attribute = 1 AND
		object_type = 'EG' AND
		object_cinfo = @engine_group AND
		object_info3 = @instanceid

END

if (attrib_notify(6, @attrib_id, @object_type, NULL, @engine_number, NULL,
            	@instanceid, @engine_group, NULL, NULL, NULL, NULL, "",
		@action) = 0)
BEGIN
	/*
	** 18270, "Failed to drop engine '%1!' from engine group '%2!'.
	**	   Check server errorlog for any additional information.
	**	   List of engines in engine group unchanged."
	*/
	IF (char_length(@new_list) > 0)
		update master..sysattributes
		set char_value = @engine_list
		where class = 6 AND
		attribute = 1 AND
		object_type = 'EG' AND
		object_cinfo = @engine_group AND
		object_info3 = @instanceid
	ELSE
		insert master..sysattributes
		(class, attribute, object_type, object_info3, object_cinfo, char_value)
		values(6, 1, 'EG', @instanceid, @engine_group, @engine_list)

	raiserror 18270, @engine_number, @engine_group
	return(1)
END
return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropexeclass')
begin
	drop procedure sp_dropexeclass
end
go
print "Installing sp_dropexeclass"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_dropexeclass"
**
** 17260, "Can't run %1! from within a transaction."
** 18272, "'%1!' is not a valid execution class name"
** 18273, "Either '%1!' is being used so it cannot be dropped or an
**	   internal error occurred. Check server errorlog for any
**	   additional information."
** 18555, "%1! is a system defined execution class which cannot be dropped."
*/

create procedure sp_dropexeclass
@classname varchar(255)			/* name of class */

as

	declare @attrib_id 	int,
	@action		int,
	@object_type	varchar(2),
	@upcase_str	varchar(255)

select @action = 3	/* drop action */
select @attrib_id = 2  	/* attribute is USERCLASS_DEFN */
select @object_type = 'UC' /* the type for USERCLASS_DEFN */

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_dropexeclass"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do "Dirty Reads" */
set transaction isolation level 1

/*
** Check to see that the input params are correct
*/
select @upcase_str = upper(@classname)
IF ((@upcase_str = "EC0") OR (@upcase_str = "EC1") OR
	(@upcase_str = "EC2") OR (@upcase_str = "EC3"))
BEGIN
	/*
	** 18555, "%1! is a system defined execution class which cannot be
	**	   dropped."
	*/
	raiserror 18555, @classname
	return (1)
END

IF not exists(select * from master..sysattributes where
	class = 6 AND
	attribute = @attrib_id AND
	object_type = @object_type AND
	object_cinfo = @classname)
BEGIN
	/*
	** 18272, "'%1!' is not a valid execution class name"
	*/
	raiserror 18272, @classname
	return (1)
END

/* Check that the execution class is not bound to any object in any db */
IF attrib_valid(6, @attrib_id, @object_type, NULL, NULL, NULL, 
	    	NULL, @classname, NULL, NULL, NULL, NULL, "",
		@action ) = 0

BEGIN
	/*
	** 18273, "Either '%1!' is being used so it cannot be dropped or
	**	   an internal error occurred. Check server errorlog for
	**	   any additional information."
	*/
	raiserror 18273, @classname
	return (1)
END

/* Now delete exec class definition entry from Sysattributes Table in master */

BEGIN
        delete master..sysattributes
                where   class = 6 AND
                attribute = @attrib_id AND
                object_type = 'UC' AND
                object_cinfo = @classname
END

return (0)

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setpsexe')
begin
	drop procedure sp_setpsexe
end
go
print "Installing sp_setpsexe"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_setpsexe"
** 17260, "Can't run %1! from within a transaction."
** 18262, "A non-SA user can not modify attributes of another task."
** 18274, "A non-SA user can only lower its own priority value."
** 18264, "No SQL Server process with the specified ID exists."
** 18266, "'%1!' is not a valid execution attribute"
** 18252, "'%1!' value '%2!' is not valid."
** 18275, "Failed to set attribute '%1!' to '%2!' for spid '%3!'. Check
**	   server errorlog for any additional information."
*/

create procedure sp_setpsexe
@spid		 int,			/* id of SQL Server process */
@exeattr	 varchar(12),		/* name of execution attribute */
@value		 varchar(30)		/* value assigned to attribute */
as

	declare @attrib_id 	int,
	@user_id	int,
	@action		int,
	@my_suid	int,
	@object_type	varchar(2),
	@dummy		int,
	@curvalue	varchar(30),
	@oldvalue	varchar(255),
	@loc		int,
	@role		int,
	@upcase_str	varchar(30)

select @action = 1	/* add operation */
select @user_id = NULL 	/* Id of user from Syslogins table */
select @dummy = 0
select @oldvalue = NULL

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_setpsexe"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do "Dirty Reads" */
set transaction isolation level 1


/* convert system defined values to upper case */
select @upcase_str = upper(@value)
IF ((@upcase_str = "HIGH") OR (@upcase_str = "MEDIUM") OR
	(@upcase_str = "LOW") OR (@upcase_str = "ANYENGINE") OR
	(@upcase_str = "LASTONLINE"))
	select @value = @upcase_str

/* Find out if the caller has sa_role. Note that 'sa_role'
** string may be embedded in a user defined role name and
** users with these roles should be checked for permissions.
*/
select @role = 1
select @loc = charindex("sa_role", show_role())
IF ( @loc > 0)
BEGIN
	IF (@loc != 1)
	BEGIN
		/* check for space just before 'sa_role' string */
		IF (ascii(substring(show_role(), (@loc -1), 8)) != 32)
			select @role = 0
	END

	/* check if role string ends in space */
	IF ((@role = 1) AND 
	    (char_length(substring(show_role(), @loc, 
			(char_length(show_role()) - (@loc-1)))) != 7) AND
		(ascii(substring(show_role(), (@loc+7), 1)) != 32))

		select @role = 0
END
ELSE
	select @role = 0

/* check that user has sa role or modifying self */
IF (@role = 0)
BEGIN
	select @my_suid = (select suid from master..sysprocesses 
				where spid = @spid)
	select @curvalue = (select priority from master..sysprocesses 
				where spid = @spid)
	IF (@my_suid != suser_id())
	BEGIN
        	/*
        	** 18262, "A non-SA user can not modify attributes of another
		**	  process."
        	*/
		raiserror 18262
        	return (1)
	END
	ELSE IF @exeattr != "priority"
	BEGIN
        	/*
        	** 18263, "A non-SA user can only modify its priority value"
        	*/
		raiserror 18263
        	return (1)
	END
	ELSE IF (@curvalue != "HIGH" )
	BEGIN
		IF (((@curvalue = "MEDIUM") AND (@value = "HIGH")) OR
			((@curvalue = "LOW") AND (@value = "HIGH")) OR
			((@curvalue = "LOW") AND (@value = "MEDIUM")))
		BEGIN
        		/*
        		** 18274, "A non-SA user can only lower its priority 
			** value"
        		*/
			raiserror 18274
        		return (1)
		END
	END
END
ELSE
	/* validate that this guy is really the sa */
	IF (proc_role("sa_role") = 0)
		return 1

/*
** Check to see that the input params are correct
*/
/* Check that process exists */
IF @spid not in(select spid from master..sysprocesses)
BEGIN
	/*
	** 18264,"No SQL Server process with specified id exists."
	*/
	raiserror 18264
	return (1)
END

/* check that @exeattr value specified is valid */
IF ((@exeattr != 'priority')
	and (@exeattr != 'timeslice')
	and (@exeattr != 'enginegroup'))
BEGIN
	/*
	** 18266, "'%1!' is not a valid execution attribute"
	*/
	raiserror 18266, @exeattr
	return (1)
END

/* check the priority value is correct */
IF (@exeattr = "priority")
BEGIN
	IF ((@value != "HIGH") AND
		(@value != "MEDIUM") AND
		(@value != "LOW"))
	BEGIN
		/*
		** 18252, "'%1!' value '%2!' is not valid."
		*/
		raiserror 18252, @exeattr, @value
    	return (1)
	END
END

/* check that enginegroup value is ok */
IF ((@exeattr = "enginegroup") AND (@value != "ANYENGINE") AND
					(@value != "LASTONLINE"))
BEGIN
	IF not exists(select * from master..sysattributes where
			class = 6 AND
			attribute = 1 AND
			object_type = 'EG' AND
			object_cinfo = @value)

	BEGIN
		/*
		** 18252, "'%1!' value '%2!' is not valid."
		*/
        	raiserror 18252, @exeattr, @value
        	return (1)
	END
END



/*
** Now hook up with Sysattributes Table...
*/

select @attrib_id = 3
select @object_type = "PS"
BEGIN
	select @oldvalue = (select char_value from master..sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object_info1 = @spid AND
			object_cinfo = @exeattr)
	IF (@oldvalue is not NULL)
	BEGIN
		update master..sysattributes
				set char_value = @value
				where class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @spid AND
				object_cinfo = @exeattr
	END
	ELSE
	BEGIN
		insert master..sysattributes
				(class, attribute, object_type, object_info1, 
				 object_cinfo, char_value)
			values(6,@attrib_id, @object_type, @spid, 
					@exeattr, @value)
	END

	IF attrib_notify(6, @attrib_id, @object_type, NULL, @spid,
			NULL, NULL, @exeattr, NULL, @value,
			NULL, NULL, "", @action) = 0
	BEGIN
		/*
		** 18275, "Failed to set attribute '%1!' to '%2!' for spid
		**	   '%3!'. Check server errorlog for any additional
		**	   information."
		*/
		IF (@oldvalue is not NULL)
			update master..sysattributes
				set char_value = @oldvalue
				where class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @spid AND
				object_cinfo = @exeattr
		ELSE
			delete master..sysattributes
				where class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @spid AND
				object_cinfo = @exeattr

        	raiserror 18275, @exeattr, @value, @spid
        	return (1)
	END
END

return (0)
go
exec sp_procxmode 'sp_setpsexe', 'anymode'
go
grant execute on sp_setpsexe to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showcontrolinfo')
begin
	drop procedure sp_showcontrolinfo
end
go
print "Installing sp_showcontrolinfo"
go

/* Sccsid = %Z% generic/sproc/%M% %I% %G%  */

/*
** Messages for "sp_showcontrolinfo"		????
** 
** 17260, "Can't run %1! from within a transaction."
** 18276, "'%1!" is not a valid object type."
** 18291, "The parameter value '%1!' is invalid."
*/

create procedure sp_showcontrolinfo
@object_type varchar(2) = NULL,		/* type of object */
@object_name varchar(255) = NULL,	/* name of object */
@spid	int = NULL			/* SQL Server process id */
as

declare	@attrib_id 	int,
	@user_name	varchar(255),
	@upcase_str	varchar(2)

select @attrib_id = 0 	/* initialization */

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_showcontrolinfo"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont use any "Dirty Reads" */
set transaction isolation level 1

/* convert object_type to upper case */
IF (@object_type is not NULL)
	select @object_type = upper(@object_type)

/*
** Check to see that the input params are correct
*/
IF @object_type not in( NULL, 'AP', 'LG', 'PR', 'PS', 'EG', 'DF')
BEGIN
        /*
        ** 18276,"'%1!' is not a valid object type." 
        */
        raiserror 18276, @object_type
        return (1)
END

IF ((@object_type = 'DF') AND ((@object_name is not NULL) OR (@spid is not NULL)))
BEGIN
	/* 18291, "The parameter value '%1!' is invalid." */
	raiserror 18291, "for object name or spid"
	return 1
END

/* 
** Create Table to hold results
** For SDC, there is one extra column, instance id; For SMP, column value null.
*/
CREATE table #shcinfo_res
	(type		varchar(2),
 	object_name	varchar(255) null,
 	scope		varchar(255) null,
 	exec_class	varchar(255) null,
 	engine_group	varchar(255) null,
 	engines		varchar(768) null,
 	spid		int null,
 	attribute	varchar(255) null,
 	attribute_value	varchar(255) null,
	instanceid	int null)

/* 
** Now look into Sysattributes Table...
** Note that this sp looks into the sysattributes table of the current db.
*/
DECLARE appl_info cursor for
	select object_type, object, object_info1, object_info3,
		object_cinfo, int_value, char_value
	from sysattributes
	where (class = 6)

DECLARE @type	varchar(2),
	@obj	int,
	@info1  int,
	@info3	int,
	@cinfo  varchar(255),
	@intval int,
	@charval varchar(768),
	@eng_str 	varchar(768),
	@eng_num	varchar(10),
	@eng_list	varchar(768),
	@len		int,
	@term		int

OPEN appl_info

FETCH appl_info into @type, @obj, @info1, @info3, @cinfo, @intval, @charval
WHILE (@@sqlstatus != 2)
BEGIN
		/*
		** Get the definitions for the given object type or all
		** object types in the sysattributes table.
		*/
		IF ((@object_type is NULL) OR (@object_type = @type))

			/* Look for class bindings for an user */

			IF (@type = "LG")
			BEGIN
				select @user_name = (select name from
					master..syslogins where (suid = @obj))
				IF ((@object_name is NULL) OR
						(@object_name = @user_name))
				BEGIN
					insert into #shcinfo_res
					values (@type, @user_name,
						@cinfo, @charval, NULL,
						NULL, NULL, NULL, NULL, @info3)
				END
			END

			/* Look for class bindings for an application */

			ELSE IF (@type = "AP")
			BEGIN
				IF ((@object_name is NULL) OR
						(@object_name = @cinfo))
				BEGIN
					IF (@info1 >= 0)
						select @user_name =
						(select name from
						master..syslogins 
						where (suid =@info1))

					insert into #shcinfo_res
						values (@type, @cinfo,
							@user_name, @charval,
							NULL, NULL, NULL, 
							NULL, NULL, @info3)
				END
			END

			/* Look for class bindings for a stored proc */

			ELSE IF (@type = "PR")
			BEGIN
				IF ((@object_name is NULL) OR
						(@object_name = @cinfo))
				BEGIN
					select @user_name =
					(select name from sysusers
						where (uid = @info1))
					insert into #shcinfo_res
					values (@type, @cinfo, @user_name, 
						@charval, NULL, NULL, NULL,
						NULL, NULL, @info3)
				END
			END
			
			/* Look for Session level attribute definitions */

			ELSE IF (@type = "PS")
			BEGIN
				IF ((@spid is NULL) OR
						(@spid = @info1))
				BEGIN
					insert into #shcinfo_res
					values (@type, NULL, NULL, NULL,
						NULL, NULL, @info1, @cinfo, 
						@charval, @info3)
				END
			END

			/* Look for engine attribute values */

			ELSE IF (@type = "EG")
			BEGIN
				IF ((@object_name is NULL) OR
						(@object_name = @cinfo))
				BEGIN

					/* format the list of engines */
					select @len = 0
					select @term = charindex(":", @charval)

					IF (@term != 0)
					BEGIN
						select @eng_str = 
								rtrim(@charval)
						while (@len < 
							char_length(@eng_str))
						BEGIN
							select @eng_num =
							substring(@eng_str, 
							   (@len+1), (@term-1))

							IF (@len = 0)
								select 
								@eng_list = 
								ltrim(@eng_num)
							ELSE
								select 
								@eng_list = 
								@eng_list + 
								"," + 
								ltrim(@eng_num)
							select @len = @len + 
								@term
						END
					END
					ELSE
					BEGIN
						select @eng_list = @charval
					END

					/*
					** For SMP, instanceid column is null
					** For SDC, it shows instance id.
					*/
					insert into #shcinfo_res
					values (@type, NULL, NULL, NULL,
						@cinfo, @eng_list, NULL,
						NULL, NULL, @info3)
				END
			END

			/* Look for default class attributes */
			ELSE IF (@type = "DF")
			BEGIN
				insert into #shcinfo_res
					values (@type, NULL, NULL, @charval, 
					NULL, NULL, NULL, NULL, NULL, @info3)
			END

	/* Fetch the next row from sysattributes table */
	FETCH appl_info into @type, @obj, @info1, @info3, @cinfo, 
						@intval, @charval
END

/* Now print out all the results we got */
exec sp_autoformat #shcinfo_res

/* Cleanup */			
close appl_info
deallocate cursor appl_info
drop table #shcinfo_res
return(0)
go
exec sp_procxmode 'sp_showcontrolinfo', 'anymode'
go
grant execute on sp_showcontrolinfo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showexeclass')
begin
	drop procedure sp_showexeclass
end
go
print "Installing sp_showexeclass"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_showexeclass"
**
** 17260, "Can't run %1! from within a transaction."
** 18277, "Execution class '%1!' is not a valid class"
*/

create procedure sp_showexeclass
@execlassname	 varchar(255) = NULL		/* Class name */

as

declare	@attrib_id 	int,
	@engine 	int,
	@term 		int,
	@object_type	varchar(2),
	@eng_gr		varchar(30),
	@priority	varchar(10),	
	@ts_str		varchar(10),
	@eng_str	varchar(255),
	@eng_num	varchar(10),
	@eng_list	varchar(255),
	@len		int,
	@upcase_str	varchar(255),
	@instanceid	int,		/* instance id */
	@i		smallint, /* loop index to iterate sysengines */
        @max_instance	smallint  /* max instance number for cluster */

select @instanceid = NULL

/*
**  IF we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_showexeclass"
        return (1)
END
else
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do any "Dirty Reads" */
set transaction isolation level 1

/* first convert any system defined class name to upper case */
IF (@execlassname is not NULL)
BEGIN
	select @upcase_str = upper(@execlassname)
	IF ((@upcase_str = "EC1") OR (@upcase_str = "EC2") OR
		(@upcase_str = "EC3"))
		select @execlassname = @upcase_str
END

/* check that class value is ok */
IF ((@execlassname is not NULL) AND (@execlassname != 'EC1') AND
	(@execlassname != 'EC2') AND
	(@execlassname != 'EC3'))
BEGIN
	IF not exists(select * from master..sysattributes where
		class = 6 AND
		attribute = 2 AND
		object_cinfo = @execlassname)

	BEGIN
        	/*
        	** 18277, "Execution class '%1!' is not a valid class"
        	*/
        	raiserror 18277, @execlassname
        	return (1)
	END
END

/* 
** Now hook up with Sysattributes Table...
** Verify that the attributes passed to sysattributes is correct.
** Errors will be displayed from the builtin functions. Note that for
** stored procedures, the sysattributes table in the current database is
** used. For other objects, the sysattributes table in master is used.
*/

select @attrib_id = 2
select @object_type = "UC"

CREATE table #shecl_desc
	(classname		varchar(30),
	 priority		varchar(10),
	 engine_group		varchar(30),
	 engines		varchar(30) null)

/* Collect the attribute values for 'EC1' Class */
IF ((@execlassname = "EC1") OR (@execlassname is NULL))
	BEGIN
		select @priority = 'HIGH'
		select @eng_gr	= 'ANYENGINE'
		select @eng_str = 'ALL'
		insert into #shecl_desc 
			values ("EC1", @priority, @eng_gr, @eng_str)

	END

/* Collect the attribute values for 'EC2' Class */
IF ((@execlassname = "EC2") OR (@execlassname is NULL))
	BEGIN
		select @priority = 'MEDIUM'
		select @eng_gr	= 'ANYENGINE'
		select @eng_str = 'ALL'
		insert into #shecl_desc 
			values ("EC2", @priority, @eng_gr, @eng_str)

	END

/* Collect the attribute values for 'EC3' Class */
IF ((@execlassname = "EC3") OR (@execlassname is NULL))
BEGIN
	select @priority = 'LOW'
	select @eng_gr = 'LASTONLINE'
	if (@@system_view != "cluster")
	BEGIN
		select @engine = (select max(engine) from master..sysengines
			where (status = 'online'))
		select @eng_str = convert(char(5), @engine)
		insert into #shecl_desc
			values ("EC3", @priority, @eng_gr, @eng_str)
	END

END

/* Collect attribute values for specified user defined class or all classes */
IF ((@execlassname is NULL) OR (@execlassname NOT IN ("EC1", "EC2", "EC3"))) 
	BEGIN
		DECLARE class_info cursor for
			(select object_cinfo, char_value, object_info3 from
			master..sysattributes where
			(class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type))

		DECLARE @class_str	varchar(255),
			@classname  	varchar(30)

		OPEN class_info

		FETCH class_info into @classname, @class_str, @instanceid
              	WHILE (@@sqlstatus != 2)
		BEGIN
			IF ((@execlassname is NULL) OR 
					(@execlassname = @classname))
			BEGIN
				/*
				** Parse the string to get the task priority
				** and engine group name for this class.
				** The class string is in the format 
				** <priority> : <timeslice> : enginegroup
				** with 10/10/30 length fields respectively,
				** in addition to the delimitors.
				*/
				select @term = charindex(":", @class_str)
		
				select @priority = 
					substring(@class_str, 1, (@term-1))
				select @ts_str = 
					substring(@class_str, (@term + 1), 10)
				select @eng_gr = 
					substring(@class_str, (@term + 12), 30)

				IF (@eng_gr = 'ANYENGINE')
					select @eng_list = 'ALL'
				ELSE IF (@eng_gr = 'LASTONLINE')
				BEGIN
					/*
					** For SDC, output format
					**   "engine#  instance <id> 
					*/
					select @engine = (select max(engine)
						from master..sysengines

						where (status = 'online'))

					select @eng_list = convert(char(5), 
								@engine)

				END
				ELSE
				BEGIN
					/*
					** Get the list of engines from the 
					** group name. The engine list is in
					** the format engine # : engine # : ..
					** For SMP or SDC with instance scope
					** only local bound engine group
					** For SDC with cluster scope
					** local and remote engine group 
					*/
					select @eng_str=(select char_value from
						master..sysattributes 
						where (class = 6 AND
						attribute = 1 AND
						object_type = 'EG' AND

						object_cinfo = @eng_gr))
					
					/* format the list of engines */
					select @len = 0
					select @term = charindex(":", @eng_str)

					IF (@term != 0)
					BEGIN
						select @eng_str=rtrim(@eng_str)
						while (@len < 
							char_length(@eng_str))
						BEGIN
							select @eng_num =
							substring(@eng_str, 
								(@len+1), 
								(@term-1))
							IF (@len = 0)
								select 
								@eng_list = 
								ltrim(@eng_num)
							ELSE
								select 
								@eng_list = 
							    	@eng_list + 
								"," + 
							    	ltrim(@eng_num)
							select @len = @len + 
									@term
						END
					END
					ELSE
					BEGIN
						select @eng_list = @eng_str
					END

				END

				/* Insert all the collected values */
				insert into #shecl_desc 
				values (@classname, @priority, @eng_gr, 
					@eng_list)
			END
			FETCH class_info into @classname, @class_str,
					@instanceid
		END

		CLOSE class_info
		deallocate cursor class_info

	END

/* Display values and cleanup */
select * from #shecl_desc
drop table #shecl_desc
return (0)
go
exec sp_procxmode 'sp_showexeclass', 'anymode'
go
grant execute on sp_showexeclass to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showpsexe')
begin
	drop procedure sp_showpsexe
end
go
print "Installing sp_showpsexe"
go

/* Sccsid = %Z% generic/include/%M% %I% %G%  */

/*
** Messages for "sp_showpsexe"		????
**
** 17260, "Can't run %1! from within a transaction."
** 18264, "No SQL Server process with specified ID exists"  
*/

create procedure sp_showpsexe
 
@spid	smallint = NULL		/* ASE process id */
 
as
declare	@msg		varchar(1024),
	@user_name	varchar(30)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        exec sp_getmessage 17260, @msg output
        print @msg, "sp_showpsexe"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont use any "Dirty Reads" */
set transaction isolation level 1

/*
** Check to see that the input params are correct
*/
 
/* Check that the supplied spid is ok */
IF (@spid is not NULL )
BEGIN
	IF @spid not in(select spid from master..sysprocesses)
	BEGIN
        	/*
        	** 18264, "No SQL Server process with specified ID exists."
        	*/
        	exec sp_getmessage 18264, @msg output
        	print @msg
        	return (1) 
	END
END
 
/* Create Tables to hold results */
CREATE table #shtsk_restab
	(

	spid			smallint,

	 appl_name		varchar(30) null,
	 login_name		varchar(30) null,
	 exec_class		varchar(30) null,
	 current_priority	varchar(10),
	 task_affinity		varchar(30) null,
	 instanceid		smallint null)

/* Now look into Sysprocesses Table */
DECLARE task_info cursor for
	select spid, suid, program_name, execlass, priority, affinity, cmd

	from master..sysprocesses

DECLARE @task		smallint,
	@id		int,
	@applname  	varchar(30),
	@class_str	varchar(30),
	@pri_str	varchar(10),
	@affinity_str	varchar(30),
	@cmd_name	varchar(30),
	@instanceid	smallint

OPEN task_info

FETCH task_info into @task, @id, @applname, @class_str, @pri_str, 
			@affinity_str, @cmd_name
	

WHILE (@@sqlstatus != 2)
BEGIN
	select @user_name = suser_name(@id)
	IF ((@cmd_name != "HK WASH")  AND
	    (@cmd_name != "HK GC") AND
	    (@cmd_name != "HK CHORES") AND
	    ((select name from master..syslogins where (suid = @id)) is NULL))
	BEGIN
		FETCH task_info into @task, @id, @applname, @class_str,
			@pri_str, @affinity_str, @cmd_name

		continue
	END

	IF ((@spid is NULL) OR (@spid = @task))
	BEGIN
		IF (@affinity_str = "ANYENGINE")
			select @affinity_str = "NONE"

		insert into #shtsk_restab
			values (@task, @applname, @user_name,
				@class_str, @pri_str, @affinity_str, 

				NULL)

	END

	/* Fetch the next row from sysprocesses table */

	FETCH task_info into @task, @id, @applname, @class_str, @pri_str,
				@affinity_str, @cmd_name

END


/* 
** Now print out all the results we got.
** For SMP, omit instanceid column. 
*/

        select spid, appl_name, login_name, exec_class,
                current_priority, task_affinity
        from #shtsk_restab


/* Cleanup */
CLOSE task_info
deallocate cursor task_info
drop table #shtsk_restab
return(0)
go
exec sp_procxmode 'sp_showpsexe', 'anymode'
go
grant execute on sp_showpsexe to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_unbindexeclass')
begin
	drop procedure sp_unbindexeclass
end
go
print "Installing sp_unbindexeclass"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%"	*/

/*
** Messages for "sp_unbindexeclass"
** 17260, "Can't run %1! from within a transaction."
** 18255, "%1! cannot be NULL."
** 18256, "%1! is not a valid object type for this stored procedure."
** 18259, "No login with the specified name '%1!' exists."
** 18278, "Failed to unbind '%1!' from execution class. Check server errorlog
**	   for any additional information."
** 18279, "The specified binding to be dropped does not exist"
** 18552, "%1! is not a valid user of this database.
** 18291, "The parameter value '%1!' is invalid."
*/

create procedure sp_unbindexeclass
@object_name varchar(255),		/* name of object */
@object_type varchar(2),		/* Type of object */
@scope varchar(255) = null       	/* user scope of the class */
as

declare @attrib_id 	int,
	@user_id	int,
	@action		int,
	@classname	varchar(255),
	@sp_objid	int,
	@owner_id	int,
	@stored_objid	int,
	@upcase_str	varchar(2),
	@instanceid	int

select @action = 3	/* drop action */
select @user_id = NULL 	/* Id of user from Syslogins table */
select @attrib_id = 0   /* Execution class attribute */
select @sp_objid = 0	/* object id of a stored proc */
select @instanceid = NULL /* instance id */

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
IF @@trancount > 0
BEGIN
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_dropexeclass"
        return (1)
END
ELSE
BEGIN
	/* Use TSQL mode of unchained transactions */
        set chained off
END

/* Dont do "Dirty Reads" */
set transaction isolation level 1

/* convert types to upper case */
select @upcase_str = upper(@object_type)
IF ((@upcase_str = "LG") OR (@upcase_str = "AP") OR
	(@upcase_str = "PR") OR (@upcase_str = "DF"))
BEGIN
	select @object_type = @upcase_str
END

/*
** Check to see that the input params are correct
*/
IF ((@object_name is NULL) and (@object_type != 'DF'))
BEGIN
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "Object name"
        return (1)
END

IF ((@object_type = "PR") AND (@scope is NULL))
BEGIN
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "Scope"
        return (1)
END

/* For object_type DF the object name and scope should be NULL */
IF ((@object_type = 'DF') AND ((@object_name is not NULL) OR 
				(@scope is not NULL)))
BEGIN
	/*
	** 18291, "The parameter value '%1!' is invalid."
	*/
	raiserror 18291, "Object name or scope"
	return (1)
END


IF ((@object_type != "LG") AND (@object_type != "AP")
	AND (@object_type != "PR") AND (@object_type != "DF"))
BEGIN
	/*
	** 18256, "%1! is not a valid object type for this stored procedure."
	*/
        raiserror 18256, @object_type
        return (1)
END

/* In case of a stored proc, if the object still exits, get obj id */
IF (@object_type = "PR")
BEGIN

	/* get owner id from scope param */
	IF not exists (select uid from sysusers
			where (name = @scope))
	BEGIN
		/*
		** 18552 "%1! is not a valid user of this database."
		*/
		raiserror 18552, @scope
		return(1)
	END
	ELSE
		select @owner_id = (select uid from sysusers
					where (name = @scope))

	IF exists (select id from sysobjects
			where ((name = @object_name) AND (uid = @owner_id)))
		select @sp_objid = (select id from sysobjects
			where ((name = @object_name) AND (uid = @owner_id)))
END


/* Now convert user name to user id */
IF (@object_type = "LG")
BEGIN
	IF not exists(select suid from master..syslogins 
			where (name = @object_name))
	BEGIN
		/*
		** 18259, "No login with specified name '%1!' exists." 
		*/
	        raiserror 18259, @object_name
		return(1)
	END

	select @user_id = 
		(select suid from master..syslogins 
			where (name = @object_name))
END
ELSE IF ((@object_type = "AP") and (@scope is not NULL))
BEGIN
	IF not exists(select suid from master..syslogins where (name = @scope))
	BEGIN
		/*
		** 18259, "No login with specified name '%1!' exists" 
		*/
	        raiserror 18259, @scope
		return(1)
	END

	select @user_id = (select suid from master..syslogins 
				where (name = @scope))
END

/* 
** Now delete the matching entry from Sysattributes Table...
** Verify that the attributes passed to sysattributes is correct. Note
** that for stored procedures, the sysattributes table in the current
** database is searched. For other objects, the sysattributes table in
** master is searched.
*/
IF (@object_type = "LG")
BEGIN

		select @classname = char_value

			 from
			master..sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object = @user_id AND
			object_cinfo = @scope

		IF (@classname is not NULL)
		BEGIN

			delete master..sysattributes
				where	class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object = @user_id AND
				object_cinfo = @scope
		END
		ELSE
		BEGIN
			/*
			** 18279, "The specified binding to be dropped does 
			**	   not exist"
			*/
			raiserror 18279
			return(1)
		END

		IF attrib_notify(6, @attrib_id, @object_type, @user_id,
			NULL, NULL, NULL, @scope, NULL, NULL,
			NULL, NULL, "", @action) = 0
		BEGIN
			insert master..sysattributes
				(class, attribute, object_type, object, 
				object_info3, object_cinfo, char_value)
				values(6, @attrib_id, @object_type,@user_id,
				@instanceid, 
				@scope, @classname)

			/*
			** 18278,"Failed to unbind '%1!' from execution class.
			**	  Check server errorlog for any additional
			**	  information."
			*/
	        	raiserror 18278, @object_name
			return(1)
		END
END
ELSE IF (@object_type = "AP")
BEGIN
		select @classname = char_value, 
			@instanceid=object_info3 from
			master..sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object_info1 = @user_id AND
			object_cinfo = @object_name

		IF (@classname is not NULL)
		BEGIN

			delete master..sysattributes
				where	class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @user_id AND
				object_cinfo = @object_name
		END
		ELSE
		BEGIN
			/*
			** 18279, "The specified binding to be dropped does 
			**	   not exist"
			*/
			raiserror 18279
			return(1)
		END

		IF attrib_notify(6, @attrib_id, @object_type, NULL,
			@user_id, NULL, NULL, @object_name, NULL, NULL,
			NULL, NULL, "", @action) = 0
		BEGIN
			insert master..sysattributes
				(class, attribute, object_type, object_info1, 
				object_info3, object_cinfo, char_value)
				values(6, @attrib_id, @object_type, @user_id, 
				@instanceid, @object_name, @classname)
			/*
			** 18278,"Failed to unbind '%1!' from execution class.
			**	  Check server errorlog for any additional
			**	  information."
			*/
        	raiserror 18278, @object_name
			return(1)
		END
END
ELSE IF (@object_type = "DF")
BEGIN
	select @classname = char_value ,
		@instanceid=object_info3 from
		master..sysattributes where
		class = 6 AND
		attribute = @attrib_id AND
		object_type = @object_type

	IF (@classname is not NULL)
	BEGIN

		delete master..sysattributes
			where   class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type
	END
	ELSE
	BEGIN
		/*
		** 18279, "The specified binding to be dropped does
		**         not exist"
		*/
		raiserror 18279
		return(1)
	END

	IF attrib_notify(6, @attrib_id, @object_type, NULL,
		NULL, NULL, NULL, NULL, NULL, @classname,
		NULL, NULL, "", @action) = 0
	BEGIN
		insert master..sysattributes
			(class, attribute, object_type, object_info3, char_value)
			values(6, @attrib_id, @object_type, @instanceid, @classname)
	END
END
ELSE 	/* object is of type "PR" */
BEGIN
		select @classname = (select char_value from sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object_info1 = @owner_id AND
			object_cinfo = @object_name),
		       @stored_objid = (select object from sysattributes where
			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object_info1 = @owner_id AND
			object_cinfo = @object_name),
		       @instanceid = (select object_info3 from sysattributes where

			class = 6 AND
			attribute = @attrib_id AND
			object_type = @object_type AND
			object_info1 = @owner_id AND
			object_cinfo = @object_name)

		IF (@classname != NULL)
		BEGIN

			delete sysattributes
				where	class = 6 AND
				attribute = @attrib_id AND
				object_type = @object_type AND
				object_info1 = @owner_id AND
				object_cinfo = @object_name
		END
		ELSE
		BEGIN
			/*
			** 18279, "The specified binding to be dropped does 
			**	   not exist"
			*/
			raiserror 18279
			return (1)
		END

		IF attrib_notify(6, @attrib_id, @object_type, @sp_objid,
			NULL, NULL, NULL, @object_name, NULL, NULL,
			NULL, NULL, "", @action) = 0
		BEGIN
			insert sysattributes
				(class, attribute, object_type, object,
				object_info1, object_info3,
				object_cinfo, char_value)
				values(6, @attrib_id, @object_type, 
				@stored_objid, @owner_id, @instanceid,
				@object_name, @classname)

			/*
			** 18278,"Failed to unbind '%1!' from execution class.
			**	  Check server errorlog for any additional
			**	  information."
			*/
			raiserror 18278, @object_name
			return(1)
		END
END

return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_activeroles')
begin
	drop procedure sp_activeroles
end
go
print "Installing sp_activeroles"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	5.0	1.0	01/28/97	sproc/src/activeroles */

/*
** Messages for "sp_activeroles"	18341
** 18341, "An invalid argument was entered. Usage: sp_activeroles [expand_down]"
*/ 

create procedure sp_activeroles
@mode		varchar(30) = NULL	/* "expand_down" only */

as

declare @hier_level	int	
declare @udr_class	int	    	/* value of UDR_CLASS in sysattributes */
declare @udr_role_hier	int	    	/* value of attribute in sysattributes
					** for rows corresponding to role 
					** hierarchy
					*/		
declare	@msg		varchar(255) 	/* message holder */
declare @rolelist	varchar(255)	/* list of roles from show_role() */
declare @maxsysrolenum	int

select @maxsysrolenum = 31

/* 
** A @@trancount of 0 indicates no current transaction.
*/
if @@trancount = 0
begin
	/* In chained mode, SQL Server implicitly executes a "begin 
	** transaction" before the following statements: delete, fetch,
	** insert, open, select, and update.
	*/
	set chained off
end

/* Exclusive lock on objects being changed, held until transaction ends. No
** shared locks
*/
set transaction isolation level 1

/* Initialize variables */
select @udr_class = class 
from master.dbo.sysattributes 
where object_type = "UR"
 
select @udr_role_hier = 2

/* Convert arg to lower case with no leading/trailing blanks. */
if @mode is not NULL
begin
	select @mode = lower(ltrim(rtrim(@mode)))

	if (@mode != "expand_down")
	begin
		/* 18341, "An invalid argument was entered. 
		** 	   Usage: sp_activeroles [expand_down]." 
		*/
		raiserror 18341
		return (1)
	end	
end
			
select @hier_level = 1

/* create a temporary table to hold the intermediate result of expansion */

create table #intermediate_roleset
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

/* create another temporary table to hold another result of expansion */

create table #tmp_roleset
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

/* select all rolenames from syssrvroles for this user and
** insert the ones for which charindex(r.name, show_role())
** returns > 0 into #intermediate_roleset.  This gives the
** active system roles without using a call to proc_role().
*/
select @rolelist = show_role()

insert into #intermediate_roleset(rolename, role_level)
	select r.name, @hier_level 
	from master.dbo.sysloginroles l, 
		master.dbo.syssrvroles r
	where l.srid = r.srid
		and l.suid = suser_id()
		and charindex(r.name, @rolelist) > 0

/* Get the user-defined roles for this user.  We will need to
** call proc_role() on these.
*/
insert into #tmp_roleset(rolename, role_level)
	select r.name, @hier_level
	from master.dbo.sysloginroles l,
		master.dbo.syssrvroles r
	where l.srid = r.srid
		and l.suid = suser_id()
		and r.srid > @maxsysrolenum

/* Call proc_role() on the user-defined roles to see which
** are active, and insert them into the intermediate table.
*/
insert into #intermediate_roleset(rolename, role_level)
	select rolename, role_level from #tmp_roleset t
	where proc_role(t.rolename) = 1

if @mode is NULL
begin
	/* display the rows from #intermediate_roleset and return */
	
	select "Role Name" = rolename
	from #intermediate_roleset

	return (0)
end

/* create two more temp tables, #cumulative_role_set and #temp_role_set */
create table #cumulative_role_set
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

create table #temp_role_set
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

/* 
** For the while loop below,
**	the start condition is:
**		#cumulative_role_set contains nothing
**		#intermediate_roleset contains the base set of roles
**		#temp_roleset contains nothing
*/

while exists (select * from #intermediate_roleset)
begin 
	select @hier_level = @hier_level + 1

	/* insert into #temp_role_set(role_level, select role1, role2 
	** from sysattributes where row is of type 'role1 contains 
	** role2' and role1 is in #intermediate_roleset)
	*/

	insert into #temp_role_set(rolename, parentrolename, role_level)
		select role_name(object_info1), rolename, @hier_level  
		from master.dbo.sysattributes, #intermediate_roleset
		where object = role_id(rolename)
			and class = @udr_class 
			and attribute = @udr_role_hier 

	/* copy all rows from #intermediate_roleset into #cumulative_role_set*/
	insert into #cumulative_role_set
		select * 
		from #intermediate_roleset
	where rolename not in (select rolename from #cumulative_role_set)
                or parentrolename not in (select parentrolename 
					from #cumulative_role_set
					where parentrolename is not null)

	/* delete all rows from #intermediate_roleset */
	delete from #intermediate_roleset

	/* copy all rows from #temp_role_set into #intermediate_roleset */ 
	insert into #intermediate_roleset
		select * 
		from #temp_role_set

	/* delete all rows from #temp_roleset */
	delete from #temp_role_set
end

/* select all rows from #cumulative_role_set and display it */

select distinct "Role Name" = rolename, "Parent Role Name" = parentrolename, 
		"Level" = role_level 
from #cumulative_role_set
order by role_level

return (0)

go
exec sp_procxmode 'sp_activeroles', 'anymode'
go
grant execute on sp_activeroles to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_displayroles')
begin
	drop procedure sp_displayroles
end
go
print "Installing sp_displayroles"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	5.0	1.0	06/10/96	sproc/src/displayroles */

/*
** Messages for "sp_displayroles"	18342
** 18342, "Invalid name '%1!'. This role or user does not exist in this SQL
**	  Server."
** 18343, "Invalid mode '%1!'. Mode should either be 'expand_up' or 
**	  'expand_down'."
** 18344, "The user name '%1!' should correspond to the current user or you 
**	  must possess System Security Officer (SSO) authorization to execute 
**	  '%2!' for another user."
** 18674, "Cannot display role information for a login name."
** 18675, "Password expiration interval: %1!"
** 18676, "Password Expired: %1!"
** 18677, "Minimum Password Length: %1!"
** 18678, "Maximum failed logins: %1!"
** 18679, "Current failed login attempts: %1!"
*/ 

create procedure sp_displayroles
@name		varchar(30) = NULL,	/* role name or login name */
@mode 		varchar(30) = NULL	/* "expand_up" or "expand_down" */

as

declare @grantee	varchar(30)	/* grantee name */
declare @loginame	varchar(30) 	/* login name */
declare @hier_level	int	
declare @udr_class	int	    	/* UDR_CLASS value in sysattributes */
declare @udr_role_hier	int	    	/* value of attribute in sysattributes
					** for rows corresponding to role 
					** hierarchy
					*/		
declare	@msg		varchar(1024) 	/* message holder */
declare @pwdate	datetime	/* last passwd set date */
declare @passwdexp   	int		/* value of passwd expiration */
declare @minpwdlen	int		/* value of minimum passwd 
					** length
					*/
declare @pwdexpired	varchar(3)	/* has the login's password 
					** expired?
					*/
declare @maxfailedlogins int		/* value of max failed logins */
declare @currentfails   int		/* number of current failed 
					** logins
					*/
declare @srid		int		/* srid of the grantee */
declare @passeclass 	int		/* class number of PASSWD_SECURITY
					** class in sysattributes
					*/
declare @local_msgbuf	char(30)	/* message holder */

/* 
** A @@trancount of 0 indicates no current transaction.
*/
if @@trancount = 0
begin
	/* In chained mode, SQL Server implicitly executes a "begin 
	** transaction" before the following statements: delete, fetch,
	** insert, open, select, and update.
	*/
	set chained off
end

/* Exclusive lock on objects being changed, held until transaction ends. No
** shared locks
*/
set transaction isolation level 1

select @udr_class = class 
from master.dbo.sysattributes 
where object_type = "UR"

 
select @udr_role_hier = 2

/* Convert the first and last args to lower case with no leading/trailing
** blanks.
*/
if @mode is not NULL
	select @mode = lower(ltrim(rtrim(@mode)))

if @name is NULL
begin
	select @name = suser_name()
	select @loginame = @name
	select @grantee = @name
end
else
begin
	/* check if name is a valid loginname */
	if exists (select name from master.dbo.syslogins 
			where name = @name)
	begin
		if (@mode = "display_info")
		begin
			/*
			** 18674, "Cannot display role information
			** for a login name."
			*/
			raiserror 18674
			return (1)
		end
		else
		begin
			select @grantee = @name
			select @loginame = @name
		end

	end
	else 
	begin
		if exists (select * from master.dbo.syssrvroles 
				where name = @name)
		begin
			select @grantee = @name
			select @loginame = NULL
		end
		else
		begin
			/* 18342, "Invalid name '%1!'. This role or user does 
			** not exist in this SQL Server."  
			*/ 
			raiserror 18342, @name
			return (1)
		end
	end
end

if @mode is NULL
	select @mode = "direct"
		
/* verify mode is set to "expand_up" or "expand_down" or "display_info" */
else if (@mode != "expand_down" and @mode != "expand_up" and 
		@mode != "display_info")
begin
	/* 18343, "Invalid mode '%1!'. Mode should either be 'expand_up'
	** or 'expand_down' or 'display_info'."
	*/
	raiserror 18343, @mode
	return(1)
end

/* Display role related info, that is requested & exit */
if (@mode = "display_info")
begin
	/* NOTE: For all the password control related 
	** information printed below, a check is first 
	** made if the specified role has a value 
	** for the attribute in sysattribute. If there
	** is no configured value, then the systemwide
	** default is picked up from sysconfigures
	*/
	select @srid = srid from master.dbo.syssrvroles
		where name = @grantee

	/* Print the role name */
	print "Role name : %1!", @grantee
	
	/* Date of last password change */
	select @pwdate = pwdate from master.dbo.syssrvroles
		where name = @grantee
	print "Date of Last Password change : %1!", @pwdate

	/* set the value of PASSWD_SECURITY class 
	*/
	select @passeclass = class from master.dbo.sysattributes where 
	object_type = "PS"

	/* Password expiration interval */
	select @passwdexp = int_value
	from master.dbo.sysattributes
	where class = @passeclass AND 
		attribute = 0 AND 
		object = @srid AND object_cinfo = "role"

	if (@passwdexp is NULL)
	begin
		select @passwdexp = value
		from master.dbo.sysconfigures
		where name = "systemwide password expiration"
	end

	/*
	** 18675, "Password expiration interval: %1!"
	*/
	exec sp_getmessage 18675, @msg output
	select @local_msgbuf = convert (char(10), @passwdexp)
	print @msg, @local_msgbuf


	/* Has the role's password expired?? */
	if (@passwdexp = 0)
	begin
		select @pwdexpired = "NO"
	end
	else 
		if ( datediff(dd, @pwdate, getdate()) > @passwdexp)
			select @pwdexpired = "YES"
		else
			select @pwdexpired = "NO"

	/*
	** 18676, "Password Expired: %1!"
	*/
	exec sp_getmessage 18676, @msg output
	select @local_msgbuf = upper(@pwdexpired)
	print @msg, @local_msgbuf

	/* Minimum password length */
	select @minpwdlen = int_value 
	from master.dbo.sysattributes
	where class = @passeclass AND
		attribute = 1 AND
		object = @srid AND object_cinfo = "role"

	if (@minpwdlen is NULL)
	begin
		select @minpwdlen = value 
		from master.dbo.sysconfigures
		where name = "minimum password length"
	end

	/*
	** 18677, "Minimum Password Length: %1!"
	*/
	exec sp_getmessage 18677, @msg output
	select @local_msgbuf = convert (char(10), @minpwdlen)
	print @msg, @local_msgbuf


	/* Maximum failed logins */
	select @maxfailedlogins = int_value 
	from master.dbo.sysattributes
	where class = @passeclass AND 
		attribute = 2  AND object = @srid
		AND object_cinfo = "role" 

	if (@maxfailedlogins is NULL)
	begin
		select @maxfailedlogins = value 
		from master.dbo.sysconfigures
		where name = "maximum failed logins"
	end

	/*
	** 18678, "Maximum failed logins: %1!"
	*/
	exec sp_getmessage 18678, @msg output
	select @local_msgbuf = convert (char(10), @maxfailedlogins)
	print @msg, @local_msgbuf

	/* Current failed logins count */
	select @currentfails = logincount 
	from master.dbo.syssrvroles
	where srid = @srid
	
	/*
	** 18679, "Current failed login attempts: %1!"
	*/
	exec sp_getmessage 18679, @msg output
	select @local_msgbuf = convert (char(10), @currentfails)
	print @msg, @local_msgbuf

	return (0)
end
else
if (@mode = "expand_up")
	select @hier_level = 0
else
	select @hier_level = 1

/* create a temporary table to hold the intermediate result of expansion */

create table #intermediate_roleset
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

if (@grantee = @loginame)
begin
	/* grantee is a login */
	if (@name != suser_name())
	begin
		/* make sure that the login has SSO role enabled */
		if (charindex("sso_role",show_role()) = 0)
		begin
			/* 18344, "The user name '%1!' should correspond to 
			** the current user or you must possess System 
			** Security Officer (SSO) authorization to execute 
			** '%2!' for another user." 
			*/
			raiserror 18344, @name, "sp_displayroles" 
			return (1)
		end
	end

	/* select all names from syssrvroles for this user and
	** insert into #intermediate_roleset
	*/
	insert into #intermediate_roleset(rolename, role_level)
		select r.name, @hier_level 
		from master.dbo.sysloginroles l, 
			master.dbo.syssrvroles r
		where l.srid = r.srid
			and l.suid = suser_id(@grantee)
end

else
begin
	/* It is for a role. */

	if (@mode != "expand_up") 
	begin	
		/* select all rolenames from sysattributes
		** which are directly contained by this role and insert into 
		** #intermediate_roleset 
		*/
	
		insert into #intermediate_roleset(rolename, parentrolename, 
							role_level)
			select role_name(object_info1), @grantee, @hier_level 
			from master.dbo.sysattributes
			where object = role_id(@grantee)
				and class = @udr_class 
				and attribute = @udr_role_hier 
	end

	else
	begin
		/* select all rolenames from sysattributes
		** which are parents of this role and insert into
		** #intermediate_roleset
		*/
		insert into #intermediate_roleset(rolename, parentrolename, 
							role_level)
			select @grantee, role_name(object), @hier_level
			from master.dbo.sysattributes
			where object_info1 = role_id(@grantee)
				and class = @udr_class
				and attribute = @udr_role_hier

	end
end

/* If mode is 'direct' then display only directly granted roles to 
** role_name that was specified.
*/
if (@mode = "direct")
begin
	/* display the rows from #intermediate_roleset and return */
	
	select "Role Name" = rolename
	from #intermediate_roleset

	return(0)
end

/* create two more temp tables, #cumulative_role_set and #temp_role_set */

create table #cumulative_role_set
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

create table #temp_role_set
	(rolename	varchar(30) not null,
	 parentrolename varchar(30) null,
	 role_level	smallint null)

/* 
** For the while loop below,
**	the start condition is:
**		#cumulative_role_set contains nothing
**		#intermediate_roleset contains the base set of roles
**		#temp_roleset contains nothing
*/

while exists (select * from #intermediate_roleset)
begin 
	if (@mode = "expand_down")
	begin
		select @hier_level = @hier_level + 1

		/* insert into #temp_role_set(role_level, select role1, role2 
		** from sysattributes where row is of type 'role1 contains 
		** role2' and role1 is in #intermediate_roleset)
		*/

		insert into #temp_role_set(rolename, parentrolename, role_level)
			select role_name(object_info1), rolename, @hier_level  
			from master.dbo.sysattributes, #intermediate_roleset
			where object = role_id(rolename)
				and class = @udr_class 
				and attribute = @udr_role_hier 
	end

	else
	begin
		select @hier_level = @hier_level - 1

		/* insert into #temp_role_set(role_level, select role1, role2
		** from sysattributes where row is of type 'role1 is contained
		** by role2' and role1 is in #intermediate_roleset)
		*/

		insert into #temp_role_set(rolename, parentrolename, role_level)
			select parentrolename, role_name(object), @hier_level
			from master.dbo.sysattributes, #intermediate_roleset
			where object_info1 = role_id(parentrolename)
				and class = @udr_class
				and attribute = @udr_role_hier
	end


	/* copy all rows from #intermediate_roleset into #cumulative_role_set */
	insert into #cumulative_role_set
		select * 
		from #intermediate_roleset
	where rolename not in (select rolename from #cumulative_role_set)
                or parentrolename not in (select parentrolename 
					from #cumulative_role_set
					where parentrolename is not null)

	/* delete all rows from #intermediate_roleset */
	delete from #intermediate_roleset

	/* copy all rows from #temp_role_set into #intermediate_roleset */
	insert into #intermediate_roleset
		select * 
		from #temp_role_set

	/* delete all rows from #temp_roleset */
	delete from #temp_role_set
end

/* select all rows from #cumulative_role_set and display it */

select distinct "Role Name" = rolename, "Parent Role Name" = parentrolename, 
		"Level" = role_level 
from #cumulative_role_set
order by role_level

return(0)
go
exec sp_procxmode 'sp_displayroles', 'anymode'
go
grant execute on sp_displayroles to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_validateconfigname')
begin
	drop procedure sp_validateconfigname
end
go
print "Installing sp_validateconfigname"
go


/*
** Messages for "sp_validateconfigname"
**
** 17410, "Configuration option doesn't exist.
**
** 17411, "Configuration option is not unique."
**
*/

/*
** Syntax:
**
** sp_validateconfigname "configname", [confignum , fullconfigname]
**
** This stored procedure validates a config parameter name. The name
** supplied is checked if it is a valid config parameter name.
**
** Parameters:
**	configname     - full/partial config parameter name.
**	confignum      - optional output parameter. The config num of
**			 the config parameter if input config name is
**			 valid.
**	fullconfigname - optional output parameter. Full config name 
**			 as the input may have been partial.
** Returns:
**	1 - if invalid or non-unique config parameter.
**	0 - if valid parameter.
*/

create procedure sp_validateconfigname
@configname	 varchar(255),
@confignum	 int = 0 output,
@fullconfigname	 varchar(255) = NULL output
as

declare @msg			varchar(1024)
declare @configcount	int
declare @configcount2	int

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_validateconfigname"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* we don't want too much of output */
set nocount on

/*
** Note that we don't want to select config variables related to
** cache manager. This is done by checking for 'parent'. Cache
** manager config variables are handled separately by the cache
** manager stored procedures.
*/
select  @configcount = count(*)
	from master.dbo.sysconfigures
	where name like "%" + @configname + "%"
	      and parent != 19


/* Check if there is duplicate row for the current instance */
select @configcount2 = count(*) 
	from master.dbo.sysconfigures 
	where name like "%" + @configname + "%" 
		and parent != 19


/*
** If more than one option like @configname, show the 
** duplicates and return.
*/
if @configcount > 1 or @configcount2 > 1
begin
	/*
	** 17411, "Configuration option is not unique."
	*/
	exec sp_getmessage 17411, @msg output
	print @msg

	select option_name = convert(char(30), name),
		config_value = convert(char(11), space(11-char_length(
		isnull(a.value2, convert(char(32), a.value)))) +
		isnull(a.value2, convert(char(32), a.value))),
		run_value = convert(char(11), space(11-char_length(
		isnull(b.value2, convert(char(32), b.value)))) +

		isnull(b.value2, convert(char(32), b.value)))


	from master.dbo.sysconfigures a,
		master.dbo.syscurconfigs b
	where
		a.config *= b.config
		and name like "%" + @configname + "%"
		and parent != 19
		and a.config != 19

	 
	return (1)
end
else
begin
	/*
	** Check if user-supplied config option is valid.
	*/
	if @configcount = 0
	begin
		/*
		** 17410, "Configuration option doesn't exist.
		*/
		exec sp_getmessage 17410, @msg output
		print @msg
		return (1)
	end
end

/*
** Get the config number.
*/
select  @confignum = config,
	@fullconfigname = name
	from  master.dbo.sysconfigures
	where name like "%" + @configname + "%"
	and parent != 19
	and config != 19


return (0)
go
exec sp_procxmode 'sp_validateconfigname', 'anymode'
go
grant execute on sp_validateconfigname to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_countmetadata')
begin
	drop procedure sp_countmetadata
end
go
print "Installing sp_countmetadata"
go


/*
** Messages for "sp_countmetadata"
**
** 17260, "Can't run %1! from within a transaction."
**
** 18280, "There are %1! user objects in %2! database(s), requiring %3!
**	  Kbytes of memory. The 'open objects' configuration parameter is 
**	  currently set to %4!."
**
** 18281, "There are %1! user indexes in %2! database(s), requiring %3! 
**	  Kbytes of memory. The 'open indexes' configuration parameter is
**	  currently set to %4!."
**
** 18282, "There are %1! databases, requiring %2! Kbytes of memory. The 
**	  'open databases' configuration parameter is currently set to %3!."
**
** 18283, "Configuration parameter '%1!' is not supported in this system
**	  stored procedure."
**
** 19343, "There are %1! user partitions in %2! database(s), requiring %3! 
**	  Kbytes of memory. The 'open partitions' configuration parameter is
**	  currently set to %4!."
**
** 19451, "Metadata counts in database '%1!' are:"
**
** 19452, "Metadata counts in all databases are:"
*/

/*
** Syntax:
**
** sp_countmetadata configname [, database_name]
**
** This stored procedure supports  some of the  configuration parameters
** from the Meta-Data Cache Group of configuration parameters. A config
** parameter in this config group is typically associated with a metadata
** element. For example, "open objects" is associated with sysobjects rows
** as an 'open object' caches sysobjects rows. Hence, it would be good to
** know how many sysobjects  rows are there  in a database or server-wide.
**
** This procedure provides the count of a metadata element like sysobjects
** rows in a database or server-wide and provides information on memory
** requirement to cache all of them and the current configuration. For each
** config parameter, we have a minimum value and a maximum value. If the 
** number of metadata elements falls out of the min/max bound, we obtain
** the memory required for the minimum value or maximum value.
**
** Parameters: 
**	configname    - full/partial name of the configuration parameter.
**			"all" may be specified to get counts for all supported
**			configuration parameters
**	database_name - optional, if supplied, count is from this database.
**			else, count is sum of counts from all databases.
**			This parameter is ignored if configname parameter
**			is 'open databases'. 
**
** Returns:
**	1 - if error.
**	0 - if no error.
*/

create procedure sp_countmetadata
@configname	varchar(255),
@dbname		varchar(255) = NULL
as

declare	@configvalue		int
declare	@minimum_value		int
declare	@maximum_value		int
declare	@confignum		int
declare	@return_value		int
declare	@metadata_count		int
declare	@memory_required	int
declare	@fullconfigname		varchar(255)
declare	@msg			varchar(1024)
declare @max_rid		int
declare @item_id		int
declare @msg_number		int

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_countmetadata"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1
set nocount on

/* Must have sa_role as this stored procedure is related to config */
if (proc_role("sa_role") < 1)
	return (1)

/* 
** create temporary table to store the results to be printed. The rid column
** is used to iterate through the table while calculating the memory_required
** for each of the configuration parameters in the table. This is required as
** direct insert or update into a temporary table using value returned by 
** config_admin is causing error 3917. Th rid column is 4 digit to accomodate
** current and possibly future additions to the number of configuration 
** parameters this sproc can support.
*/

create table #metadata_result_tbl(
			rid		numeric(4, 0) identity,
			confignum	int,
			metadata_count	int NULL, 
			configvalue	int NULL,
			min_value	int NULL,
			max_value	int NULL,
			fullconfigname	varchar(255) NULL,
			memory_required int NULL,
			dbname		varchar(255) NULL)
			
/* if @configname = "all" don't validate */
if @configname = "all"
begin
	/*
	** fill the result table with required information from syscurconfigs
	** and sysconfigures for the config options that this stored procedure
	** supports, i.e the list of confignums in 'in' clause below, this list 
	** should be consistent with the confignums it checks after validation.
	*/

	insert #metadata_result_tbl(confignum, fullconfigname, configvalue, 
			min_value, max_value, dbname)
		select b.config, b.name, a.value, 
			minimum_value, maximum_value, 
			case b.config
				when 105 then 'master'
				else @dbname
			end
		from master.dbo.syscurconfigs a,
			master.dbo.sysconfigures b
		where b.config in (105, 107, 263, 408) 
			and a.config = b.config
end
else
begin
	/*
	** Only one configuration parameter is expected.
	** Validate the configname and get the corresponding config number,
	** and the full name of the config option for printing messages. 
	*/
	exec @return_value = sp_validateconfigname @configname, 
							@confignum output,
					   		@fullconfigname output
	if @return_value != 0
		return @return_value

	/* 
	** This stored procedure supports only a few config parameters. Check 
	** if the user supplied config parameter is one of them. For now we
	** support 'number of open databases', 'number of open objects' and
	** 'number of open indexes', 'number of open partitions'.
	*/
	if ((@confignum != 105) and (@confignum != 107) and (@confignum != 263)
	    and (@confignum != 408))
	begin
		/*
		** 18283, "Configuration parameter '%1!' is not supported in 
		**	   this system stored procedure."
		*/
		raiserror 18283, @fullconfigname
		return(1)
	end
	insert #metadata_result_tbl(confignum, fullconfigname, configvalue, 
			min_value, max_value, dbname)
		select b.config, b.name, a.value, 
			minimum_value, maximum_value, 
			case @confignum
				when 105 then 'master'
				else @dbname
			end
		from master.dbo.syscurconfigs a,
			master.dbo.sysconfigures b
		where b.config = @confignum 
			and a.config = b.config
	
end

/* find metadata counts */

update #metadata_result_tbl 
	set metadata_count = count_metadata(confignum, dbname)
/*
** A meaningful error message would have been printed in the builtin.
*/
if @@error != 0
begin
	return (1)
end

/*
** find memory required. We need to iterate through the whole table updating
** memory_required column for each row. If we try updating directly into table
** the values returned by config_admin(), it raises error 3917.
*/

select @item_id = min(rid),
	@max_rid = max(rid) from #metadata_result_tbl

while @item_id <= @max_rid
begin
	/* set to NULL for validation */
	select @confignum = NULL

	select @confignum = confignum,
		@minimum_value = min_value,
		@maximum_value = max_value,
		@metadata_count = metadata_count
	from #metadata_result_tbl
	where rid = @item_id
	
	/* 
	** check if the rid corresponding to @item_id exists in table. We are 
	** using identity column which may have gaps in it.
	**/
	if @confignum is not NULL
	begin
		select @memory_required = 
		    case
		    	when @metadata_count < @minimum_value then 
						config_admin(16, @confignum,
							@minimum_value, 0, NULL, 
							NULL)
						
			when @metadata_count > @maximum_value then
						config_admin(16, @confignum,
							@maximum_value, 0, NULL, 
							NULL)
						
			else			config_admin(16, @confignum,
							@metadata_count, 0, NULL, 
							NULL)
		    end /* case */
		    /* 
		    ** in case of error built in would have printed error 
		    ** message.
		    */
		    if @memory_required = 0
		    begin
		    	return (1)
		    end
	end
	update #metadata_result_tbl
		set memory_required = @memory_required
		where confignum = @confignum

	select @item_id = @item_id + 1
end

/* print the results */
if @configname = "all"
begin
	 select @msg_number = 
		case 
			when @dbname is null then 19452
			else 19451 
		end
	exec sp_getmessage @msg_number, @msg output
	print @msg, @dbname
	select convert(varchar(40), fullconfigname) "option name",
		metadata_count "metadata count",
		configvalue "config value",
		memory_required "memory required"
	from #metadata_result_tbl

	return (0)
end

/* if @dbname was not specified, results pertain to all databases */
if @dbname is NULL
begin
	select @dbname = "all"
end

/* print result only for specified config parameter. i.e. @configname != 'all' */
select @metadata_count = metadata_count,
	@configvalue = configvalue,
	@memory_required = memory_required 
from #metadata_result_tbl

if @confignum = 105
begin
	/*
	** 18282, "There are %1! databases, requiring %2! Kbytes of memory.
	**	   The 'open databases' configuration parameter is currently 
	**	   set to %3!."
	*/
	exec sp_getmessage 18282, @msg output
	print @msg, @metadata_count, @memory_required, @configvalue
end
else
if @confignum = 107
begin
	/*
	** 18280, "There are %1! user objects in %2! database(s), requiring 
	**	   %3! Kbytes of memory. The 'open objects' configuration 
	**	   parameter is currently set to %4!."
	*/
	exec sp_getmessage 18280, @msg output
	print @msg, @metadata_count, @dbname, @memory_required, @configvalue
end
else if @confignum = 263
begin
	/*
	** 18281, "There are %1! user indexes in %2! database(s), requiring 
	**	   %3! Kbytes of memory. The 'open indexes' configuration 
	**	   parameter is currently set to %4!."
	*/
	exec sp_getmessage 18281, @msg output
	print @msg, @metadata_count, @dbname, @memory_required, @configvalue
end
else
begin
	/*
	** 19343, "There are %1! user partitions in %2! database(s), requiring 
	**	   %3! Kbytes of memory. The 'open partitions' configuration 
	**	   parameter is currently set to %4!."
	*/
	exec sp_getmessage 19343, @msg output
	print @msg, @metadata_count, @dbname, @memory_required, @configvalue
end

return (0)
go
exec sp_procxmode 'sp_countmetadata', 'anymode'
go
grant execute on sp_countmetadata to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitorconfig')
begin
	drop procedure sp_monitorconfig
end
go
print "Installing sp_monitorconfig"
go

/*
** Messages for "sp_monitorconfig"
**
** 17260, "Can't run %1! from within a transaction."
**
** 18283, "Configuration parameter '%1!' is not supported in this system
**	  stored procedure."
**
** 18292, "An internal error occurred while accessing
**        monitor information."
**
** 17977, "'%1!' does not exist."
*/

/*
** Syntax:
**
** sp_monitorconfig "configname" [, "result_tbl_name"] [, "full"] or
** sp_monitorconfig "all" [, "result_tbl_name"] [, "full"] 
**
** This stored procedure provides statistics/monitor related information
** on a configuration parameter. This data could be extracted from
** monitor counters or from other places where statistics are maintained.
**
** For example, if the config name is 'open objects', then the monitor 
** information is number of open objects, number of them free, percentage 
** of open objects currently being used, etc. The actual information may be 
** printed in stored procedure(s) invoked from here. Other config parameters 
** can be added here.
**
** Note: The server collects these resource stats by default, however,
** you can turn off the activity by boot the server with trace flag 3631.
**
** Design:
** 1. There are two temporary table created in this stored procedure:
**
** -- #resource_monitor_tbl is used for setting up the resource
**	to be monitored. It has 7 columns:
**
**	create table #resource_monitor_tbl(id int, confignum int,
**					   	counter1 varchar(40) NULL,
**					   	counter2 varchar(40) NULL,
**					   	counter3 varchar(40) NULL,
**					  	counter4 varchar(40) NULL,
**					 	is_perprocess int,
**						multiplier int)
**
**		o id		-- a unique numbering of the resource
**				   to be monitored
**		o confignum	-- the configure number of the resource
**				   to be added
**		o counter1	-- the first monitor counter to be
**				   retrieved, usually it is the current
**				   active value. 
**		o counter2	-- the second monitor counter to be retrieved,
**				   usually it is the high watermark value.
**		o counter3	-- the third monitor counter to be retrieved,
**				   usually it is reused count.
**		o counter4	-- the fourth monitor counter to be retrieved,
**				   it is reserved for future use, not used now.
**		o is_perprocess	-- it designate whether the configure
**				   parameter is related to number of pss or
**				   worker process:
**				   Value 0 - means it is not a per
**					     process value.
**				   Value 1 - means it is a per process value.
**				   value 2 - means it is a per worker
**				  	     process value. 
**		o multiplier	-- used to calculate the max value of a
**				   certain parameter.
**
** -- #resource_result_tbl is used to store the monitoring
**	results for each resource whose monitoring information being
**	collected, and output them once all the collections are done.
**	It has 9 columns. Each is self explanatory by its name. 
**
**	create table #resource_result_tbl(Name varchar(25),
**						Config_val int,
**						System_val int,
**						Total_val int,
**						Num_free int,
**						Num_active int, 
**						Pct_act char(6),
**						Max_Used int, 
**						Reuse_cnt int)
**
**
** To add a new monitoring resource, you only need to insert a new row
** into #resource_monitor_tbl, indicating the configure number
** of the resource, the monitor counter you try to retrieve and whether
** it is a per process value.
**
**
** Note, if you want to save the result into your own specified table,
** provide the table name as the second parameter of this stored procedure. 
** The table if exists should be in the following format:
**
**		create table table_name(
**				Name varchar(35),
**				Config_val int, System_val int,
**				Total_val int, Num_free int,
**				Num_active int, Pct_act char(6),
**				Max_Used int, Reuse_cnt int,
**				Date varchar(30), Instance_Name varchar(30) NULL)
**
** This table is a bit different from #resource_result_tbl. Note the
** Name field is 10 bytes wider.If the table specified as second parameter 
** doesn't exist it will be created with same format as above. You may specify
** fully qualified table name if you want to save the information in a table
** in database other than current one.
**
** 2. API for getting monitoring stats:
** --  config_admin() is used to get monitoring stats from the server.
**     Following values are passed into this API to indicate the specific
**     info we are trying to gather:
**		o cmd 		- Set to be 22 (CFG_RESOURCEMONITOR_VALUE) 
**				  indicating we are gathering statistics.
**		o value1	- Set to the @confignum of the resource
**				  we are interested in.
**		o value2	- Set to one of following values:
**				  1 - gathering adjusment value 
**				  2 - gathering the active value
**				  3 - gathering the HWM value
**				  4 - gathering the reused value
**		o value3	- not used
**		o value4	- Set to the monitor counter name of
**				  the resource we are gathing, if 
**				  we get the stats from monitor counters
** 
** If you are adding a new resource to be monitored, you need to add the
** memory pool name used by this resource(if there is one) in 
** function cfg__resmonitor_value() of utils/cfg_mgr.c to calculate the
** actual value, max value and the adjustable value. 
**
**
** Parameters (for the stored procedure):
**	configname - configuration parameter name.
**	result_tbl_name - Optional, the name for a table where to store 
**			  the results. If the table already exists it should 
**			  be in specified format. If the table does not exist
** 			  it will be created in specified format and result 
** 			  will be inserted into this table. It could be
**			  in the format owner.tablename with 2 * 255 + 1
**			  length.	
**	option -	print option. Default is NULL. If the value is 'full'
**			the columns Config_val, System_val and Total_val are
**			added to the output.
**
** Result output:
**	If result_tbl_name is not provided, the result will be printed on
**	standard output. 
**	If result_tbl_name is provided, the result will be inserted into
**	the table with result_tbl_name and will not be printed on standard
**	output.
**
** Returns:
**	1 - if error.
**	0 - if no error.
**
*/
create procedure sp_monitorconfig
(@configname	varchar(255),
 @result_tbl_name varchar(511) = NULL,
 @option	varchar(5) = NULL)
as

declare	@confignum	int
declare	@return_value	int
declare	@fullconfigname	varchar(255)

declare @config_runval  int
declare @temp_var2      int
declare @perct_active   float
declare @num_active     int
declare @max_active     int
declare @reuse_reqs     int
declare @num_free       int
declare @msg            varchar(1024)
declare @curdate        varchar(30)
declare @counter        int
declare @total_item     int
declare @item_id        int
declare @syst_value	int
declare @num_wkpss	int
declare @num_pss	int
declare @perprocess	int
declare @insert_add_tbl	int
declare @procval	int

declare @reuse_str      varchar(10)
declare @cmd_str	varchar(700)	/*
					** this string is used for sql
					** commands for creating and inserting
					** into @result_tbl_name
					** the size of cmd_str should be
					** atleast size of @result_tbl_name
					** additional space for remaining
					** parts of the sql command strings
					*/
declare @num_free_str   varchar(10)
declare @num_active_str varchar(10)
declare @per_active_str varchar(10)
declare @max_used_str   varchar(7)

declare @counter1       varchar(40)
declare @counter2       varchar(40)
declare @counter3       varchar(40)
declare @counter4       varchar(40)

declare @multiplier	int
declare @user_conn	int
declare @online_engines int
declare @max_value	int
declare @tot_value	int
declare @mode		int
declare @whoami		varchar(30)	/* stores name of this proc */
declare @rtnstatus 	int
declare @monprocname	varchar(255)

select @whoami = object_name(@@procid, db_id('sybsystemprocs'))

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_monitorconfig"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* we don't want too much of output */
set nocount on

select @monprocname = 'sybsystemprocs.dbo.sp_monitor_check_permission'

exec @rtnstatus = @monprocname @whoami

if (@rtnstatus = 1)
        return(1)

/* Validate config name */
if @configname != "all"
begin
	/*
	** Validate the configname and get the corresponding config number,
	** and the full name of the config option for printing messages.
	*/
	exec @return_value = sp_validateconfigname @configname,
						   @confignum output,
						   @fullconfigname output
	if @return_value != 0
		return @return_value

end

if (lower(@option) = "full")
begin
	select @mode = 1
end
else
begin
	select @mode = 0
end

/*
** Create the control table to hold all the info about the
** resource we want to monitor.
*/
create table #resource_monitor_tbl(id int, confignum int,
					   counter1 varchar(40) NULL,
					   counter2 varchar(40) NULL,
					   counter3 varchar(40) NULL,
					   counter4 varchar(40) NULL,
					   is_perprocess int,
					   multiplier int)

/*
** Get the run value of number of user connections and
** number of online engines.
*/
select @user_conn = value
from   master.dbo.syscurconfigs
where  config = 103


select @online_engines = value
from   master.dbo.syscurconfigs
where  config = 126


/* -----------------------------------------------------------
** Now insert all the information about the resource that we
** would like to retrieve their monitoring information. 
*/
/* number of open databases */
insert into #resource_monitor_tbl 
	values(1, 105, null, null, "open_database_reuse_requests", null, 0, 1)

/* number of open objects */
insert into #resource_monitor_tbl 
	values(2, 107, null, null, "open_object_reuse_requests", null, 0, 1)

/* procedure cache size */
insert into #resource_monitor_tbl 
	values(3, 146, "active_procedure_cache", "hwm_procedure_cache", 
	       "procedure_cache_reuse_requests", null, 0, 1)

/* number of open indexes */
insert into #resource_monitor_tbl 
	values(4, 263, null, null, "open_index_reuse_requests", null, 0, 1)

/* number of aux scan descriptors */
insert into #resource_monitor_tbl 
	values(5, 266, null, null, null, null, 0, 1)

/* number of large i/o buffers */
insert into #resource_monitor_tbl
        values(6, 301, "active_dskbufs", "hwm_dskbufs", null, null, 0, 1)

/* txn to pss ratio */
insert into #resource_monitor_tbl 
	values(7, 185, null, null, null, null, 1, @user_conn)

/* number of dtx participants */
insert into #resource_monitor_tbl 
	values(8, 347, null, null, "dtxp_reuse_reqs", null, 0, 1)

/* number of user connections */
insert into #resource_monitor_tbl
        values(9, 103, "active_connections", "hwm_connections", null, null, 0, 1)

/* number of worker processes */
insert into #resource_monitor_tbl
        values(10, 267, "active_worker_process", "hwm_worker_process",
               null, null, 0, 1)

/* partition groups */
insert into #resource_monitor_tbl
        values(11, 242, null, null, null, null, 0, 1)

/* number of devices */
insert into #resource_monitor_tbl
        values(12, 116, "active_devices", "hwm_devices", null, null, 0, 1)

/* size of global fixed heap */
insert into #resource_monitor_tbl
        values(13, 355, null, null, null, null, 0, 1)

/* size of process object heap */
insert into #resource_monitor_tbl
        values(14, 340, null, null, null, null, 0, 1)

/* size of shared class heap */
insert into #resource_monitor_tbl
        values(15, 341, null, null, null, null, 0, 1)

/* size of unilib cache */
insert into #resource_monitor_tbl
        values(16, 331, null, null, null, null, 0, 1)

/* number of java sockets */
insert into #resource_monitor_tbl
        values(17, 395, null, null, null, null, 0, 1)

/* number of remote connections */
insert into #resource_monitor_tbl
        values(18, 120, "active_remote_connections", "hwm_remote_connections",
               null, null, 0, 1)

/* number of remote logins */
insert into #resource_monitor_tbl
        values(19, 118, "active_remote_logins", "hwm_remote_logins",
               null, null, 0, 1)

/* number of remote sites */
insert into #resource_monitor_tbl
        values(20, 119, "active_remote_sites", "hwm_remote_sites",
               null, null, 0, 1)

/* audit queue size */
insert into #resource_monitor_tbl
        values(21, 136, null, null, null, null, 0, 1)

/* permission cache entries */
insert into #resource_monitor_tbl
        values(22, 186, "active_perm_cache_entries", "hwm_perm_cache_entries",
		"perm_cache_entries_reuse_requests", null, 1, 1)

/* additional network memory */
insert into #resource_monitor_tbl
         values(23, 137, null, null, null, null, 0, 1)

/* number of mailboxes */
insert into #resource_monitor_tbl
        values(24, 171, null, null, null, null, 0, 1)

/* number of messages */
insert into #resource_monitor_tbl
        values(25, 172, null, null, null, null, 0, 1)

/* number of sort buffers */
insert into #resource_monitor_tbl
        values(26, 181, "active_sort_buffers", "hwm_sort_buffers",
		null, null, 0, 1)

/* heap memory per user */
insert into #resource_monitor_tbl
        values(27, 399, null, null, "heap_mem_waits",
		 null, 1, 1)

/* max memory. */
insert into #resource_monitor_tbl
        values(28, 396, "hwm_maxmem", "hwm_maxmem", null, null, 0, 1)

/* number of locks */
insert into #resource_monitor_tbl
        values(29, 106, null, null, null, null, 0, 1)

/* number of alarms */
insert into #resource_monitor_tbl
        values(30, 173, null, null, null, null, 0, 1)

/* max cis remote connections */
insert into #resource_monitor_tbl
	values(31, 277, null, null, null, null, 0, 1)

/* memory per worker process */
insert into #resource_monitor_tbl
	values(32, 268, null, null, null, null, 2, 1)

/* max online engines */
insert into #resource_monitor_tbl
        values(33, 126, "active_online_engines", "hwm_online_engines",
	       null, null, 0, 1)

/* max number network listeners */
insert into #resource_monitor_tbl
        values(34, 156, "active_network_listeners", "hwm_network_listeners",
	       null, null, 0, 1)

/* disk i/o structures */
insert into #resource_monitor_tbl
        values(35, 150, null, null, null, null, 0, 1)

/* number of open partitions */
insert into #resource_monitor_tbl 
	values(36, 408, null, null, "open_partition_reuse_requests", null,
	       0, 1)

/* CIPC regular message pool size */
if (@@clustermode = "shared disk cluster")
insert into #resource_monitor_tbl
	values(37, 481, null, null, null, null,
		0, 1)

/* CIPC large message pool size */
if (@@clustermode = "shared disk cluster")
insert into #resource_monitor_tbl
	values(38, 465, null, null, null, null,
		0, 1)



/* ------------------------end of insertion------------------------ */


/*
** Check whether the specified configure parameter is in the control
** table(resource_monitor_tbl)
*/
if (@configname != "all")
begin

	if not exists (select id
			from #resource_monitor_tbl
			where (confignum = @confignum))
	begin
        	raiserror 18283, @fullconfigname
		return (1)
	end
end

/* Create a temp table #resource_result_tbl to store all the result. */
create table #resource_result_tbl(Name varchar(25),
					Config_val int, System_val int,
					Total_val int, Num_free int,
					Num_active int, Pct_act char(6),
					Max_Used int, Reuse_cnt int,
					Instance_Name varchar(30) NULL)
select @insert_add_tbl = 0
if (@result_tbl_name is not NULL)
begin
	if (object_id(@result_tbl_name) is NULL)
	begin
		/* 
		** since table doesn't exist create it
		** if creation is successful, set @insert_add_tbl to 1
		** otherwise  keep it to @insert_add_tbl = 0
		*/

		select @cmd_str = "create table " 
					+ @result_tbl_name 
					+ "("
					+ "Name varchar(35),"
					+ "Config_val int,"
					+ "System_val int,"
					+ "Total_val int,"
					+ "Num_free int,"
					+ "Num_active int,"
					+ "Pct_act char(6),"
					+ "Max_Used int,"
					+ "Reuse_cnt int,"
					+ "Date varchar(30),"
					+ "Instance_Name varchar(30) NULL)"
					
		exec @return_value = sp_exec_SQL @cmd_str, @whoami
		if (@return_value != 0)
		begin
			return (1)
		end
		select @insert_add_tbl = 1
	end
	else
	begin
		select @insert_add_tbl = 1 
	end
end

/* Check how many items we need to retrieve */
if (@configname = "all")
begin
	select @item_id = 1
	    , @total_item = count(*) from #resource_monitor_tbl
end
else
begin
	select @total_item = 1
	    , @item_id = id from #resource_monitor_tbl
			where (confignum = @confignum)
end

select @counter = 1

/*
** Now loop through the monitoring list to get information for
** each monitoring items.
*/
while (@counter <= @total_item)
begin
	/* Get configure parameter info from the control table. */
	select @confignum = confignum, @counter1 = counter1,
	       @counter2 = counter2, @counter3 = counter3, 
	       @counter4 = counter4, @perprocess = is_perprocess,
	       @multiplier = multiplier
	from #resource_monitor_tbl
	where (id = @item_id)

	/*
	** Get the run value for the config variable
	*/
	select @config_runval = value 
	from   master.dbo.syscurconfigs
	where  config = @confignum


	/* 
	** Retrieve info for the 4 counters. Pass flag 2 as the third
	** parameter of config_admin() to get the active value
	*/
	select @num_active = config_admin(22, @confignum, 2, 0, @counter1, NULL)

	/*
	** Pass flag 3 as the third parameter of config_admin() to get
	** the max value. 
	*/
	select @max_active = config_admin(22, @confignum, 3, 0, @counter2, NULL)

	/*
	** Pass flag 4 as the third parameter of config_admin() to get
	** reused value
	*/
	if (@counter3 is not NULL)
	begin
		select @reuse_reqs = config_admin(22, @confignum, 4, 0, @counter3, NULL)
	end
	else
	begin
		select @reuse_reqs = 0
	end


	/* 
	** Check the return results: null is unexpected for these
	** values. We will tolerate these errors by resetting
	** the values to some appropriate numbers and continuing 
	** collecting other stats. 
	*/
	if ((@num_active is null) or (@max_active is null) or 
	    (@reuse_reqs is null)) 
	begin
		/*
		** 18292, "An internal error occurred while accessing
		**	  monitor information." 
		*/
		raiserror 18292
		select @num_active = 0
		    , @max_active = 0
		    , @reuse_reqs = -1
	end

	/*
	** If the return value of @num_active and @max_active is negative,
	** reset them to 0 and continue.
	*/
	if (@num_active < 0)
	begin
		select @num_active = 0
	end
	if (@max_active < 0)
	begin
		select @max_active = 0
	end	
	
	/* Get the configure parameter's name. */
	if (@fullconfigname is NULL)
		select @fullconfigname = name from master..sysconfigures
		where config = @confignum


	/* 
	** The adjustment value is the size of the resource-pool when the
	** actual configured value for the parameter is set to 0.
	** Pass flag 1 as the third parameter of config_admin() to get
	** the adjustment value. 
	*/
	select @syst_value = config_admin(22, @confignum, 1, 0, NULL, NULL)

	/* 
	** Per pss resource, such as "heap memory per user" and 
	** "permission cache entries" needs to be divided by
	** number of psses.
	*/
	if (@perprocess = 1)
	begin
		/* Get cfgpss. */
		select @num_pss = config_admin(22, 190, 0, 0, NULL, NULL)
		
		select @num_active = @num_active / @num_pss
		    , @max_active = @max_active / @num_pss
		select @reuse_reqs = @reuse_reqs / @num_pss
	end

	/* Per worker process resource, such as "memory per worker process" */
	if (@perprocess = 2)
	begin
		/* Get worker processes. */
		select @num_wkpss = value 
		from   master.dbo.syscurconfigs
		where  config = 267


		if (@num_wkpss != 0)
		begin
			select @num_active = @num_active / @num_wkpss
			    , @max_active = @max_active / @num_wkpss
		end
		else
		begin
			select @num_active = 0
			    , @max_active = 0
		end
	end

	/*
	** Convert in 2k pagesize value the configure parameters
	** 'size of global fixed heap' and 'size of shared class heap'
	** because they are measured in bytes. Note that the configure
	** parameter 'size of process object heap' must not be converted
	** here because it is measured in 2k pagesize value already.
	*/ 
	if (@confignum = 355 or @confignum = 341)
	begin
		select @num_active = (@num_active + 2047) / 2048
		    , @max_active = (@max_active + 2047) / 2048
	end


	/*
	** Depending on the type of parameter we need to take
	** the multiplier to correctly calculate the max possible
	** value. Some config options are per user connection
	** or per engine.
	*/
	if (@config_runval = 0 and @syst_value = 0)
	begin
		/*
		** As there're no resources available, it's
		** not possible to show any active numbers.
		*/
		select @tot_value = 0
		    , @perct_active = 0
		    , @num_active = 0
		    , @num_free = 0
		    , @max_active = 0
		    , @reuse_reqs = 0
	end
	else
	begin
		/*
		** As we don't use synchronization methods for
		** monitor counters, it's possible some numbers
		** are off. We adjust when necessary.
		*/
		if (@num_active > @max_active)
		begin
			select @num_active = @max_active
		end

		/*
		** Are we using a pool configured by the user
		** or a pool allocated by the server ? We first
		** test the config value as this takes precedence
		** over the adjust value.
		*/
		if (@config_runval != 0)
		begin
			select @tot_value = @config_runval

			/*
			** When we have a config value
			** the adjustment value for
			** max cis remote connections
			** should revert back to 0.
			*/
			if (@confignum = 277)
			begin
				select @syst_value = 0
			end
		end
		else
		begin
			select @tot_value = @syst_value
		end

		select @max_value = @multiplier * @tot_value

		/*
		** First check if the @num_active is bigger then
		** the @max_value. This is possible if
		** the config value is set to a number smaller
		** then to what's currently being used.
		*/
		if (@num_active > @max_value)
		begin
			select @max_value = @num_active

			/*
			** We need to adjust total also
			** to prevent from having wrong
			** numbers later on. As we don't
			** know the previous config/system
			** value we make total equal to
			** @max_value (i.e. @num_active).
			*/
			if (@multiplier > 0)
			begin
				select @tot_value =
					@max_value / @multiplier
			end
		end

		/*
		** Percentage of resources in active state.
		*/
		if (@multiplier > 0)
		begin
			select @perct_active = (@num_active * 100.0) /
					@max_value
		end
		else
		begin
			select @perct_active = 0
		end

        	/*
        	** Number of free resources
        	*/
        	select @num_free = @max_value - @num_active
	end

	/*
	** Insert the results into the result table only if table name is not
	** provided. 
	*/
	if (@insert_add_tbl = 0)
	begin
		insert into #resource_result_tbl values(
			convert(char(30), @fullconfigname), 
			@config_runval,
			@syst_value,
			@tot_value,
			@num_free, 
			@num_active,
			convert(char(6),
				(rtrim(str(@perct_active, 6, 2)))), 
			@max_active,
			@reuse_reqs,
			@@instancename)
	end
	else
	begin
		select @curdate = convert(varchar, getdate())

		/*
		** Insert the results into user supplied table if
		** the table name is provided.
		*/
                select @cmd_str = "insert into " + @result_tbl_name
				+ "(Name, Config_val, System_val, Total_val, "
				+ "Num_free, Num_active, Pct_act, Max_Used, "
				+ "Reuse_cnt, Date, Instance_Name)"
				+ " values('"
                                + convert(varchar(35), @fullconfigname)
                                + "',"
                                + convert(varchar(11), @config_runval)
                                + ","
                                + convert(varchar(11), @syst_value)
                                + ","
                                + convert(varchar(11), @tot_value)
                                + ","
                                + convert(varchar(11), @num_free)
                                + ","
                                + convert(varchar(11), @num_active)
                                + ", '"
                                + convert(varchar(6),
					 (rtrim(str(@perct_active, 6, 2))))
                                + "',"
                                + convert(varchar(11),@max_active)
                                + ", "
                                + convert(varchar(11), @reuse_reqs)
                                + ", '"
				+ convert(varchar(30), @curdate)
                                + "' ,'" 
				+ @@instancename
				+ "')"

		exec @return_value = sp_exec_SQL @cmd_str, @whoami
		if (@return_value != 0)
		begin
			return (1)
		end
	end

	/* Get to next item if there are any. */
	if (@configname = "all")
	begin
		select @item_id = @item_id + 1
	end

	select @fullconfigname = NULL
	    , @reuse_reqs = NULL
	    , @num_active = NULL
	    , @max_active = NULL 
	    , @counter = @counter + 1

end

/*
** Send the result to standard output only if the results are not
** already inserted into a user supplied table.
*/
if (@insert_add_tbl != 1)
begin
	/*
	** 18284, "Usage information at date and time: %1!"
	*/
	exec sp_getmessage 18284, @msg output
	select @curdate = convert(varchar, getdate())

	/* print usage date and time */
	print @msg, @curdate
	print ""
	
	if (@mode = 1)
	begin
		select
			Name,
			Config_val "Configure Value",
			System_val "System Value",
			Total_val "Run Value",
			Num_free,
			Num_active,
			Pct_act,
			Max_Used,
			Reuse_cnt,
			Instance_Name
		from #resource_result_tbl
		order by Name
	end
	else
	begin
		select
			Name,
			Num_free,
			Num_active,
			Pct_act,
			Max_Used,
			Reuse_cnt,
			Instance_Name
		from #resource_result_tbl 
		order by Name 

	end
end

return (0)
go
exec sp_procxmode 'sp_monitorconfig', 'anymode'
go
grant execute on sp_monitorconfig to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpconfig')
begin
	drop procedure sp_helpconfig
end
go
print "Installing sp_helpconfig"
go


/*
** Messages for "sp_helpconfig"
**
** 17260, "Can't run %1! from within a transaction."
**
** 18283, "Configuration parameter '%1!' is not supported in this
**	  system stored procedure, or the usage is incorrect. Please refer
**	  to System Administration Guide for help."
**
** 18395, "Configuration parameter, '%1!', will consume %2!K of memory if
**        configured at %3!.
**
** 18396, "Configuration parameter, '%1!', can be configured to %2! to
**        fit in %3! of memory.
**
** 18397, "Changing the value of '%1!' does not increase the amount of memory
**        SQL Server uses.
**
** 18401, "Configuration parameter, 'max memory', will need to be set to 
**        %1! (%2!K) in order for 'total data cache size' to have a value of 
**        %3!K.
**
** 18403, "Configuration parameter, 'max memory', will need to be set to
**	  %1! (%2!K) in order for the procedure cache to have a value of %3!.
**
** 18521, "Omni services must be enabled and loaded in order to perform
**	  memory calculations."
**
** 18916, "Changing the value of '%1!' to '%2!' increases the amount of
** 	  memory ASE uses by %3! K.
**
** 18917, "Changing the value of '%1!' to '%2!' reduces the amount of
** 	  memory ASE uses by %3! K. The reduced memory could be reused
**	  when this configure value changes, but will not be released
**	  until ASE restarts."
**
*/

/*
** Syntax:
**
** sp_helpconfig "configname", "size"
**
** This stored procedure provides help information for a config parameter.
** The help information provided is specific to a config parameter.
**
** Parameters:
**	configname	- full/partial name of the config parameter.
**			  special: if configname is "static options",
**                        "dynamic options" or "read-only options" we will 
**                        list all config parameters of that type.
**	size		- for parameters which use memory, this is the size 
**			  of either the proposed config value, or the size 
**			  of memory.  If either, K, M, or G are used, it is
**			  interpreted that size is a memory value and 
**			  a message will be printed that explains how many
**			  of configname will fit in size.
**			  if only a number is used, then a message will be
**			  printed that will explain how much memory will be
**			  consumed by size number of confignames.
**
** Returns:
**	1 - if error.
**	0 - if no error.
*/


create procedure sp_helpconfig
@configname	varchar(80),
@size		varchar(30) = NULL
as

declare	@confignum	int
declare	@return_value	int
declare	@message_num	int
declare	@memory_size	int
declare	@status		int
declare	@datatype	int
declare	@value		int
declare	@dir		int
declare @pages		int
declare @msg		varchar(1024)
declare	@fullconfigname	varchar(80)
declare @size_len	int
declare @count		int
declare @found_memory	int
declare @unit_size	char(1)
declare @logical_memory	int      /* current total logical memory */
declare @additional_memory int   /* increase in logical memory due to change*/

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_helpconfig"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/* we don't want too much of output */
set nocount on

/*
** Check if configname is one of 'static options', 'dynamic options', 
** 'read-only options' or 'cluster options'
*/
if (@configname in ('static options','dynamic options','read-only options', 'cluster options'))
begin
	if @@system_view = 'INSTANCE'
	begin
		select 	distinct Config_Name = name,
			Config_Value = convert(char(32), space(11-char_length(
			isnull(a.value2, convert(char(32), a.value)))) +
			isnull(a.value2, convert(char(32), a.value))),
			Run_Value = convert(char(11), space(11-char_length(
			isnull(b.value2, convert(char(32), b.value)))) +
			isnull(b.value2, convert(char(32), b.value))),
			Unit =  b.unit

		into #sphelpconfig1rs
		from master.dbo.sysconfigures a, master.dbo.syscurconfigs b
		where
			a.config = b.config

			and a.parent != 19
			and a.config != 19
			and b.type like "%" + substring(@configname,1,char_length(@configname)-8) + "%"

		exec sp_autoformat @fulltabname = #sphelpconfig1rs,
		@selectlist = "'Config Name'=Config_Name,'Config Value'=Config_Value,'Run Value'=Run_Value,'Unit'=Unit,'Instance Name'=Instance_Name",
		@orderby = "order by lower(Config_Name)"
		drop table #sphelpconfig1rs
		return (0)
	end
	else
	begin
		select  distinct Config_Name = name,
			Config_Value = convert(char(32), space(11-char_length(
			isnull(a.value2, convert(char(32), a.value)))) +
			isnull(a.value2, convert(char(32), a.value))),
			Run_Value = convert(char(11), space(11-char_length(
			isnull(b.value2, convert(char(32), b.value)))) +
			isnull(b.value2, convert(char(32), b.value))),
			Unit =  b.unit


		into #sphelpconfig3rs
		from master.dbo.sysconfigures a, master.dbo.syscurconfigs b
		where
			a.config = b.config
			and a.parent != 19
			and a.config != 19

			and b.type like "%" + substring(@configname,1,char_length(@configname)-8) + "%"


		exec sp_autoformat @fulltabname = #sphelpconfig3rs,
		@selectlist = "'Config Name'=Config_Name,'Config Value'=Config_Value,'Run Value'=Run_Value,'Unit'=Unit", 
		@orderby = "order by lower(Config_Name)"

		drop table #sphelpconfig3rs
		return (0)
	end
end

/*
** Validate the configname and get the corresponding config number,
** and the full name of the config option for printing messages.
*/
exec @return_value = sp_validateconfigname @configname,
			@confignum output, @fullconfigname output
if @return_value != 0
	return @return_value

/*
** Retrieve some info from syscurconfigs
*/
select	@message_num = message_num, 
	@status = status,
	@datatype = datatype
from master..syscurconfigs where config = @confignum

/* Localization? */
select @msg = description from master.dbo.sysmessages
                                    where error = @message_num

print ""
print @msg
print ""

/* If the config option is a string valued option, return */
if (@datatype = 5)
	return(0)

select	Minimum_Value = minimum_value,
	Maximum_Value = maximum_value,
	Default_Value = convert(int, defvalue),
	Current_Value = value,
	Memory_Used = convert(char(11), space(11-char_length(
                                        convert(varchar(11), comment)))+
                                        convert(varchar(11), comment)),
	Unit = unit,

	Type = type

into #sphelpconfig2rs
from master..syscurconfigs where config = @confignum
exec sp_autoformat @fulltabname = #sphelpconfig2rs,

	@selectlist = "'Minimum Value'=Minimum_Value, 'Maximum Value'=Maximum_Value, 'Default Value'=Default_Value,'Current Value'=Current_Value,'Memory Used'=Memory_Used,'Unit'=Unit,'Type'=Type"

drop table #sphelpconfig2rs
print ""

/* Done if the second parameter was not passed into the sproc */
if (@size is NULL)
	return(0)

/*
** If this config parameter uses memory and a second param was passed in
** then additional processing is needed.
**
** 	If the second param is of type '%d [k | K | m | M]', then user supplied
** 	a memory value, and is asking for how many of a particular parameter
**	will fit in that memory value.
**
**	If the second param is of type '%d', then user supplied a config value
**	and is asking for how much memory value will use.
**
*/

/* Chech to see if the parameter uses memory by looking for the correct bit */
select @status = @status & 64

if (@status != 64)
begin
	/*
	** 18397, Changing the value of '%1!' does not increase the amount 
	** of memory SQL Server uses.
	*/
	exec sp_getmessage 18397, @msg output
	print @msg,  @fullconfigname
	return(0)
end

/*
** Check if the second parameter contains non integer character(s).
*/
select @size_len = char_length(@size)
select @count = 1
select @found_memory = 0
while (@count <= @size_len) and
	(@found_memory = 0)
begin
	select @unit_size = substring(@size, @count, 1)
	if (@unit_size not like "[0-9]")
	begin
		if (@count != 1) or (@unit_size != "-")
		begin
			select @found_memory = 1
		end
	end 
	select @count = @count + 1
end

if (@found_memory = 1)
begin
	/*
	** second parameter is a memory size.
	**
	** sp_aux_getsize returns the memory size in terms of KB.
	** Note that negitive size will be caught by sp_aux_getsize
	*/
	exec @return_value = sp_aux_getsize @size, @value output

	/*
	** check if input had an error, if so return. Message was
	** printed in sp_aux_getsize.
	*/
	if @return_value = 0
		return (1)

	select @dir = 1
end
else
begin
	/*
	** second parameter is a value
	*/
	select @value = convert(int, @size)

	select @dir = 0
end

/*
** Validate the directions ( 0 or 1 ) based on applicability to
** a configuration parameter.
**
** For 'total datacache size (132) we will estimate the total logical memory
** given X mount of datacache in unit sizes (K, M etc). ( dir = 1) 
**
** For procedure cache size (146) we will estimate the total logical memory
** given X number of procedure cache size in pages. ( dir = 0)
**
** Given a stacksize, we will compute the memory consumed. But the stack size
** can be given in terms of K ( assumed )
**
*/
if @dir = 0 
begin
	if @confignum in (132, 104)
	begin
		/*
		** 18283, "Configuration parameter '%1!' is not supported in
		**	   this system stored procedure, or the usage is
		**	   incorrect. Please refer to System Administration
		**	   Guide for help"
		*/
		raiserror 18283, @fullconfigname
		return (1)
	end
end

if @dir = 1
begin
	if @confignum in (146, 134, 212, 104)
	begin
		/*
		** 18283, "Configuration parameter '%1!' is not supported in
		**	   this system stored procedure, or the usage is
		**	   incorrect. Please refer to System Administration
		**	   Guide for help"
		*/
		raiserror 18283, @fullconfigname
		return (1)
	end
end
		
select @return_value = config_admin(16, @confignum, @value, @dir, 
				NULL, NULL)

/*
** Return if error occurred in config_admin.
*/
if (@return_value = 0)
begin
	if @confignum = 278
	begin
		/*
		** 18521, "Omni services must be enabled and loaded
		** in order to perform memory calculations."
		*/
		raiserror 18521
	end

	return(1)
end

/*
** special messages for the following configuration parameters:
**	'total data cache size' (config number 132)
**	'procedure cache size' (config number 146)
*/
if (@confignum = 132 and @dir = 1)
begin
	/*
	** 18401, Configuration parameter, 'max memory', will need to
	** be set to %1! (%2!K) in order for 'total data cache size'
	** to have a value of %3!.
	*/
	exec sp_getmessage 18401, @msg output
	select @pages = @return_value / 2
	print @msg, @pages, @return_value, @size
	return (0)
end

if @dir = 0
begin
	if @confignum = 146
	begin
		/*
		** 18403, Configuration parameter, 'max memory', will 
		** need to be set to %1! (%2!K) in order for the procedure 
		** cache to have a value of %3!.
		*/
		exec sp_getmessage 18403, @msg output
		select @pages = @return_value / 2
		print @msg, @pages, @return_value, @size
	end
	else 
	begin
		/*
		** 18395, Configuration parameter, '%1!', will consume %2!K 
		** of memory if configured at %3!.
		*/
		exec sp_getmessage 18395, @msg output
		print @msg,  @fullconfigname, @return_value, @size
	end

	/*
	** Calculate increase in 'total logical memory' 
	*/
	select 	@additional_memory = (config_admin(21, @confignum, @value, 
					0, NULL, NULL) - b.value) * 2
	from 	master.dbo.sysconfigures a,
		master.dbo.syscurconfigs b
	where 	a.name = 'total logical memory'
	and	a.config = b.config

	if ( @additional_memory > 0 ) 
	begin
		/*
		** 18916, Changing the value of '%1!' to '%2!' increases 
		** the amount of memory ASE uses by %3! K.
		*/
		exec sp_getmessage 18916, @msg output
		print @msg,  @fullconfigname, @size, @additional_memory
	end
	else if ( @additional_memory < 0 ) 
	begin
		/*
		** 18917, Changing the value of '%1!' to '%2!' reduces 
		** the amount of memory ASE uses by %3! K.
		*/
		select @additional_memory = @additional_memory * -1 
		exec sp_getmessage 18917, @msg output
		print @msg,  @fullconfigname, @size, @additional_memory
	end
	else
	begin
		/*
		** 18397, Changing the value of '%1!' does not increase 
		** the amount of memory SQL Server uses.
		*/
		exec sp_getmessage 18397, @msg output
		print @msg,  @fullconfigname
	end
	return (0)
end
else
begin
	/*
	** 18396, Configuration parameter, '%1!', can be configured 
	** to %2! to fit in %3! of memory.
	*/
	exec sp_getmessage 18396, @msg output
	print @msg,  @fullconfigname, @return_value, @size
	return (0)
end

go
exec sp_procxmode 'sp_helpconfig', 'anymode'
go
grant execute on sp_helpconfig to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_mdcache')
begin
	drop procedure sp_sysmon_mdcache
end
go
print "Installing sp_sysmon_mdcache"
go

/* This stored procedure produces a report containing a summary of
** SQL Server engine activity.
*/
create procedure sp_sysmon_mdcache
	@NumElapsedMs int,	/* for "per Elapsed second" calculations */
	@NumXacts int,		/* for per transactions calculations */
	@Reco char(1)		/* Flag for recommendations             */
as

/* --------- declare local variables --------- */
declare @tmp_int int		   /* temp var for integer storage */
declare @sum1line char(80)	   /* string to delimit total lines without 
				   ** percent calc on printout */	
declare @blankline char(1)	   /* to print blank line */
declare @psign char(3)		   /* hold a percent sign (%) for print out */
declare @na_str char(3)		   /* holds 'n/a' for 'not applicable' strings */
declare @rptline char(80)	   /* formatted stats line for print statement */
declare @spinlock_contention float /* holds the current spinlock contention being
				   ** processed. 
				   */
declare @desmgr_contention float   /* holds the object manager spinlock contention */
declare @des_contention float 	   /* holds the open object spinlock contention */
declare @ides_contention float 	   /* holds the open index spinlock contention */
declare @hash_contention float 	   /* holds the open index chain spinlock contention */
declare @section char(80)	   /* string to delimit sections on printout */
declare @ides_hash_contention int /* holds the open index chain spinlock contention */
declare @pdes_contention int  /* holds the open partition spinlock contention */
declare @pdes_hash_contention int /* holds the open partition chain spinlock contention */

/* ------------- Variables for Tuning Recommendations ------------*/
declare @recotxt char(80)
declare @recoline char(80)
declare @reco_hdr_prn bit
declare @tmp_int1 int
declare @tmp_int2 int
declare @ret_status int
declare @tmp_db_reuse_requests int
declare @tmp_obj_reuse_failed int
declare @tmp_ind_reuse_failed int
declare @tmp_ptn_reuse_failed int
declare @tmp_db_reuse_failed int
declare @tmp_int_open_object int
declare @tmp_int_open_index int
declare @tmp_int_open_ptn int
declare @tmp_int_dbtables int
/* --------- Setup Environment --------- */
set nocount on			/* disable row counts being sent to client */

select @sum1line   = "  -------------------------  ------------  ------------  ----------  ----------"
select @blankline  = " "
select @psign      = " %%"		/* extra % symbol because '%' is escape char in print statement */
select @na_str     = "n/a"
select @section = "==============================================================================="

/* Create a temp table to store the result from sp_monitorconfig. */
create table #tmp_res_monitor(Name varchar(35),
			      Config_val int, System_val int,
			      Total_val int, Num_free int,
			      Num_active int, Pct_act char(6),
			      Max_Used int, Reuse_cnt int,
			      Date varchar(30), Instance_Name varchar(30) NULL)

/* Get information of "number of open objects". */
execute @ret_status = sp_monitorconfig "number of open objects", "#tmp_res_monitor"

if (@ret_status != 0)
begin
        print @blankline
        return 0
end

print @section
print @blankline

print "Metadata Cache Management"
print "-------------------------"
print @blankline


print "  Metadata Cache Summary         per sec      per xact       count  %% of total"
print @sum1line
print @blankline


/* ----------------- number of open objects ------------ */
select @rptline = "  Open Object Usage"
print @rptline

if (@@clustermode = "shared disk cluster")
begin
	select @tmp_int2 = Num_active, @tmp_int = Max_Used, 
   		@tmp_int_open_object = Num_free
  		from #tmp_res_monitor
  		where Name = 'number of open objects' and
		      Instance_Name = @@instancename
end
else
begin
	select @tmp_int2 = Num_active, @tmp_int = Max_Used, 
   		@tmp_int_open_object = Num_free
  		from #tmp_res_monitor
  		where Name = 'number of open objects'
end
select @rptline = "    Active" + space(28) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int2 , 10) + space(7) +
			@na_str
print @rptline

select @rptline = "    Max Ever Used Since Boot" + space(10) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @rptline = "    Free" + space(30) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int_open_object, 10) + space(7) +
			@na_str
print @rptline

select @rptline="    Reuse Requests"
print @rptline

/*
** The information for reuse/reuse fail is still stored in monitor
** counters in resource_stats group. 
*/
select @tmp_int1 = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_object_reuse_requests"

select @rptline = "      Succeeded" + space(23) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int1, 10) + space(7) +
			@na_str
print @rptline

select @tmp_obj_reuse_failed = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_object_reuse_fail"

select @rptline = "      Failed" + space(26) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_obj_reuse_failed, 10) + space(7) +
			+ @na_str
print @rptline
print @blankline


/* ----------------- number of open indexes ------------ */
execute @ret_status = sp_monitorconfig "number of open indexes", "#tmp_res_monitor"

if (@ret_status != 0)
begin
        print @blankline
        return 0
end

select @rptline = "  Open Index Usage"
print @rptline

if (@@clustermode = "shared disk cluster")
begin
	select @tmp_int2 = Num_active, @tmp_int = Max_Used, 
		@tmp_int_open_index = Num_free
		from #tmp_res_monitor
		where Name = 'number of open indexes' and
			Instance_Name = @@instancename
end
else
begin
	select @tmp_int2 = Num_active, @tmp_int = Max_Used, 
		@tmp_int_open_index = Num_free
		from #tmp_res_monitor
		where Name = 'number of open indexes'
end
select @rptline = "    Active" + space(28) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int2 , 10) + space(7) +
			@na_str
print @rptline

select @rptline = "    Max Ever Used Since Boot" + space(10) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @rptline = "    Free" + space(30) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int_open_index, 10) + space(7) +
			@na_str
print @rptline

select @rptline="    Reuse Requests"
print @rptline

/*
** The information for reuse/reuse fail is still stored in monitor
** counters in resource_stats group. 
*/
select @tmp_int1 = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_index_reuse_requests"

select @rptline = "      Succeeded" + space(23) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int1, 10) + space(7) +
			@na_str
print @rptline

select @tmp_ind_reuse_failed = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_index_reuse_fail"

select @rptline = "      Failed" + space(26) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_ind_reuse_failed , 10) + space(7) +
			@na_str
print @rptline
print @blankline

/* ----------------- number of open partitions ------------ */
execute @ret_status = sp_monitorconfig "number of open partitions", "#tmp_res_monitor"

if (@ret_status != 0)
begin
        return 0
end

select @rptline = "  Open Partition Usage"
print @rptline

if (@@clustermode = "shared disk cluster")
begin
	select @tmp_int2 = Num_active, @tmp_int = Max_Used, 
		@tmp_int_open_ptn = Num_free
		from #tmp_res_monitor
		where Name = 'number of open partitions' and
			Instance_Name = @@instancename
end
else
begin
	select @tmp_int2 = Num_active, @tmp_int = Max_Used, 
		@tmp_int_open_ptn = Num_free
		from #tmp_res_monitor
		where Name = 'number of open partitions'
end
select @rptline = "    Active" + space(28) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int2 , 10) + space(7) +
			@na_str
print @rptline

select @rptline = "    Max Ever Used Since Boot" + space(10) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

select @rptline = "    Free" + space(30) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int_open_ptn, 10) + space(7) +
			@na_str
print @rptline

select @rptline="    Reuse Requests"
print @rptline

/*
** The information for reuse/reuse fail is still stored in monitor
** counters in resource_stats group. 
*/
select @tmp_int1 = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_partition_reuse_requests"

select @rptline = "      Succeeded" + space(23) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int1, 10) + space(7) +
			@na_str
print @rptline

select @tmp_ptn_reuse_failed = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_partition_reuse_fail"

select @rptline = "      Failed" + space(26) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_ptn_reuse_failed , 10) + space(7) +
			@na_str
print @rptline
print @blankline

/* ----------------- number of open databases ------------ */
execute @ret_status = sp_monitorconfig "number of open databases", "#tmp_res_monitor"

if (@ret_status != 0)
begin
        return 0
end
select @rptline = "  Open Database Usage"
print @rptline

if (@@clustermode = "shared disk cluster")
begin
	select @tmp_int2 = Num_active
		from #tmp_res_monitor
		where Name = 'number of open databases' and
			Instance_Name = @@instancename
end
else
begin
	select @tmp_int2 = Num_active
		from #tmp_res_monitor
		where Name = 'number of open databases'
end
select @rptline = "    Active" + space(28) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int2 , 10) + space(7) +
			@na_str
print @rptline

if (@@clustermode = "shared disk cluster")
begin
	select @tmp_int = Max_Used
		from #tmp_res_monitor
		where Name = 'number of open databases' and
			Instance_Name = @@instancename
end
else
begin
	select @tmp_int = Max_Used
		from #tmp_res_monitor
		where Name = 'number of open databases'
end
select @rptline = "    Max Ever Used Since Boot" + space(10) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int, 10) + space(7) +
			@na_str
print @rptline

if (@@clustermode = "shared disk cluster")
begin
	select @tmp_int_dbtables = Num_free
		from #tmp_res_monitor
		where Name = 'number of open databases' and
			Instance_Name = @@instancename
end
else
begin
	select @tmp_int_dbtables = Num_free
		from #tmp_res_monitor
		where Name = 'number of open databases'
end	
select @rptline = "    Free" + space(30) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_int_dbtables, 10) + space(7) +
			@na_str
print @rptline

select @rptline="    Reuse Requests"
print @rptline

/*
** The information for reuse/reuse fail is still stored in monitor
** counters in resource_stats group. 
*/
select @tmp_db_reuse_requests= value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_database_reuse_requests"

select @rptline = "      Succeeded" + space(23) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_db_reuse_requests, 10) + space(7) +
			@na_str
print @rptline


select @tmp_db_reuse_failed = value
  from #tempmonitors
  where group_name like 'resource_stats%' and
                field_name = "open_database_reuse_fail"

select @rptline = "      Failed" + space(26) +
			@na_str + space(11) +
			@na_str + space(2) +
			str(@tmp_db_reuse_failed , 10) + space(7) +
			@na_str

print @rptline
print @blankline


/* ----------------- Object Manager Spinlock Contention ------------ */
select @spinlock_contention = isnull(avg(100.0*w.value/g.value), 0)
  from #tempmonitors g, #tempmonitors w
  where w.group_name like 'spinlock_w%' 
    and w.field_name = "Resource->rdesmgr_spin"
    and g.field_name = "Resource->rdesmgr_spin"
    and g.group_name like 'spinlock_p%'
    and g.field_id = w.field_id
    and g.value > 0

select @rptline = "  Object Manager Spinlock Contention"+ space(2) +
		@na_str + space(11)+
		@na_str + space(9) +
		@na_str  + space(5) +
		str(@spinlock_contention,5,1) + @psign,
		@desmgr_contention = @spinlock_contention
print @rptline
print @blankline

/* ----------------- Object Spinlock Contention ------------ */
select @spinlock_contention = isnull(avg(100.0*w.value/g.value), 0)
  from #tempmonitors g, #tempmonitors w
  where w.group_name like 'spinlock_w%' 
    and w.field_name = "Des Upd Spinlocks"
    and g.field_name = "Des Upd Spinlocks"
    and g.group_name like 'spinlock_p%'
    and g.field_id = w.field_id
    and g.value > 0

select @rptline = "  Object Spinlock Contention"+ space(10) +
		@na_str + space(11)+
		@na_str + space(9) +
		@na_str  + space(5) +
		str(@spinlock_contention,5,1) + @psign,
		@des_contention = @spinlock_contention
print @rptline
print @blankline

/* ----------------- Index Spinlock Contention ------------ */
select @spinlock_contention = isnull(avg(100.0*w.value/g.value), 0)
  from #tempmonitors g, #tempmonitors w
  where w.group_name like 'spinlock_w%' 
    and w.field_name = "Ides Spinlocks"
    and g.field_name = "Ides Spinlocks"
    and g.group_name like 'spinlock_p%'
    and g.field_id = w.field_id
    and g.value > 0

select @rptline = "  Index Spinlock Contention" + space(11) +
		@na_str + space(11)+
		@na_str + space(9) +
		@na_str  + space(5) +
		str(@spinlock_contention,5,1) + @psign,
		@ides_contention = @spinlock_contention
print @rptline
print @blankline

/* ----------------- Index Hash Spinlock Contention ------------ */
select @spinlock_contention = isnull(avg(100.0*w.value/g.value), 0)
  from #tempmonitors g, #tempmonitors w
  where w.group_name like 'spinlock_w%' 
    and w.field_name = "Ides Chain Spinlocks"
    and g.field_name = "Ides Chain Spinlocks"
    and g.group_name like 'spinlock_p%'
    and g.field_id = w.field_id
    and g.value > 0

select @rptline = "  Index Hash Spinlock Contention" + space(6) +
		@na_str + space(11) +
		@na_str + space(9) +
		@na_str  + space(5) +
		str(@spinlock_contention,5,1) + @psign,
		@ides_hash_contention = @spinlock_contention
print @rptline
print @blankline

/* ----------------- Partition Spinlock Contention ------------ */
select @spinlock_contention = convert(int,isnull(avg(100.0*w.value/g.value), 0))
  from #tempmonitors g, #tempmonitors w
  where w.group_name like 'spinlock_w%' 
    and w.field_name = "Pdes Spinlocks"
    and g.field_name = "Pdes Spinlocks"
    and g.group_name like 'spinlock_p%'
    and g.field_id = w.field_id
    and g.value > 0

select @rptline = "  Partition Spinlock Contention" + space(7) +
		@na_str + space(11)+
		@na_str + space(9) +
		@na_str  + space(5) +
		str(@spinlock_contention,5,1) + @psign,
		@pdes_contention = @spinlock_contention
print @rptline
print @blankline

/* ----------------- Partition Hash Spinlock Contention ------------ */
select @spinlock_contention = convert(int,isnull(avg(100.0*w.value/g.value), 0))
  from #tempmonitors g, #tempmonitors w
  where w.group_name like 'spinlock_w%' 
    and w.field_name = "Pdes Chain Spinlocks"
    and g.field_name = "Pdes Chain Spinlocks"
    and g.group_name like 'spinlock_p%'
    and g.field_id = w.field_id
    and g.value > 0

select @rptline = "  Partition Hash Spinlock Contention" + space(2) +
		@na_str + space(11) +
		@na_str + space(9) +
		@na_str  + space(5) +
		str(@spinlock_contention,5,1) + @psign,
		@pdes_hash_contention = @spinlock_contention
print @rptline
print @blankline

if @Reco = 'Y'
 begin
        select @recotxt =     "  Tuning Recommendations for Metadata Cache Management"
        select @recoline = "  ----------------------------------------------------"
        select @reco_hdr_prn = 0

	/*
	** If the number of open objects configured is equal to  
	** the high water mark for open objects used and if the
	** number of times a reuse of an open object failed
	** consider increasing the 'number of open objects'
	*/
	if (@tmp_int_open_object = 0 or @tmp_obj_reuse_failed > 0)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the 'number of open objects'"
		print "    configuration parameter."
		print @blankline
	end	

	/*
	** If the number of open indexes configured is equal to  
	** the high water mark for open indexes used and if the
	** number of times a reuse of an open indexes failed
	** consider increasing the 'number of open indexes'
	*/
	if (@tmp_int_open_index = 0 or @tmp_ind_reuse_failed > 0)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the 'number of open indexes'" 
		print "    configuration parameter." 
		print @blankline
	end	

	/*
	** If the number of open partitions configured is equal to  
	** the high water mark for open partitions used and if the
	** number of times a reuse of an open partitions failed
	** consider increasing the 'number of open partitions'
	*/
	if (@tmp_int_open_ptn = 0 or @tmp_ptn_reuse_failed > 0)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the 'number of open partitions'" 
		print "    configuration parameter." 
		print @blankline
	end	

	/*
	** If the number of open databases configured is equal to  
	** the high water mark for open databases used and if the
	** number of times a reuse of an open databases failed
	** consider increasing the 'number of open databases'
	*/
	if (@tmp_int_dbtables = 0 or @tmp_db_reuse_requests > 0 or @tmp_db_reuse_failed > 0)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
		print "  - Consider increasing the 'number of open databases'" 
		print "    configuration parameter."
		print @blankline
	end	

	/*
	** If the contention on the object manager spinlock is > 10%
	** consider using dbcc tune(des_bind, dbid, objname) on the hot objects
	*/
	if (@desmgr_contention > 10)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
        	print "  - Consider identifying the hot objects using sp_object_stats"
		print "    and using dbcc tune(des_bind, <dbid>, <objname>) on the" 
		print "    hottest set of objects."
		print @blankline
	end

	/*
	** If the contention on the object spinlock is > 3%
	** consider decreasing the 'open object spinlock ratio'
	*/
	if (@des_contention > 3)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
        	print "  - Consider decreasing the 'open object spinlock ratio'"
		print "    configuration parameter."
		print @blankline
	end
	
	/*
	** If the contention on the index spinlock is > 3%
	** consider decreasing the 'open index spinlock ratio'
	*/
	if (@ides_contention > 3)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
        	print "  - Consider decreasing the 'open index spinlock ratio'"
		print "    configuration parameter."
		print @blankline
	end

	/*
	** If the contention on the ides chain spinlock is > 3%
	** consider decreasing the 'open index hash spinlock ratio'
	*/
	if (@ides_hash_contention > 3)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
        	print "  - Consider decreasing the 'open index hash spinlock ratio'"
		print "    configuration parameter."
		print @blankline
	end

	/*
	** If the contention on the partition spinlock or
	** pdes chain spinlock is > 3%
	** consider decreasing the 'partition spinlock ratio'
	*/
	if (@pdes_contention > 3 or @pdes_hash_contention > 3)
	begin
		if (@reco_hdr_prn = 0)
		begin
			print @recotxt
			print @recoline
			select @reco_hdr_prn = 1
		end
        	print "  - Consider decreasing the 'partition spinlock ratio'"
		print "    configuration parameter."
		print @blankline
	end
 end
return 0
go
exec sp_procxmode 'sp_sysmon_mdcache', 'anymode'
go
grant execute on sp_sysmon_mdcache to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_collect')
begin
	drop procedure sp_sysmon_collect
end
go
print "Installing sp_sysmon_collect"
go

/* Messages for sp_sysmon_collect
**
** 17142, "You need to be able to set curwrite label to data_high.  This script wi
ll continue in spite of failure to set curwrite. Please rerun after setting your l
abels correctly."
** 18179, "Invalid parameter '%1!'. Usage: sp_sysmon {'begin_sample'|{{'end_sample'|'hh:mm:ss'}[,section] [,@applmon={'appl_only'|'appl_and_login'|'no_appl'}]}}"
** 18127, "You must have System Administrator (SA) role to execute this
**         stored procedure."
** 18307, "Server name '%1!' does not exist in sysservers."
** 19121, "%1!: Permission denied. This operation requires mon_role"
** 17260, "Can't run %1! from within a transaction."
** 19122, "%1! is not installed. Please run '%2!' script with appropriate role
**	   %3!"
** 19374, "The monitor counter usage count was not decremented as expected
**	when sp_sysmon end_sample was executed. This may be because the
**	monitor counters were enabled by another user or because you executed
**	sp_sysmon begin_sample in another session. If you wish to decrement
**	the monitor counter usage count, execute the command
**	'dbcc monitor (decrement)'."
*/
create procedure sp_sysmon_collect
  @interval_or_option char(12), /* Time interval string, option 
				** "begin_sample" or "end_sample" */
  @section_name char(80),	/* used to decide call to mda proc */
  @applmon char(14),		/* Application monitoring option */
  @noclear int = 0		/* Whether to operate in no clear mode */
as
 
/* --------- declare local variables --------- */
declare @status int             /* hold sproc status codes */
declare	@mda_procname char(50)	/* call sp_sysmon_collect_mda */ 
declare @rtn_status int		/* hold mda sproc return status codes */
declare	@mda_status int		/* check if mda is enabled */
declare	@enabled_status int	/* success of enabling monitoring */
declare @has_mon_role int	/* check for mon_role */
declare @cache_wizard_section tinyint /* 1 indicates cache wizard section */
declare @monitor_usage_count int /* # of processes using monitor counters */
 
/* --------- Setup Environment --------- */
set nocount on                  /* disable row counts being sent to client */
 
/*
** If the interval_or_option string is not an option (i.e. "begin_sample" or "end_sample")
** then it must be an time interval string. Validate that.
*/

if (@interval_or_option != "begin_sample" and @interval_or_option != "end_sample")
 begin
	if (patindex("[0-9][0-9]:[0-5][0-9]:[0-5][0-9]", @interval_or_option) = 0 or
		patindex("00:00:00",@interval_or_option) = 1)
  	begin
	  	raiserror 18179, @interval_or_option
        	return 1
  	end
 end
 
/*
** Check if OK to Run
*/
if proc_role("sa_role") < 1
  begin
        /* 18127, "You must have System Administrator (SA) role to execute
        this stored procedure." */
        raiserror 18127, "sp_sysmon"
        return 1
  end
 
/*
** In a transaction?, disallow since it might make recovery impossible
*/
if @@trancount > 0
  begin
        /* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_sysmon"
        return 1
  end
else
set chained off
set transaction isolation level 1
select @mda_procname = 'sp_sysmon_collect_mda'
select @has_mon_role = 1
/* Check if user has mon_role */
if (charindex("mon_role", show_role()) = 0)
begin
	select @has_mon_role = 0
end

/*
** Retrieve the current settings for 'enable monitoring'(356)
** and 'per object statistics'(387) config options. We will
** have to enable these if they are not enabled and restore them
** to their original state at the end of sampling.
** We use @mda_status as a bit map with the first bit representing 
** config # 356 and the 2nd bit representing 387.
*/
select	@mda_status = isnull(cur.value, 0)
from	master.dbo.sysconfigures con,
	master.dbo.syscurconfigs cur
where	con.config = 356
and	con.config *= cur.config

select	@mda_status = @mda_status + 2 * isnull(cur.value, 0)
from	master.dbo.sysconfigures con,
	master.dbo.syscurconfigs cur
where	con.config = 387
and	con.config *= cur.config

if (@section_name = "cache wizard")
begin
	select @cache_wizard_section = 1
end
else
begin
	select @cache_wizard_section = 0
end


/*
** Clear out all monitor counters 
** only if an interval is specified
** or if the option is "begin_sample"
*/
if (@interval_or_option != "end_sample")
 begin 
	/*
	** Clear and enable monitor counters if not in noclear mode.  In 
	** noclear mode this will have been done by the sp_sysmon procedure.
	*/
	if (@noclear = 0)
	begin
		/*
		** Clear monitor counter values to create
		** baseline.
		*/
		dbcc monitor("clear", "all", "on")
		dbcc monitor("clear", "spinlock_s", "on")
		if (@applmon != "no_appl" and @cache_wizard_section != 1)
		begin
			dbcc monitor("clear", "appl", "on")
		end
	end

	/*
	** If user has specified the interval and a section other than
	** cache wizard, there is no need to worry about the
	** sp_sysmon_collect_mda procedure
	** Else,  invoke sp_sysmon_collect_mda if it has been installed.
	*/
	if ( ((@interval_or_option = "begin_sample") or 
		(@cache_wizard_section = 1)) 
	      and exists(select 1 from sybsystemprocs.dbo.sysobjects where
			sysstat & 7 = 4 and name like @mda_procname))
	begin
		/*
		** Only in the case of begin_sample, we do not know
		** the sections the user is interested in, hence
		** the error message is not printed.
		*/
		if (@has_mon_role = 0)
		begin
			if (@interval_or_option = "begin_sample")
			begin
				return 0
			end
               		else if (@cache_wizard_section = 1)
			begin
				raiserror 19121, "sp_sysmon_collect"
				return 1
			end
        	end

		/* Enable MDA if not enabled */
		if (@mda_status & 1 = 0)
		begin
	                select @enabled_status =
				config_admin(23, 356, 1, 0, NULL, NULL)
		end

		if (@mda_status & 2 = 0)
		begin
	                select @enabled_status =
				config_admin(23, 387, 1, 0, NULL, NULL)
		end

		/*
		** We don't want the MDA collect operation to affect
		** monitoring. Hence disable monitoring and disable
		** MDA using mdaconfig. After the initial snapshot
		** is taken, enable monitoring and MDA.
		*/
		select @status = mdaconfig('freeze', 'begin')
		dbcc monitor("sample", "all", "off")
		dbcc monitor("sample", "spinlock_s", "off")
		exec @rtn_status = @mda_procname @interval_or_option,
						 @mda_status
		dbcc monitor("sample", "all", "on")
		dbcc monitor("sample", "spinlock_s", "on")
		select @status = mdaconfig('freeze', 'end')
	end
	/*
	** if the option is "begin_sample", then
	** the job is done, so return 
	*/

	if (@interval_or_option = "begin_sample")
 	begin
		return 0
 	end

	/*
	** Sleep while accumulating counter statistics
	** for the interval time specified
	*/

	waitfor delay @interval_or_option
 end
 
/*
**  Sample Performance Stats
*/
dbcc monitor("sample", "spinlock_s", "off")
if (@applmon != "no_appl")
begin
	dbcc monitor("sample", "appl", "off")
end
select @monitor_usage_count = @@monitors_active
dbcc monitor("sample", "all", "off")

/*
** Check to see whether the monitor counter usage count was decremented
** when monitor counters were turned off.  If it was not, this is
** probably because the user executed sp_sysmon begin_sample from
** another login session.  Display a message warning the user that
** the usage count was not decremented and suggesting that they
** run dbcc monitor(decrement) to decrement it.
*/
if (@@monitors_active = @monitor_usage_count)
begin
	raiserror 19374
end

dbcc monitor("select", "spinlock_s", "on")
dbcc monitor("select", "all", "on")

select @rtn_status = 0
/*
** Call sp_sysmon_collect_mda to store the snapshot at
** the end of time interval only if the section is a
** valid MDA section.
*/
if (@cache_wizard_section = 1)
begin
	if exists(select 1 from sybsystemprocs.dbo.sysobjects where
			sysstat & 7 = 4 and name = 'sp_sysmon_collect_mda')
	begin
		if (@has_mon_role = 0)
		begin
			raiserror 19121, "sp_sysmon_collect"
			return 1
		end
	
		/*
		** Halt the MDA counters during the time we execute
		** sp_sysmon_collect_mda
		*/
		select @status = mdaconfig('freeze', 'begin')
		exec @rtn_status = @mda_procname "end_sample",
					@mda_status output
		select @status = mdaconfig('freeze', 'end')

		/* Reset the config #356, 387 if it was set by us */
		if (@mda_status & 1 = 0)
		begin
			select @enabled_status =
				config_admin(23, 356, 0, 0, NULL, NULL)
		end

		if (@mda_status & 2 = 0)
		begin
			select @enabled_status =
				config_admin(23, 387, 0, 0, NULL, NULL)
		end
	end
	
	else
	begin
		select @rtn_status = 1
		/* Print message that MDA is not installed */
		raiserror 19122, "MDA", "installmontables", "(mon_role)"
	end
	
	if @rtn_status = 1
	begin
		return @rtn_status
	end
end
/* If we turned on monitoring during begin_sample
** turn it off now. Note that we wouldn't turn this on
** for the interval case unless the 'cache wizard' section
** was specified.
*/
else if((@mda_status & 1 = 1) and
	(@interval_or_option = "end_sample") 
	and exists(select 1 from sybsystemprocs.dbo.sysobjects where
			sysstat & 7 = 4 and name like @mda_procname))
begin
	/* 99 indicates sp_sysmon_collect_mda should just return the stored
	** value of @mda_status and is chosen since it has the lower bits
	** 1,2 set.
	*/
	select @mda_status = 99
	exec @rtn_status = @mda_procname "end_sample",
				@mda_status output

	/* Reset the config #356, 387 if it was set by us */
	if (@mda_status & 1 = 0)
	begin
		select @enabled_status =
			config_admin(23, 356, 0, 0, NULL, NULL)
	end

	if (@mda_status & 2 = 0)
	begin
		select @enabled_status =
			config_admin(23, 387, 0, 0, NULL, NULL)
	end
end

/*
** If the interval is less than a second
** do not produce the report
*/

if (@interval_or_option = "00:00:00")
 begin
	raiserror 18545,"sp_sysmon"
	return 1
 end

return 0
go
exec sp_procxmode 'sp_sysmon_collect', 'anymode'
go
grant execute on sp_sysmon_collect to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_analyze')
begin
	drop procedure sp_sysmon_analyze
end
go
print "Installing sp_sysmon_analyze"
go

/* This stored procedure produces is used to invoke all the subordinate stored
** procedures
*/
create procedure sp_sysmon_analyze
	@interval int,
	@Reco char(1),
	@section char(80),
	@applmon char(14),
	@instid	smallint = NULL	/* optional SDC instance id */
as

/* ----------- declare local variables ---------- */
declare @NumXacts int           /* for per transactions calculations */
declare @NumElapsedMs int       /* for "per Elapsed second" calculations */
declare @NumEngines tinyint     /* number of engines online */
declare @tmpNumEngines tinyint     /* number of engines online */
declare @status int             /* hold sproc status codes */
declare @eng_count int
declare @tmpelapsedMs int
declare @GetStatTime datetime   /* time monitor counters sampled */
declare @sec_hdr char(80)       /* string to delimit sections on printout */
declare @blankline char(1)      /* to print blank line */
declare @rptline char(80)       /* formatted stats line for print statement */
declare @tmp_grp_name varchar(80)
declare @tmp_elapsedMs_total int
declare @CacheID smallint       /* Cache ID to map to buffer_N group */
declare @CacheName varchar(255)  /* Cache Name from cache id lookup */
declare @i int
declare @msg varchar(255)

select @eng_count =0
select @tmp_elapsedMs_total =0
select @sec_hdr = "==============================================================================="
 
select @tmpNumEngines = value
from #tempmonitors where
field_name="cg_cmaxonline" and
group_name ="config"

select @NumEngines = 0
 
while @eng_count <  @tmpNumEngines
 begin 
        select @tmp_grp_name="engine_" + convert(varchar(3),@eng_count)
 
        if (select value
                from #tempmonitors where field_name="clock_ticks"
                and group_name=@tmp_grp_name) > 0
           begin 
                        select @NumEngines = @NumEngines + 1
           end 

           select @eng_count = @eng_count + 1
 end 


select @NumElapsedMs = @interval*1000 

 
/*
**      Name:           Number of Transactions
**      Descrip:        Measures the number of committed transactions, both
**                      explicit via BEGIN TRAN and COMMIT TRAN as well as
**                      implicit via single statement DML.  Used to report
**                      not just how much work has been done within the sample
**                      but, more importantly, as a measure of viewing other
**                      statistics with a common denominator (ie., I/Os per
**                      transaction).  This provides a common way of judging
**                      the effects of making changes within a controlled test
**                      environment.
**
**                      For example, what effect does adding memory have on I/O
**                      rates.
**      Calc:           access.xacts
**      Caveats:        This counter is also incremented once for each
**                      "sub-transaction" participating in a multi-DB
**                      transaction.
**      Tuning:         None, informational only to provide a frame of
**                      reference for evaluating other statistics.
*/
 
select @NumXacts = value
  from #tempmonitors
  where group_name = "access" and
        field_name = "xacts"
 
if @NumXacts = 0
  select @NumXacts = 1            /* avoid divide by 0 for all per xact calcs */

/* 
** Since monitor counters are updated usually without any synchronization
** these are not completely accurate in multi-engine scenarios where trace 
** 4050 is used or if the platform is NT where we don't have engine local 
** counters. Usually this is not a problem. But in cases where we deduce some 
** values based on the relative values of two or more counters, this can cause 
** sysmon to report meaningless values at times. (E.g. -ve values)
** We should fixup any such counters here to avoid meaningless reporting.  
**
** 1. Cache Misses = Cache searches - Cache hits
**	If hits > searches set hits = searches.
**	Although we have cache hit counters at pool level, those are not being 
**	used in reporting so we need not take care of them here.
*/

update #tempmonitors
   set value = b.value
from #tempmonitors a, #tempmonitors b
where a.group_name = b.group_name
  and a.group_name like 'buffer_%'
  and b.group_name like 'buffer_%'
  and a.field_name = 'bufsearch_calls'
  and b.field_name = 'bufsearch_finds'
  and a.value < b.value

if (@section= "NULL")
	begin 
			exec @status = sp_sysmon_kernel @NumEngines, @NumElapsedMs, @NumXacts, @Reco, @instid
			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */

			exec @status = sp_sysmon_wpm  @NumElapsedMs,@NumXacts, @Reco

			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */

			exec @status = sp_sysmon_parallel  @NumElapsedMs,@NumXacts, @Reco

			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */

			exec @status = sp_sysmon_taskmgmt @NumEngines, @NumElapsedMs, @NumXacts, @Reco
			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */

			exec @status = sp_sysmon_appmgmt @NumEngines, @NumElapsedMs, @NumXacts, @applmon
			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */

			exec @status = sp_sysmon_esp @NumElapsedMs, @NumXacts
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_hk @NumElapsedMs, @NumXacts, @Reco, @instid
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_maccess @NumElapsedMs, @NumXacts, @Reco
			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */

                        exec @status = sp_sysmon_xactsum  @NumElapsedMs, @NumXacts
                        if @status = 1          /* fatal error - abort run */
                        begin 
                                /* Subordinate stored procedures print their own messages. */
                                return 1
                        end /* } */

			exec @status = sp_sysmon_xactmgmt @NumElapsedMs, @NumXacts, @Reco
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_index @NumElapsedMs, @NumXacts
        		if @status = 1          /* fatal error - abort run */
                	begin 
               	        	 /* Subordinate stored procedures print their own messages. */
               	        	 return 1
                	end /* } */

			exec @status = sp_sysmon_mdcache @NumElapsedMs, @NumXacts, @Reco
			if @status = 1          /* fatal error - abort run */
 			begin 
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
 			end /* } */
		
	
			exec @status = sp_sysmon_locks @NumElapsedMs, 
					@NumXacts, @Reco, @NumEngines
        		if @status = 1          /* fatal error - abort run */
                	begin 
               	        	 /* Subordinate stored procedures print their own messages. */
               	        	 return 1
                	end /* } */

			exec @status = sp_sysmon_dcache @NumEngines, @NumElapsedMs, @NumXacts, @Reco, @instid
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_pcache @NumElapsedMs, @NumXacts, @Reco
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_memory @NumElapsedMs, @NumXacts
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_recovery @NumElapsedMs, @NumXacts
			if @status = 1          /* fatal error - abort run */
			begin 
                        	/* Subordinate stored procedures print their own messages. */
                        	return 1
                	end /* } */

			exec @status = sp_sysmon_diskio @NumEngines, @NumElapsedMs, @NumXacts, @Reco
        		if @status = 1          /* fatal error - abort run */
                	begin 
                       		 /* Subordinate stored procedures print their own messages. */
                       		 return 1
                	end /* } */

			exec @status = sp_sysmon_netio @NumEngines, @NumElapsedMs, @NumXacts
			if @status = 1          /* fatal error - abort run */
 			begin /* { */
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
			end /* } */
			exec @status = sp_sysmon_repagent 
			if @status = 1          /* fatal error - abort run */
 			begin /* { */
       	 			/* Subordinate stored procedures print their own messages. */
       	 			return 1
			end /* } */
			return 0
	end /* } */
else
if (@section="kernel")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_kernel @NumEngines, @NumElapsedMs, @NumXacts , @Reco, @instid
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="wpm")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_wpm @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="parallel")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_parallel  @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                	begin /* { */
                       		 /* Subordinate stored procedures print their own
                       		 messages. */
                       		 return 1
                	end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="taskmgmt")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_taskmgmt @NumEngines, @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                	begin /* { */
                       		 /* Subordinate stored procedures print their own
                       		 messages. */
                       		 return 1
                	end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="appmgmt")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_appmgmt @NumEngines, @NumElapsedMs, @NumXacts, @applmon
		if @status = 1          /* fatal error - abort run */
 		begin /* { */
       	 		/* Subordinate stored procedures print their own messages. */
       	 		return 1
 		end /* } */
		else
		begin /* { */
			return 0
		end /* } */
	end /* } */
else 
if (@section="esp")
	begin
		exec @status = sp_sysmon_esp @NumElapsedMs, @NumXacts
        	if @status = 1          /* fatal error - abort run */
                begin 
                  	 /* Subordinate stored procedures print their own messages. */
                       	 return 1
                end /* } */
	end /* } */
else 
if (@section="housekeeper")
	begin
		exec @status = sp_sysmon_hk @NumElapsedMs, @NumXacts, @Reco, @instid
        	if @status = 1          /* fatal error - abort run */
                begin 
                  	 /* Subordinate stored procedures print their own messages. */
                       	 return 1
                end /* } */
	end /* } */
else 
if (@section="monaccess")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_maccess @NumElapsedMs, @NumXacts, @Reco
		if @status = 1          /* fatal error - abort run */
 		begin /* { */
       	 		/* Subordinate stored procedures print their own messages. */
       	 		return 1
 		end /* } */
	end /* } */
else
if (@section="xactsum")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_xactsum  @NumElapsedMs, @NumXacts
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="xactmgmt")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_xactmgmt @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="indexmgmt")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_index @NumElapsedMs, @NumXacts
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="mdcache" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_mdcache @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="locks" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_locks @NumElapsedMs, 
				@NumXacts, @Reco, @NumEngines
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="dcache" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_dcache @NumEngines, @NumElapsedMs, @NumXacts, @Reco, @instid
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="pcache" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_pcache @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="memory" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_memory @NumElapsedMs, @NumXacts
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="recovery" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_recovery @NumElapsedMs, @NumXacts
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="diskio")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_diskio @NumEngines, @NumElapsedMs, @NumXacts, @Reco
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else 
if (@section="netio" )
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_netio @NumEngines, @NumElapsedMs, @NumXacts
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */

else 
if (@section="repagent")
	begin /* { */ 
		print @sec_hdr
		exec @status = sp_sysmon_repagent 
        	if @status = 1          /* fatal error - abort run */
                begin /* { */
                        /* Subordinate stored procedures print their own
                        messages. */
                        return 1
                end /* } */
		else
		begin /* { */
			return 0
		end /* } */

	end /* } */
else
	begin 
		raiserror 18532 @msg, "sp_sysmon"
		raiserror 18534 @msg, "sp_sysmon"
	end
go
exec sp_procxmode 'sp_sysmon_analyze', 'anymode'
go
grant execute on sp_sysmon_analyze to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_shmdumpsize')
begin
	drop procedure sp_shmdumpsize
end
go
print "Installing sp_shmdumpsize"
go

/*
** SP_SHMDUMPSIZE
**
** This stored procedure calculates the estimated size for a shared memory
** dump file.  It is not meant to be executed from the command line, but
** is called by the sp_shmdumpconfig stored procedure when displaying
** current configuration informmtion.  Expect the values calculated to be
** conservative and to overestimate the size significantly.
**
** Returns the estimated size in the @size output parameter.  This value
** is in megabyte units.
**
** History:
** 16dec96	pdorfman	written
** 28aug97	pdorfman	corrected arithmetic overflow problem
** 31mar99	pdorfman	More improvments in memory calculation (197105)
** 20apr04	pdorfman	Correct procedure cache size calculations
*/

create procedure sp_shmdumpsize
@pagecache	varchar(20),	/* Page cache setting for condition           */
@proccache	varchar(20),	/* Procedure cache setting for condition      */
@size		int	output	/* Estimated size of dump file in megabytes
				** (return value) 
				*/
as
declare	@cache_size	int,
	@proc_percent	int,
	@proc_size	int,
	@defpagecache	int,
	@defproccache	int,
	@memory		int

select @cache_size = 0
select @proc_size = 0

/*
** Determine the default settings for page caches and procedure cache
*/
select @defpagecache = int_value 
	from master.dbo.sysattributes sa
        where sa.class 		= 7
        and sa.object_type 	= "DC"
        and sa.attribute 	= 5
        and sa.object_info1 	= 5
	
select @defproccache = int_value 
	from master.dbo.sysattributes sa
        where sa.class 		= 7
        and sa.object_type 	= "DC"
        and sa.attribute 	= 5
        and sa.object_info1 	= 6

/*
** 19 is the config # for named caches.
** This value is in kilobytes.
*/
select @cache_size = sum(cu.value)
	from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
	where co.config	= 19 
	and co.config 	= cu.config
	and co.name 	= cu.comment

/*
** Obtain the current total memory allocated to the server. 104 is the
** configuration # for total logical memory. 
*/
select @memory = convert(int, comment)
	from master.dbo.syscurconfigs
	where config 	= 104

/*
** Set initial size to total memory value.  Subsequent
** operations subtract from this amount.
*/
select @size = @memory

/*
** Determine whether and how much memory to exclude for page caches
*/
if (@pagecache = "Omit" or (@pagecache = "Default" and @defpagecache != 1))
begin
	select @size = @size - @cache_size
end

/*
** Determine whether and how much memory to subtract for procedure cache.
** Since the default action is to include the procedure cache in the dump
** file, only perform this operation if the user has explicitly configured
** this condition to omit the procedure cache or if the dump mode for
** the procedure cache in the Defaults setting is 2 (omit).
** This calculation is very conservative and tends to over estimate
** the amount of space required for the dump file.
*/
if (@proccache = "Omit" or (@proccache = "Default" and  @defproccache = 2))
begin
	/*
	** Combine procedure cache size and statement cache
	** size to get total memory allocated to procedure cache.
	** Config # 146 is the procedure cache size value.
	** Config # 414 is the statement cache size value.
	*/
	select @proc_size = sum(convert(int, comment))
		from master.dbo.syscurconfigs
		where config in (146, 414)

	select @size = @size - @proc_size
end

/*
** Convert @size from kilobytes to megabytes
*/
select @size = (@size / 1024) + 1

return 0

go
exec sp_procxmode 'sp_shmdumpsize', 'anymode'
go
grant execute on sp_shmdumpsize to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_shmdumpdrop')
begin
	drop procedure sp_shmdumpdrop
end
go
print "Installing sp_shmdumpdrop"
go

/*
** SP_SHMDUMPDROP
**
** This stored procedure is used to drop shared memory dump conditions.
** It is called by the sp_shmdumpconfig stored procedure when I user
** invokes sp_shmdumpconfig to drop a dump condition.
**
** Security: The sa_role role is required in order to execute this
** stored procedure.
**
** History:
** 19sept96	pdorfman	Initial coding
** 07Apr97	pdorfman	Created separate stored procedure
*/

create procedure sp_shmdumpdrop
/* -------------- Stored Procedure Parameters ----------------------- */
@type 		varchar(20),		/* type of attribute affected */
@value 		int,			/* attribute value            */
@attrib		int			/* attribute id from caller   */
as

/* ----------------- Declare Local Variables ------------------------ */
declare @object		int, 		/* object column value        */
	@not_status 	int		/* notification return status */


/*
** The following variables are treated as constants within this
** stored procedure. They are set below.
*/
declare @DUMPCOND_CLASS	int,		/* sysattributes class        */
	@OBJTYPE	char(2),	/* sysattributes object typ   */
	@CFG_PRIMARY	int,		/* primary record id          */
	@CFG_FILENAME	int,		/* file name record id        */
	@CFG_DIRNAME	int,		/* directory name record id   */
	@CFG_MAXDUMPS	int,		/* maxdumps record id         */
	@CFG_PAGECACHE	int,		/* page cache record id       */
	@CFG_PROCCACHE	int,		/* proc cache record id       */
	@CFG_UNUSED	int,		/* unused memory record id    */
	@ATTR_ADD	int,		/* add notification value     */
	@ATTR_CHANGE	int,		/* change notification val    */
	@ATTR_DROP	int,		/* drop notification value    */
	@ATTR_FETCH	int,		/* fetch notification value   */
	@CFG_INCLUDE	int,		/* include memory type        */
	@CFG_OMIT	int,		/* omit memory type           */
	@CFG_DEFAULT	int		/* use default mem setting    */

/* ----------------- Setup and Validation ------------------------ */
set nocount on

/*
** Verify that the user has sufficient permissions to
** update the dump configuration
*/
if (proc_role("sa_role") < 1)
begin
	return 1
end

/*
**  Common Definition Section: Note: any changes made to the following
**  values must also be made in shmdumpconfig and shmdumpdisp
*/

/*
** Class ID and type defined in utils/attrib.lst
*/
select @DUMPCOND_CLASS 	= 7
select @OBJTYPE		= "DC"

/*
** The following constants define record types for the dump condition
** class in the sysattributes table.The values set here must be the 
** same as those defined in utils/cfgdump.c.
*/
select @CFG_PRIMARY 	= 1
select @CFG_FILENAME 	= 2
select @CFG_DIRNAME 	= 3
select @CFG_MAXDUMPS 	= 4
select @CFG_PAGECACHE 	= 5
select @CFG_PROCCACHE 	= 6
select @CFG_UNUSED 	= 7

/*
** The following must correspond to values in sysattr.h
*/
select @ATTR_ADD 	= 1
select @ATTR_CHANGE	= 2
select @ATTR_DROP	= 3
select @ATTR_FETCH	= 4

/*
** End Common Definition Section
*/
 
/* ----------------- Identify and Perform the Command ----------- */

if (@type = 'defaults')
begin
	/*
	** 18508, "You cannot drop the system default settings"
	*/
	raiserror 18508
	return 1
end
 
begin tran drop_condition

/*
** Delete all rows belonging to this condition from
** the sysattributes table.
*/
if (@type in ('severity', 'timeslice', 'defaults', 'panic', 'dbcc')
    and @value is NULL)
begin
	/*
	** Value not required in order to drop
	** a severity, timeslice, panic, dbcc or defaults condition
	*/
	delete master.dbo.sysattributes
		where class = @DUMPCOND_CLASS    
		and object_type = @OBJTYPE   
		and attribute = @attrib 
end
else
begin
	/*
	** For other condition types a value
	** must also be supplied.
	*/
	select @object = @value
	delete master.dbo.sysattributes
		where class = @DUMPCOND_CLASS    
		and object_type = @OBJTYPE   
		and attribute = @attrib 
		and object = @object
end

if (@@rowcount = 0)
begin
	/*
	** 18509, "There is no condition set for %1! %2!"
	*/
	raiserror 18509, @type, @object
	rollback tran drop_condition
	return 1
end

if (@@error = 0)
begin
	select @not_status = attrib_notify(
				@DUMPCOND_CLASS,/*cl*/
				@attrib, 	/*attrib */
				@OBJTYPE,    	/*type*/ 
				@object, 	/*object*/
				@CFG_PRIMARY,	/*info1*/
				NULL, 		/*info2*/
				NULL, 		/*info3*/
				NULL, 		/*cinfo*/
				NULL,		/*intval*/
				NULL,		/*charval*/
				NULL, 		/*textval*/
				NULL, 		/*imageval*/
				NULL,		/*comment*/
				@ATTR_DROP)

	if (@not_status = 0)
	begin
		/*
		** 18510, "Notification failed. Your change did not take affect."
		*/
		raiserror 18510
		rollback tran drop_condition
		return 1
	end
end

/*
** Delete of rows and notification were successful.
** Commit transaction.
*/
commit tran drop_condition

/*
** Indicate success
*/
return 0

/*
** End sp_shmdumpdrop
*/
go
exec sp_procxmode 'sp_shmdumpdrop', 'anymode'
go
grant execute on sp_shmdumpdrop to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_shmdumpdisp')
begin
	drop procedure sp_shmdumpdisp
end
go
print "Installing sp_shmdumpdisp"
go

/*
** SP_SHMDUMPDISP
**
** This stored procedure is used to display the current setting for
** shared memory dump conditions. It is called by the sp_shmdumpconfig
** stored procedure when a user executes sp_shmdumpconfig to display
** the current settings.
**
** This stored procedure calls the sp_shmdumpsize stored procedure 
** in order to get size estimates for the shared memory dump files
** that will be generated for each condition.
**
** History:
** 19sept96	pdorfman	Initial coding
** 07apr97	pdorfman	Created separate stored procedure
** 21jan02	dwein		Added support for message type
** 19apr04	pdorfman	Skip dump count for default condition
*/

create procedure sp_shmdumpdisp
/* -------------- Stored Procedure Parameters ----------------------- */
@type	 	varchar(20) 		/* action requested by user   */
as

/* ----------------- Declare Local Variables ------------------------ */
declare @not_status 	int,		/* notification return status */
	@maxconds	int,		/* max # dump conditions      */
	@curcount	int,		/* current # dump cond's      */
	@header_printed	int,		/* display header printed     */
	@print_str	varchar(1024),	/* for printing error msgs    */
	@cache_size     int,		/* total data cache memory    */
        @proc_size      int,		/* size of procedure cache    */
        @memory         int,		/* server total memory        */
        @shm_size       int,		/* non-cache memory           */
        @proc_size_str	char(9),	/* size of procedure cache    */
        @cache_size_str	char(9),	/* server total memory        */
        @shm_size_str	char(9),	/* non-cache memory           */
	@memory_str	char(9),	/* server total memory        */
	@position	int,		/* position of first blank    */
	@windows	int,		/* indicates windows platform */
	@rptline	varchar(512)

/*
** The following variables are treated as constants within this
** stored procedure. They are set below.
*/
declare @DUMPCOND_CLASS	int,		/* sysattributes class        */
	@OBJTYPE	char(2),	/* sysattributes object typ   */
	@CFG_PRIMARY	int,		/* primary record id          */
	@CFG_FILENAME	int,		/* file name record id        */
	@CFG_DIRNAME	int,		/* directory name record id   */
	@CFG_MAXDUMPS	int,		/* maxdumps record id         */
	@CFG_PAGECACHE	int,		/* page cache record id       */
	@CFG_PROCCACHE	int,		/* proc cache record id       */
	@CFG_UNUSED	int,		/* unused memory record id    */
	@CFG_HALT	int,		/* halt option record id	*/
	@ATTR_ADD	int,		/* add notification value     */
	@ATTR_CHANGE	int,		/* change notification val    */
	@ATTR_DROP	int,		/* drop notification value    */
	@ATTR_FETCH	int,		/* fetch notification value   */
	@CFG_INCLUDE	int,		/* include memory type        */
	@CFG_OMIT	int,		/* omit memory type           */
	@CFG_DEFAULT	int,		/* use default mem setting    */
	@CFG_ATTRIBUTE	int,		/* attrib val for config options */
	@CFG_ERRORLOG	int,		/* include errorlog record id */
	@CFG_MERGE	int,		/* merge pll dump record id   */ 
	@CFG_CLUSTER	int		/* cluster dump behavior      */

/*
** Declare variables and cursors used to display current settings
*/
declare	@cond_name	char(10),
	@cond_value	int,
	@cond_cvalue	char(20),
	@cond_attrib	int,
	@rectype	int,
	@int_val	int,
	@char_val	varchar(255),
	@cmaxdumps	char(7),
	@dmaxdumps 	char(7),
	@cpagecache	varchar(20),
	@dpagecache 	varchar(20),
	@cproccache	varchar(20),
	@dproccache	varchar(20),
	@cunused	varchar(20),
	@dunused	varchar(20),
	@chalt		varchar(20),
	@dhalt		varchar(20),
	@cdirname	varchar(255),
	@ddirname	varchar(255),
	@cfilename	varchar(30),
	@dfilename	varchar(30),
	@defaults_found	int,
	@dumpsize	int,
	@cdumpsize	varchar(8),
	@order_number	int,
	@dumpcount	char(3),
	@cfgval		int,
	@cluster	char(7),
	@dcluster	char(7)

/*
** Create temporary lookup table referenced by the c_conditions
** cursor (below).  Table creation is required here in order to 
** declare the cursor.
*/
create table #attname (attrib int, name char(10))

/*
** Create temporary conditions table referenced by the c_display
** cursor (below).  Table creation is required here in order to
** declare the cursor
*/
create table #conditions
	(order_num	int,
	 Type		char(10),
	 Value		char(20) null,
	 Maxdumps	char(7),
	 Dump_Count	char(3) null,
	 Page_Cache	char(7),
	 Proc_Cache	char(7),
	 Unused_Space	char(7),
	 Halt		char(7),
	 Cluster	char(7),
	 Est_File_Size	varchar(8), 
	 Filename	varchar(30),
	 Directory	varchar(255))

/*
** Cursor to return all dump condition rows, ordered by object type
** (attribute)
*/
declare c_conditions cursor
	for select an.name, sa.attribute, sa.object
	from master.dbo.sysattributes sa, #attname an
	where sa.class = @DUMPCOND_CLASS
	and sa.object_type = @OBJTYPE
	and sa.attribute = an.attrib
	and sa.object_info1 = @CFG_PRIMARY
	order by sa.attribute

/*
** Cursor to return all settings for a given dump condition
*/
declare c_settings cursor
	for select sa.object_info1, sa.int_value, sa.char_value
	from master.dbo.sysattributes sa
	where sa.class = @DUMPCOND_CLASS
	and sa.object_type = @OBJTYPE
	and sa.attribute = @cond_attrib
	and sa.object = @cond_value
	and sa.object_info1 != @CFG_PRIMARY

/*
** Cursor to read the #conditions table and display the contents.
*/
declare c_display cursor
	for select Type, Value, Maxdumps, Dump_Count,
		Page_Cache, Proc_Cache, Unused_Space,
		Halt, Cluster, Est_File_Size, Filename, Directory
	from #conditions
	order by order_num

/* ----------------- Setup and Validation ------------------------ */
set nocount on

/*
**  Common Definition Section: Note: any changes made to the following
**  values must also be made in shmdumpdrop and shmdumpconfig
*/

/*
** Class ID and type defined in utils/attrib.lst
*/
select @DUMPCOND_CLASS 	= 7
select @OBJTYPE		= "DC"

/*
** The following constants define record types for the dump condition
** class in the sysattributes table.The values set here must be the 
** same as those defined in utils/cfgdump.c.
*/
select @CFG_PRIMARY 	= 1
select @CFG_FILENAME 	= 2
select @CFG_DIRNAME 	= 3
select @CFG_MAXDUMPS 	= 4
select @CFG_PAGECACHE 	= 5
select @CFG_PROCCACHE 	= 6
select @CFG_UNUSED 	= 7
select @CFG_HALT	= 8
select @CFG_CLUSTER	= 9

/*
** The following constants define record types for the dump condition
** class in the sysattributes table for the config records. The values
** set here must be the same as those defined in utils/shmdump.c.
*/
select @CFG_ATTRIBUTE	= 0
select @CFG_ERRORLOG    = 1
select @CFG_MERGE       = 2

/*
** The following constants are used for setting memory modes and other
** options.  These values must correspond to those used in utils/cfgdump.c.
*/
select @CFG_DEFAULT	= 0			/* Use the default value */
select @CFG_INCLUDE	= 1			/* Include memory / Option On */
select @CFG_OMIT	= 2			/* Omit memory / Option off */

/*
** The following must correspond to values in sysattr.h
*/
select @ATTR_ADD 	= 1
select @ATTR_CHANGE	= 2
select @ATTR_DROP	= 3
select @ATTR_FETCH	= 4

/*
** Determine if we are running on the windows platform
*/
if (select charindex("NT (IX86)", @@version)) > 0
begin
	select @windows = 1
end
else
begin
	select @windows = 0
end


/*
** End Common Definition Section
*/

/* ----------------- Identify and Perform the Command ----------- */

select @defaults_found = 0
select @header_printed = 0

/*
** Create table #attname (attrib int, name char(25))
** NOTE: The atribute values must correspond to those defined
** in utils/attrib.lst.
*/
insert #attname values (1, 'Error   ')
insert #attname values (2, 'Signal  ')
insert #attname values (3, 'Severity')
insert #attname values (4, 'Module  ')
insert #attname values (5, 'Defaults')
insert #attname values (6, 'Timeslice')
insert #attname values (7, 'Panic')
insert #attname values (8, 'Message')
insert #attname values (9, 'Dbcc')
insert #attname values (10, 'Codepoint')

/*
** Open curson to select all dump conditions
*/
open c_conditions

fetch c_conditions into @cond_name, @cond_attrib, @cond_value

if (@@sqlstatus = 1)
begin
	/*
	** 18511, "Error reading sysattributes table"
	*/
	raiserror 18511
	return 1
end

select @cmaxdumps 	= "Default"
select @cpagecache 	= "Default"
select @cproccache 	= "Default"
select @cunused 	= "Default"
select @chalt		= "Default"
select @cfilename	= "Default File Name"
select @cdirname	= "Default Directory"
select @dumpcount	= ""
select @cluster		= "Default"

while (@@sqlstatus = 0)
begin
	/*
	** Fetch all special settings for the current
	** dump condition
	*/
	open c_settings

	fetch c_settings into @rectype, @int_val, @char_val

	/*
	** There is no dump count for the Defaults condition
	*/
	if (@cond_name != "Defaults")
	begin
		select @dumpcount = convert(char(3),
					shmdumpcount(rtrim(@cond_name),
						@cond_value))
	end
	else
	begin
		select @dumpcount = "  0"
	end

	while (@@sqlstatus = 0)
	begin
		if (@rectype = @CFG_MAXDUMPS)
		begin
			select @cmaxdumps = convert(char(7), @int_val)
		end
		else if (@rectype = @CFG_PAGECACHE)
		begin
			if (@int_val = 1)
				select @cpagecache = 'Include'
			else
				select @cpagecache = 'Omit   '
		end
		else if (@rectype = @CFG_PROCCACHE)
		begin
			if (@int_val = 1)
				select @cproccache = 'Include'
			else
				select @cproccache = 'Omit   '
		end
		else if (@rectype = @CFG_UNUSED)
		begin
			if (@int_val = 1)
				select @cunused = 'Include'
			else
				select @cunused = 'Omit   '
		end
		else if (@rectype = @CFG_HALT)
		begin
			if (@int_val = 1)
				select @chalt = 'Halt   '
			else
				select @chalt = 'No Halt'
		end
		else if (@rectype = @CFG_DIRNAME)
		begin
			select @cdirname = @char_val
		end
		else if (@rectype = @CFG_FILENAME)
		begin
			select @cfilename = @char_val
		end
		else if (@rectype = @CFG_CLUSTER)
		begin
			if (@int_val = 1)
				select @cluster = 'All'
			else
				select @cluster = 'Local  '
		end
		else
		begin
			/*
			** 18512, "WARNING: Unknown dump condition record type found: %1!"
			*/
			raiserror 18512, @rectype
		end

		fetch c_settings 
			into @rectype, @int_val, @char_val
	end /* while (@@sqlstatus = 0) */

	/*
	** Close cursor on settings for current condition
	*/
	close c_settings

	select @cond_cvalue = convert(char(20), @cond_value)

	/*
	** Handle the system default settings separately.
	*/
	if (@cond_attrib = 5)
	begin
display_defaults:
		select @defaults_found = 1

		if (@header_printed = 1)
		begin
			print " "
		end

		/*
		** If the following values are not set by
		** records in the sysattributes table, report
		** the built in system defaults that we know will
		** be enforced at dump time (csmd_dump_condition)
		** using values hard-coded in the software.
		*/
		if (@cmaxdumps = 'Default')
		begin
			select @cmaxdumps = '1      '
		end
		select @dmaxdumps = @cmaxdumps

		if (@cpagecache = 'Default')
		begin
			select @cpagecache = 'Omit   '
		end
		select @dpagecache = @cpagecache

		if (@cproccache = 'Default')
		begin
			select @cproccache = 'Include'
		end
		select @dproccache = @cproccache

		if (@cunused = 'Default')
		begin
			select @cunused = 'Omit   '
		end
		select @dunused = @cunused

		if (@chalt = 'Default')
		begin
			select @chalt = 'Halt   '
		end
		select @dhalt = @chalt

		if (@cfilename = 'Default File Name')
		begin
			select @cfilename = 'Generated File Name'
		end
		select @dfilename = @cfilename

		if (@cdirname = 'Default Directory')
		begin
			select @cdirname = '$SYBASE'
		end
		select @ddirname = @cdirname

		if (@cluster = 'Default')
		begin
			select @cluster = 'Local  '
		end
		select @dcluster = @cluster

		select @dumpcount = "---"

		/*
		** Make sure that default settings display last in
		** the output.
		*/
		select @order_number = 9999
	end
	else /* (@cond_attrib = 5) */
	begin
		/*
		** Group dump conditions by condition type
		*/
		select @order_number = @cond_attrib
	end /* (@cond_attrib = 5) */

	/*
	** The value column is not applicable to the
	** system defaults, timeslice or panic
	*/
	if (@cond_attrib in (5, 6, 7, 9))
	begin
		select @cond_cvalue = '---  '
	end

	/*
	** Calculate the estimated dump file size
	*/
	exec sp_shmdumpsize @cpagecache, @cproccache, @dumpsize output

	/*
	** Convert @dumpsize to varchar and append the units specification to
	** the string
	*/
	select @cdumpsize = (convert(varchar(5), @dumpsize) + " " + "MB")

	/*
	** Insert data for curent condition into worktable for 
	** display later.
	*/
	insert #conditions 
		values (@order_number,
			@cond_name,
			@cond_cvalue,
			@cmaxdumps,
			@dumpcount,
			@cpagecache,
			@cproccache,
			@cunused,
			@chalt,
			@cluster,
			@cdumpsize,
			@cfilename,
			@cdirname)

	/*
	** Fetch next dump condition
	*/
	fetch c_conditions into @cond_name, @cond_attrib, @cond_value

	/*
	** Set to default values
	*/
	select @cmaxdumps 	= "Default"
	select @cpagecache 	= "Default"
	select @cproccache 	= "Default"
	select @cunused 	= "Default"
	select @chalt		= "Default"
	select @cfilename	= "Default File Name"
	select @cdirname	= "Default Directory"
	select @dumpcount	= ""
	select @cluster		= "Default"
end /* while (@@sqlstatus = 0) */

/*
** If we didn't find a defaults record, go back and display default
** values anyway. This is as bit of a kludge, but it will work as long
** as the goto statement is executed before the close cursor
** statement that follows.
*/
if (@defaults_found = 0)
begin
	/*
	** There is no entry for the default settings in the
	** sysattributes table.  Display the system defaults 
	** that are defined in the server.
	*/
	select @cond_name 	= 'Defaults'
	select @cmaxdumps 	= '1      '
	if (@windows = 1)
	begin
		select @cdirname = "%%SYBASE%%"
	end
	else
	begin
		select @cdirname = "$SYBASE"
	end
	select @cond_attrib = 5
	goto display_defaults
end

/*
** Close cursor on dump conditions
*/
close c_conditions

/*
** Now actually display the settings
*/

/*
** Display a list of configured dump conditions
*/
print ""
print "Configured Shared Memory Dump Conditions"
print "----------------------------------------"
print ""

open c_display

fetch c_display into 
	@cond_name,
	@cond_cvalue,
	@cmaxdumps,
	@dumpcount,
	@cpagecache,
	@cproccache,
	@cunused,
	@chalt,
	@cluster,
	@cdumpsize,
	@cfilename,
	@cdirname

while (@@sqlstatus = 0)
begin
		if (@windows = 1 and @cond_name = "Signal")
		begin
			select @rptline = space(2) + "Exception" + space(1) + 
				"0x" + inttohex(convert(int, @cond_cvalue))
		end
		else
		begin
			select @rptline = space(2) + @cond_name + space(1) + @cond_cvalue
		end
		print @rptline

		if (@cond_name = "Message")
		begin
			select @print_str = space(4) + 
					"Message Text:" + space(11) + 
					str_replace(ssel_message(convert(int,
						 @cond_cvalue)), "%", "%%")
			print @print_str
		end
		else if (@cond_name = "Error")
		begin
			if (@@langid = 0)
			begin
				select @print_str = space(4) + "Error Text" 
					+ space(14) +
					str_replace(description, "%", "%%")
					from master.dbo.sysmessages where
					error = convert(int, @cond_cvalue)
					and langid is NULL
			end
			else
			begin
				select @print_str = space(4) + "Error Text" 
					+ space(14) +
					str_replace(description, "%", "%%")
					from master.dbo.sysmessages where
					error = convert(int, @cond_cvalue)
					and langid = @@langid
			end
			print @print_str
		end

		select @rptline = space(4) + "Maximum Dumps:" + 
							space(10) + @cmaxdumps
		if (@cond_name != "Defaults" and @cmaxdumps = "Default")
			select @rptline = @rptline + " (" + rtrim(@dmaxdumps) + ")" 
		print @rptline

		if (@cond_name != "Defaults")
		begin
			select @rptline = space(4) + "Dumps since boot:" + 
							space(7) + @dumpcount
			print @rptline
		end

		select @rptline = space(4) + "Halt Engines:" + 
							space(11) + @chalt
		if (@cond_name != "Defaults" and @chalt = "Default")
			select @rptline = @rptline + " (" + rtrim(@dhalt) + ")" 
		print @rptline

		select @rptline = space(4) + "Cluster:" + 
							space(16) + @cluster
		if (@cond_name != "Defaults" and @cluster = "Default")
			select @rptline = @rptline + " (" + rtrim(@dcluster) + ")" 
		print @rptline

		select @rptline = space(4) + "Page Cache:" +
							space(13) + @cpagecache
		if (@cond_name != "Defaults" and @cpagecache = "Default")
			select @rptline = @rptline + " (" + rtrim(@dpagecache) + ")" 
		print @rptline

		select @rptline = space(4) + "Procedure Cache:" +
							space(8) + @cproccache
		if (@cond_name != "Defaults" and @cproccache = "Default")
			select @rptline = @rptline + " (" + rtrim(@dproccache) + ")" 
		print @rptline

		select @rptline = space(4) + "Unused Space:" +
							space(11) + @cunused
		if (@cond_name != "Defaults" and @cunused = "Default")
			select @rptline = @rptline + " (" + rtrim(@dunused) + ")" 
		print @rptline

		select @rptline = space(4) + "Dump Directory:" + 
							space(9) + @cdirname
		if (@cond_name != "Defaults" and @cdirname = "Default Directory")
			select @rptline = @rptline + " (" + rtrim(@ddirname) + ")" 
		print @rptline

		select @rptline = space(4) + "Dump File Name:" +
							space(9) + @cfilename
		if (@cond_name != "Defaults" and @cfilename = "Default File Name")
			select @rptline = @rptline + " (" + rtrim(@dfilename) + ")" 
		print @rptline

		select @rptline = space(4) + "Estimated File Size:" +
							space(4) + @cdumpsize
		print @rptline

		print ""

		fetch c_display into 
			@cond_name,
			@cond_cvalue,
			@cmaxdumps,
			@dumpcount,
			@cpagecache,
			@cproccache,
			@cunused,
			@chalt,
			@cluster,
			@cdumpsize,
			@cfilename,
			@cdirname
end

close c_display

/*
** Get configured maximum number of dump conditions
*/
select @maxconds = value
	from master.dbo.sysconfigures
	where name = 'maximum dump conditions'

/*
** Subtract 1 so that we don't count the defaults record
*/
select @curcount = (count(*) - 1) 
	from #conditions

/*
** 18513, "Current number of conditions: %1!"
*/
exec sp_getmessage 18513, @print_str output
print @print_str, @curcount
/*
** 18514, "Maximum number of conditions: %1!"
*/
exec sp_getmessage 18514, @print_str output
print @print_str, @maxconds

/*
** Display CSMD-related configuration options.
*/
print ""
print "Configurable Shared Memory Dump Configuration Settings"
print "------------------------------------------------------"

select @cfgval = value
	from master.dbo.sysconfigures
	where name = 'dump on conditions'

/*
** 19399, "Dump on conditions: %1!"
*/
exec sp_getmessage 19399, @print_str output
print @print_str, @cfgval

if (@cfgval = 0)
begin
	/*
	** 19400, "You must run 'sp_configure 'dump on conditions',1' to
	**		enable the shared memory dump facility."
	*/
	exec sp_getmessage 19400, @print_str output
	print ""
	print @print_str
	print ""
end

select @cfgval = value
	from master.dbo.sysconfigures
	where name = 'number of dump threads'

/*
** 19398, "Number of dump threads: %1!"
*/
exec sp_getmessage 19398, @print_str output
print @print_str, @cfgval

/*
** Determine include errorlog setting.  Set the @cfgval variable
** to the default setting in the event there is no configuration row in
** sysattributes.  This must be the same default as in utils/shmdump.c.
*/
select @cfgval = 1
select @cfgval = int_value
	from master.dbo.sysattributes
	where class = @DUMPCOND_CLASS
	and object_type = @OBJTYPE
	and attribute = @CFG_ATTRIBUTE
	and object = @CFG_ERRORLOG

/*
** 19396, "Include errorlog in dump file: %1!"
*/
exec sp_getmessage 19396, @print_str output
print @print_str, @cfgval

/*
** Determine merge files setting.  Set the @cfgval variable
** to the default setting in the event there is no configuration row in
** sysattributes.  This must be the same default as in utils/shmdump.c.
*/
select @cfgval = 1
select @cfgval = int_value
	from master.dbo.sysattributes
	where class = @DUMPCOND_CLASS
	and object_type = @OBJTYPE
	and attribute = @CFG_ATTRIBUTE
	and object = @CFG_MERGE

/*
** 19397, "Merge parallel files after dump: %1!"
*/
exec sp_getmessage 19397, @print_str output
print @print_str, @cfgval


/*
** Calculate server memory usage
*/

select @cache_size = 0
select @proc_size = 0

/*
** Obtain the current total memory allocated to the server. 104 is the
** configuration # for total logical memory.
*/
select @memory = convert(int, comment)
        from master.dbo.syscurconfigs
        where config    = 104

select @memory = (@memory / 1024) + 1

select @memory_str = convert(char(6), @memory)
select @position = charindex(" ", @memory_str)
select @memory_str = space(6 - @position) + rtrim(@memory_str) + " MB"

/*
** 19 is the config # for named caches.
** This value is in kilobytes.
*/
select @cache_size = sum(cu.value)
        from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
        where co.config = 19
        and co.config   = cu.config
        and co.name     = cu.comment

select @cache_size_str = convert(char(6), (@cache_size / 1024) + 1)
select @position = charindex(" ", @cache_size_str)
select @cache_size_str = space(6 - @position) + rtrim(@cache_size_str) + " MB"

/*
** Config # 146 is the procedure cache size value.
** Config # 414 is the statement cache size value.
** Since statement cache is added to the configured procedure cache
** size, these two values must be combined to calculate the total
** procedure cache size.
*/
select @proc_size = sum(convert(int, comment))
        from master.dbo.syscurconfigs
        where config in (146, 414)

select @proc_size_str = convert (char(6), (@proc_size / 1024) + 1)
select @position = charindex(" ", @proc_size_str)
select @proc_size_str =space(6 - @position) + rtrim(@proc_size_str) + " MB"

select @shm_size_str =  convert(char(6), @memory - (((@cache_size / 1024)) + (@proc_size / 1024)))
select @position = charindex(" ", @shm_size_str)
select @shm_size_str = space(6 - @position) + rtrim(@shm_size_str) + " MB"

print ""
print "Server Memory Allocation"
print "Procedure Cache  Data Caches  Server Memory  Total Memory"
print "---------------  -----------  -------------  ------------"
print "       %1!    %2!      %3!     %4!",
	@proc_size_str, @cache_size_str, @shm_size_str, @memory_str

if (@type = 'debug')
begin
	print " "
	/*
	** Printing Debug Information:
	*/
	exec sp_getmessage 18515, @print_str output
	print @print_str
	print " "
	select @not_status = attrib_notify(@DUMPCOND_CLASS, 1, @OBJTYPE,
					1, NULL,
					NULL, NULL, NULL, NULL,
					NULL, NULL, NULL, NULL,
					@ATTR_FETCH)
end

/*
** Indicate success
*/
return 0

/*
** End sp_shmdumpdisp
*/
go
exec sp_procxmode 'sp_shmdumpdisp', 'anymode'
go
grant execute on sp_shmdumpdisp to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_shmdumpconfig_config')
begin
	drop procedure sp_shmdumpconfig_config
end
go
print "Installing sp_shmdumpconfig_config"
go

/*
** SP_SHMDUMPCONFIG_CONFIG
**
** This file contains the definition of the sp_shmdumpconfig_config system
** stored procedure.  This stored procedure is used to set "global" shared
** memory dump configuration options (these are options not specified on a
** per-condition basis. The sa_role is required to make any changes to the
** system configuration.
**
** Security: The sa_role role is required in order to execute this
** stored procedure
**
** History:
** 06apr05	dwein		Initial coding
*/

create procedure sp_shmdumpconfig_config
/* -------------- Stored Procedure Parameters ----------------------- */
@option 	varchar(20)	,/* config option requested by user   */
@value 		int		 /* new value for config option	      */

as

/* ----------------- Declare Local Variables ------------------------ */
declare @cfgitem	int, 		/* configuration option	      */
	@not_status 	int,		/* notification return status */
	@ret_value	int		/* return value */

/*
** The following variables are treated as constants within this
** stored procedure. They are set below.
*/
declare @DUMPCOND_CLASS	int,		/* sysattributes class		*/
	@OBJTYPE	char(2),	/* sysattributes object type	*/
	@ATTRIB		int,		/* attribute column value	*/
	@CFG_ERRORLOG	int,		/* include errorlog record id	*/
	@CFG_MERGE	int,		/* merge pll dump record id	*/
	@ATTR_ADD	int,		/* add notification value	*/
	@ATTR_CHANGE	int,		/* change notification value	*/
	@ATTR_DROP	int,		/* drop notification value	*/
	@ATTR_FETCH	int		/* fetch notification value	*/


/* ----------------- Setup and Validation ------------------------ */
set nocount on

/*
** Verify that the user has sufficient permissions to
** update the dump configuration
*/
if (proc_role("sa_role") < 1)
begin
	return 1
end

/*
** Class ID and type defined in utils/attrib.lst
*/
select @DUMPCOND_CLASS 	= 7
select @OBJTYPE		= "DC"
select @ATTRIB		= 0

/*
** The following constants define record types for the dump condition
** class in the sysattributes table for the config records. The values 
** set here must be the same as those defined in utils/shmdump.c.
*/
select @CFG_ERRORLOG 	= 1
select @CFG_MERGE	= 2

/*
** The following must correspond to values in sysattr.h
*/
select @ATTR_ADD 	= 1
select @ATTR_CHANGE	= 2
select @ATTR_DROP	= 3
select @ATTR_FETCH	= 4

select @ret_value = 0

/* Validate the config option */
if (@option = "merge files")
begin
	select @cfgitem = @CFG_MERGE
end
else if @option = "include errorlog"
begin
	select @cfgitem = @CFG_ERRORLOG
end
else if @option is NULL
begin
	goto usage
end
else
begin
	/* 
	** 19401, "Invalid dump configuration option: '%1!'"
	*/
	raiserror 19401, @option
	select @ret_value = 2
	goto usage
end

/* Validate the value against the config option */
if (@cfgitem in (@CFG_MERGE, @CFG_ERRORLOG))
begin
	/* valid values are 0 or 1 */
	if (@value not in (0, 1))
	begin
		/* 
		** 19402, "Invalid configuration value '%1!' for option '%2!'"
		*/
		raiserror 19402, @value, @option
		select @ret_value = 3 
		goto usage
	end
end

begin tran update_dump_config

/*
** The sysattributes rows that represent this configuration options
** do not exist until a user explicitly configures an option.  Prior
** to that point ASE will use a hard coded default.  This procedure
** needs to determine if it will be creating the row for the first
** time, or if it will be updating an existing row
*/
if exists (select * from master.dbo.sysattributes
		where class = @DUMPCOND_CLASS
		and attribute = @ATTRIB
		and object = @cfgitem)
begin
	/* the row already exists, update it */
	update master.dbo.sysattributes 
		set int_value = @value
		where class = @DUMPCOND_CLASS
		and attribute = @ATTRIB
		and object = @cfgitem
end
else
begin
	/* insert the new row */
	insert master.dbo.sysattributes
		(class, attribute, object_type, object, int_value)
		values
		(@DUMPCOND_CLASS, @ATTRIB, @OBJTYPE,
			@cfgitem, @value)
end

if (@@error = 0)
begin
	select @not_status
		= attrib_notify(@DUMPCOND_CLASS,/*cl*/
				@ATTRIB, 	/*attrib*/
				@OBJTYPE,   /*type*/ 
				@cfgitem, 	/*object*/
				NULL,		/*info1*/
				NULL, 		/*info2*/
				NULL, 		/*info3*/
				NULL, 		/*cinfo*/
				@value,		/*intval*/
				NULL,	 	/*charval*/
				NULL, 		/*textval*/
				NULL, 		/*imageval*/
				NULL,		/*comment*/
				@ATTR_CHANGE)

	if (@not_status = 0)
	begin
		/*
		** 18510, "Notification failed. Your change did not take affect."
		*/
		raiserror 18510
		rollback tran update_dump_config
		return 3
	end
end
else
begin
	/* we had an error either inserting into or updating sysattributes */
	rollback tran update_dump_config
	return 4
end

/*
** Delete of rows and notification were successful.
** Commit transaction.
*/
commit tran uppdate_dump_config

/*
** Indicate success
*/
return 0

usage:
print ""
print "Valid CSMD configuration options:"
print "---------------------------------"
print "  'include errorlog', 0 | 1  (include the ASE errorlog in the dump file)"
print "  'merge files', 0 | 1  (merge dump files after a parellel dump)"
print ""

return @ret_value

/*
** End sp_shmdumpconfig_config
*/
go
exec sp_procxmode 'sp_shmdumpconfig_config', 'anymode'
go
grant execute on sp_shmdumpconfig_config to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_shmdumpconfig')
begin
	drop procedure sp_shmdumpconfig
end
go
print "Installing sp_shmdumpconfig"
go

/*
** SP_SHMDUMPCONFIG
**
** This file contains the definition of the sp_dumpconfig system
** stored procedure.  This stored procedure is used to set shared
** memory dump conditions and to display the current dump condition
** settings.  The sa_role is required to make any changes to the
** system configuration, but public access is granted to display the
** current settings.
**
** This stored procedure calls sp_shmdumpdrop to drop shared memory
** dump conditions; and it calls sp_shmdumpdisp to display current
** settings.
**
** Security: The sa_role role is required in order to add a dump condition.
** The sa_role role is required by sp_shmdumpdrop to drop a dump
** condition.
**
** History:
** 19sept96	pdorfman	Initial coding
** 07apr97	pdorfman	Code complete
** 21jan02	dwein		Added support for message dump type
** 20jun03	panchaks	Added support for dbcc dump type
** 12dec03	dwein		Added support for the halt / no_halt option
*/

create procedure sp_shmdumpconfig
/* -------------- Stored Procedure Parameters ----------------------- */
@action 	varchar(10) = "display",/* action requested by user   */
@type 		varchar(20) 	= "",	/* type of attribute affected */
@value 		int		= NULL,	/* attribute value            */
@maxdumps 	int 		= NULL,	/* maximum # of dumps         */
@dirname	varchar(255)	= NULL,	/* dump directory             */
@filename	varchar(128)	= NULL,	/* dump file name.  Maximum   */
					/* length is 30 but declare   */
					/* longer here to avoid       */
					/* truncation                 */
@optarg1	varchar(20)	= NULL,	/* in/exclude memory type or option     */
@optarg2	varchar(20)	= NULL,	/* in/exclude memory type or option     */
@optarg3	varchar(20)	= NULL,	/* in/exclude memory type or option     */
@optarg4	varchar(20)	= NULL,	/* in/exclude memory type or option     */
@optarg5	varchar(20)	= NULL	/* in/exclude memory type or option     */
as

/* ----------------- Declare Local Variables ------------------------ */
declare @object		int, 		/* object column value        */
	@attrib   	int,		/* attribute column value     */
	@not_status 	int,		/* notification return status */
	@curarg		varchar(20),	/* memory mode working var    */
	@opttype	int,		/* type of memory for obj     */
	@optsetting	int,		/* setting for this memtype   */
	@counter	int,		/* counter                    */
	@recfound	int,		/* record already exists      */
	@notify_cnt	int,		/* count notification done    */
	@maxconds	int,		/* max # dump conditions      */
	@curcount	int,		/* current # dump cond's      */
	@trancount	int,		/* receiver for @@trancount   */
	@print_str	varchar(1024),	/* Buffer for messages        */
	@windows	int,		/* indicates if this is the windows platform */
	@hvalue		char(8),	/* value as a hex number      */
	@temp_maxdumps	int		/* used to check maxdumps     */

/*
** The following variables are treated as constants within this
** stored procedure. They are set below.
*/
declare @DUMPCOND_CLASS	int,		/* sysattributes class        */
	@OBJTYPE	char(2),	/* sysattributes object typ   */
	@CFG_PRIMARY	int,		/* primary record id          */
	@CFG_FILENAME	int,		/* file name record id        */
	@CFG_DIRNAME	int,		/* directory name record id   */
	@CFG_MAXDUMPS	int,		/* maxdumps record id         */
	@CFG_PAGECACHE	int,		/* page cache record id       */
	@CFG_PROCCACHE	int,		/* proc cache record id       */
	@CFG_UNUSED	int,		/* unused memory record id    */
	@CFG_HALT	int,		/* halt option record id	*/
	@ATTR_ADD	int,		/* add notification value     */
	@ATTR_CHANGE	int,		/* change notification val    */
	@ATTR_DROP	int,		/* drop notification value    */
	@ATTR_FETCH	int,		/* fetch notification value   */
	@CFG_INCLUDE	int,		/* include memory type        */
	@CFG_OMIT	int,		/* omit memory type           */
	@CFG_DEFAULT	int,		/* use default mem setting    */
	@CFG_CLUSTER	int		/* behavior of dump in cluster*/

/* ----------------- Setup and Validation ------------------------ */
set nocount on

/*
**  Common Definition Section: Note: any changes made to the following
**  values must also be made in shmdumpdrop and shmdumpdisp
*/

/*
** Class ID and type defined in utils/attrib.lst
*/
select @DUMPCOND_CLASS 	= 7
select @OBJTYPE		= "DC"

/*
** The following constants define record types for the dump condition
** class in the sysattributes table.  The values set here must be the 
** same as those defined in utils/cfgdump.c.
*/
select @CFG_PRIMARY 	= 1
select @CFG_FILENAME 	= 2
select @CFG_DIRNAME 	= 3
select @CFG_MAXDUMPS 	= 4
select @CFG_PAGECACHE 	= 5
select @CFG_PROCCACHE 	= 6
select @CFG_UNUSED	= 7
select @CFG_HALT	= 8
select @CFG_CLUSTER	= 9

/*
** The following constants are used for setting memory modes and other
** options.  These values must correspond to those used in utils/cfgdump.c.
*/
select @CFG_DEFAULT	= 0			/* Use the default value */
select @CFG_INCLUDE	= 1			/* Include memory / Option On */
select @CFG_OMIT	= 2			/* Omit memory / Option off */

/*
** The following must correspond to values in sysattr.h
*/
select @ATTR_ADD 	= 1
select @ATTR_CHANGE	= 2
select @ATTR_DROP	= 3
select @ATTR_FETCH	= 4

/*
** Determine if we are running on the windows platform
*/
if (select charindex("NT (IX86)", @@version)) > 0
begin
	select @windows = 1
end
else
begin
	select @windows = 0
end

/*
** End Common Definition Section
*/

select @notify_cnt 	= 0

/*
** Validate the action value
*/
if (@action not in ('add', 'drop', 'update', 'reset', 
			'display', 'debug', 'config'))
begin
	/*
	** 18516, "Invalid action %1!"
	*/
	raiserror 18516, @action
        return  17
end

/*
** Determine the attribute number for the attribute indicated
** by the @type parameter.
**
** NOTE: The integer values used for @attrib here must correspond to values
** defined in utils/attrib.lst.  Any changes made here must also be made
** in attrib.lst, and vice versa.
*/

if @type = 'error'
        select @attrib = 1
else if @type = 'signal'
        select @attrib = 2
else if (@windows = 1 and @type = 'exception')
	select @attrib = 2 
else if @type = 'severity' 
        select @attrib = 3 
else if @type = 'module'  
        select @attrib = 4 
else if @type = 'defaults' 
        select @attrib = 5 
else if @type = 'timeslice'
	select @attrib = 6
else if @type = 'panic'
	select @attrib = 7
else if @type = 'message'
	select @attrib = 8
else if @type = 'dbcc'
	select @attrib = 9
else if @type = 'codepoint'
	select @attrib = 10
else if @action = 'debug'
begin
	select @action = 'display'
	select @type = 'debug'
end
else if @action not in ('display', 'config')
begin 
	/*
	** We are here because @type does not have a valid value
	** and the @action value is not 'display' or 'config'. 
	** The 'config' option is responsible for validating its own
	** types.  The display option does not have a type flag.
	*/
        /*
        ** 18492, "Invalid dump condition type %1!"
        */
        raiserror 18492, @type
        return 1
end 
 
/* 
** If we are on windows and the user entered the "exception" condition
** then we need to byte-swap the value stored in @value.
*/
if (@windows = 1 and @type = 'exception')
begin
	select @hvalue = inttohex(@value)
	select @hvalue = substring(@hvalue, 7, 2) +
			substring(@hvalue, 5, 2) +
			substring(@hvalue, 3, 2) +
			substring(@hvalue, 1, 2)
	select @value = hextoint(@hvalue)
end

/* ----------------- Identify and Perform the Command ----------- */

/*
** Add a new dump condition or configuration parameter
*/
if (@action in ('add', 'update', 'reset'))
begin
	/*
	** Verify that the user has sufficient permissions to
	** update the dump configuration
	*/
	if (proc_role("sa_role") < 1)
	begin
		return 2
	end

	/*
	** Make sure valid parameters were provided
	*/
	if (@action = 'add')
	begin
		if (@type = 'defaults')
		begin
			/*
			** 18493 "You cannot add the system default settings. Use update."
			*/
			raiserror 18493
			return 3
		end

		if ((@value is NULL) and
		    (@type not in ('timeslice', 'panic', 'dbcc')))
		begin
			/*
			** 18494 "No value for %1! was given."
			*/
			raiserror 18494, @type
			return 4
		end

		/*
		** Determine whether there is room to add another dump condition.
		** Get configured maximum number of dump conditions
		*/
		select @maxconds = value
			from master.dbo.sysconfigures
			where name = 'maximum dump conditions'

		/*
		** Count number of conditions set for type error, signal or module
		*/
		select @curcount = count(*)
			from master.dbo.sysattributes
			where class = @DUMPCOND_CLASS
			and object_info1 = @CFG_PRIMARY
			and attribute != 5 /* Skip default entry */

		/*
		** Raise an error if there is no more room
		*/
		if (@curcount >= @maxconds)
		begin
			/*
			** 18495, "The maximum number of dump conditions (%1!) are already set."
			*/
			raiserror 18495, @maxconds

			/*
			** 18496,  "Either drop a dump condition or increase the value of 'maximum dump conditions'."
			*/
			raiserror 18496
			return 5
		end
	end
	else if (@action != 'reset')
	begin
		/*
		** Make sure that the user has provided arguments for at
		** least one updatable value.
		*/
		if (@maxdumps is NULL and @dirname is NULL and @filename is NULL 
		    and @optarg1 is NULL and @optarg2 is NULL 
		    and @optarg3 is NULL and @optarg4 is NULL
		    and @optarg5 is NULL)
		begin
			/*
			** 18497, "No values to update were given."
			*/
			raiserror 18497
			return 6
		end
	end

	select @object = @value

	/*
	** Determine whether there are currently any records for the
	** the conditions supplied by the user.  This information is
	** used below.
	*/
	if (@type in ('severity', 'defaults', 'timeslice', 'panic', 'dbcc'))
	begin
		if exists (select * from master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib)
		begin
			select @recfound = 1
		end
		else
		begin
			select @recfound = 0
		end
	end
	else
	begin
		if exists (select * from master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
				and object = @object)
		begin
			select @recfound = 1
		end
		else
		begin
			select @recfound = 0
		end
	end

	/*
	** Determine whether action can proceed.  For add, record must
	** not already exist, for update it must exist.
	*/
	if (@action = 'add' and @recfound = 1)
	begin
		if (@type in ('severity', 'defaults', 'timeslice', 
			      'panic', 'dbcc'))
		begin
			/*
			** 18498, "There is already a condition of type %1!"
			*/
			raiserror 18498, @type
		end
		else
		begin
			/*
			** 18499, "There is already a condition of type %1! and value %2!"
			*/
			raiserror 18499, @type, @value
		end
		return 7
	end
	else if (@action = 'update' and @recfound = 0 and @type != 'defaults')
	begin
		if (@type in ('severity', 'timeslice', 'panic', 'dbcc'))
		begin
			/*
			** 18500, "No record found for %1!"
			*/
			raiserror 18500, @type
		end
		else
		begin
			/*
			** 18501, "No record found for %1! %2!"
			*/
			raiserror 18501, @type, @value
		end
		return 8
	end

	/*
	** Validate the dump condition. Signal value cannot be
	** verified, since this is determined by the operating
	** system.  Message value cannot be validated either 
	** since there is no way to look this up. Dbcc type
	** has no value specified.  Codepoint also has no lookup.
	*/
	if (@type = 'error')
	begin
		/*
		** Verify that an row exists for this error number
		** in the master..sysmessages table
		*/
		if not exists (select * from master..sysmessages
					where error = @value)
		begin
			/*
			** 18502, "%1! is not a valid error number"
			*/
			raiserror 18502, @value
			return 9
		end
	end
	else if (@type = 'module')
	begin
		/*
		** Make sure there is at least one error in
		** master..sysmessages that belongs to this module
		*/
		if ((@value % 100 != 0)
		    or not exists (select * from master..sysmessages
					where error between @value
					and @value + 99))
		begin
			/*
			** 18503, "%1! is not a valid module"
			*/
			raiserror 18503, @value
			return 10
		end
	end
	else if (@type = 'severity')
	begin
		/*
		** Minimum severity = 10; maximum severity = 26
		*/
		if (@value < 10 or @value > 26)
		begin
			/*
		`	** 18504, "Severity must be between 10 and 26"
			*/
			raiserror 18504
			return 11
		end

		/*
		** Make sure we have the correct severity value
		*/
		if (@action = 'update')
		begin
			select @object = object
				from master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
		end
	end
	else if (@type = 'defaults')
	begin
		if (@value is not null)
		begin
			/*
			** 18536, "The value parameter must be NULL when setting system defaults."
			*/
			raiserror 18536
			goto error_exit
		end

		/*
		** If there is not a default record, add one.
		*/
		if (@recfound = 0)
		begin
			select @action = 'add'
		end
	end

	/*
	** Reset the dump count for this condition.  This does not require
	** updating the sysattributes table, but a call must be made to
	** attrib_notify() to reset the value.
	*/
	if (@action = 'reset')
	begin
		if (@type = 'defaults')
		begin
			/*
			** 18518,  "You cannot reset the dump count for the default setting."
			*/
			raiserror 18518
			return 12
		end

		/*
		** A non-zero value for info2 for the maxdumps entry
		** indicates that the dump count should be reset.
		*/
		select @not_status 
			= attrib_notify(@DUMPCOND_CLASS,/*cl*/
				@attrib, 	/*attrib */
				@OBJTYPE,    	/*type*/ 
				@object, 	/*object*/
				@CFG_MAXDUMPS,	/*info1*/
				1, 		/*info2*/
				NULL, 		/*info3*/
				NULL, 		/*cinfo*/
				NULL,		/*intval*/
				NULL, 		/*charval*/
				NULL, 		/*textval*/
				NULL, 		/*imageval*/
				NULL,		/*comment*/
				@ATTR_CHANGE)

		if (@not_status = 0)
		begin
			/*
			** 18505, "Notification failed. Condition not set."
			*/
			raiserror 18505
			return 13
		end

		/*
		** 18517, "Dump count reset for %1! %2!"
		*/
		exec sp_getmessage 18517, @print_str output 
		print @print_str, @type, @value  
		return 0
	end

	/*
	** Values have been validated. Begin transaction and
	** insert primary row if needed.
	*/
	begin tran add_condition

	/*
	** For add action, the primary record must first be added. For
	** update, it already exists.
	*/
	if (@action = 'add')
	begin
		/*
		** Insert primary record for new entry in sysattributes 
		** table and invoke the notification routine if insert 
		** is successful.
		*/
		insert master.dbo.sysattributes
			(class, attribute, object_type, object, object_info1)
			values (@DUMPCOND_CLASS, @attrib, @OBJTYPE, @object,
					@CFG_PRIMARY)

		if (@@error = 0)
		begin
			select @not_status = attrib_notify(@DUMPCOND_CLASS, 
						@attrib, @OBJTYPE, 
						@object, @CFG_PRIMARY,
						NULL, NULL, NULL, NULL,
						NULL, NULL, NULL, NULL,
						@ATTR_ADD)

			if (@not_status = 0)
			begin
				/*
				** 18505, "Notification failed. Condition not set."
				*/
				raiserror 18505
				goto error_exit
			end

			select @notify_cnt = @notify_cnt + 1
		end
		else
		begin
			/*
			** 18506, "Insert of new record for %1! %2! failed."
			*/
			raiserror 18506, @type, @value
			goto error_exit
		end
	end

	/*
	** Now insert rows for any additional condition settings
	** that were specified by the user.
	*/
	if (@maxdumps is not NULL)
	begin
		if (@maxdumps <= 0)
		begin
			/*
			** 18519, "The maxdumps parameter value must be greater than zero."
			*/
			raiserror 18519
			goto error_exit
		end

		/*
		** A value of 0 means that the existing maxdumps setting
		** for this condition is being dropped. The sysattributes
		** row is removed and attrib_notify() is called to unset
		** the maxdumps value internally.
		*/
		/*
		** Delete existing entry, if there is one
		*/
		if (@action = 'update'
		    and exists (select * from master.dbo.sysattributes
			where class = @DUMPCOND_CLASS
			and attribute = @attrib
			and object_type = @OBJTYPE
			and object = @object
			and object_info1 = @CFG_MAXDUMPS))
		begin
			delete master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
				and object_type = @OBJTYPE
				and object = @object
				and object_info1 = @CFG_MAXDUMPS
		end

		if (@maxdumps != 0)
		begin
			insert master.dbo.sysattributes
				(class, attribute, object_type, object, 
					object_info1, int_value)
				values(@DUMPCOND_CLASS, @attrib, @OBJTYPE, 
					@object, @CFG_MAXDUMPS, @maxdumps)
		end

		if (@@error = 0)
		begin
			/*
			** info2 must be set to zero to indicate the
			** the maxdumps value should be updated.
			*/
			select @not_status 
				= attrib_notify(@DUMPCOND_CLASS,/*cl*/
					@attrib, 	/*attrib */
					@OBJTYPE,    	/*type*/ 
					@object, 	/*object*/
					@CFG_MAXDUMPS,	/*info1*/
					0, 		/*info2*/
					NULL, 		/*info3*/
					NULL, 		/*cinfo*/
					@maxdumps,	/*intval*/
					NULL, 		/*charval*/
					NULL, 		/*textval*/
					NULL, 		/*imageval*/
					NULL,		/*comment*/
					@ATTR_CHANGE)

			if (@not_status = 0)
			begin
				/*
				** 18505, "Notification failed. Condition not set."
				*/
				raiserror 18505
				goto error_exit
			end

			select @notify_cnt = @notify_cnt + 1
		end
		else
		begin
			goto error_exit
		end

		/*
		** Warn the user that there is a dump file specified
		** for this condition and that setting maxdumps > 1 may
		** lead to dump files being oeverwritten.
		*/
		if (@maxdumps > 1
		     and exists (select *
			from master.dbo.sysattributes
			where class = @DUMPCOND_CLASS
			and attribute = @attrib
			and object_type = @OBJTYPE
			and object = @object
			and object_info1 = @CFG_FILENAME))
		begin
			/*
			** WARNING:  There is a dump file name configured for
			** this dump condition.  Setting maxdumps to a value
			** greater than 1 may cause the dump file to be
			** overwritten if more than one shared memory dump
			** is performed.
			*/
			raiserror 19440
		end
	end

	/*
	** Set dump directory name if specified.  If user supplies a
	** @dirname value of "", drop the current value.
	*/
	if (@dirname is not NULL) 
	begin
		/*
		** Delete existing entry, if there is one
		*/
		if (@action = 'update'
		    and exists (select * from master.dbo.sysattributes
			where class = @DUMPCOND_CLASS
			and attribute = @attrib
			and object_type = @OBJTYPE
			and object = @object
			and object_info1 = @CFG_DIRNAME))
		begin
			delete master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
				and object_type = @OBJTYPE
				and object = @object
				and object_info1 = @CFG_DIRNAME
		end

		/*
		** If user supplies a @dirname value of "", then just
		** drop the current setting but do not insert a new one.
		*/
		if (@dirname != "")
		begin
			insert master.dbo.sysattributes
				(class, attribute, object_type, object, 
					object_info1, char_value)
				values(@DUMPCOND_CLASS, @attrib, @OBJTYPE, 
					@object, @CFG_DIRNAME, @dirname)

			if (@@error = 0)
			begin
				select @not_status 
					= attrib_notify(@DUMPCOND_CLASS,/*cl*/
						@attrib, 	/*attrib*/
						@OBJTYPE,    	/*type*/ 
						@object, 	/*object*/
						@CFG_DIRNAME,	/*info1*/
						NULL, 		/*info2*/
						NULL, 		/*info3*/
						NULL, 		/*cinfo*/
						NULL,		/*intval*/
						@dirname, 	/*charval*/
						NULL, 		/*textval*/
						NULL, 		/*imageval*/
						NULL,		/*comment*/
						@ATTR_CHANGE)

				if (@not_status = 0)
				begin
					/*
					** 18505, "Notification failed. Condition not set."
					*/
					raiserror 18505
					goto error_exit
				end

				select @notify_cnt = @notify_cnt + 1
			end
			else
			begin
				goto error_exit
			end
		end
		else
		begin
			/*
			** Drop the dump directory entry for this
			** condition.
			*/
			if (@@error = 0)
			begin
				select @not_status 
					= attrib_notify(@DUMPCOND_CLASS,/*cl*/
						@attrib, 	/*attrib*/
						@OBJTYPE,    	/*type*/ 
						@object, 	/*object*/
						@CFG_DIRNAME,	/*info1*/
						NULL, 		/*info2*/
						NULL, 		/*info3*/
						NULL, 		/*cinfo*/
						NULL,		/*intval*/
						NULL,	 	/*charval*/
						NULL, 		/*textval*/
						NULL, 		/*imageval*/
						NULL,		/*comment*/
						@ATTR_DROP)

				if (@not_status = 0)
				begin
					/*
					** 18505, "Notification failed. Condition not set."
					*/
					raiserror 18505
					goto error_exit
				end
				select @notify_cnt = @notify_cnt + 1
			end
			else
			begin
				goto error_exit
			end
		end
	end

	/*
	** Set dump file name if specified. Drop the current value if
	** the user supplies a @filename value of "".
	*/
	if (@filename is not NULL) 
	begin
		/*
		** Delete existing entry, if there is one
		*/
		if (@action = 'update'
		    and exists (select * from master.dbo.sysattributes
			where class = @DUMPCOND_CLASS
			and attribute = @attrib
			and object_type = @OBJTYPE
			and object = @object
			and object_info1 = @CFG_FILENAME))
		begin
			delete master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
				and object_type = @OBJTYPE
				and object = @object
				and object_info1 = @CFG_FILENAME
		end

		/*
		** If the user supplies a @filename value of "", drop
		** the current value but do not insert a new one.
		*/
		if (@filename != "")
		begin
			/*
			** Make sure the new file name is not longer than
			** 30 characters
			*/
			if ((select char_length(@filename)) > 30)
			begin
				/*
				** The shared memory dump file name must be 30
				** characters or less in length.
				*/
				raiserror 19441
				goto error_exit
			end

			insert master.dbo.sysattributes
				(class, attribute, object_type, object, 
					object_info1, char_value)
				values(@DUMPCOND_CLASS, @attrib, @OBJTYPE, 
					@object, @CFG_FILENAME, @filename)

			if (@@error = 0)
			begin
				select @not_status 
					= attrib_notify(@DUMPCOND_CLASS,/*cl*/
						@attrib, 	/*attrib */
						@OBJTYPE,    	/*type*/ 
						@object, 	/*object*/
						@CFG_FILENAME,	/*info1*/
						NULL, 		/*info2*/
						NULL, 		/*info3*/
						NULL, 		/*cinfo*/
						NULL,		/*intval*/
						@filename,	/*charval*/
						NULL, 		/*textval*/
						NULL, 		/*imageval*/
						NULL,		/*comment*/
						@ATTR_CHANGE)

				if (@not_status = 0)
				begin
					/*
					** 18505, "Notification failed. Condition not set."
					*/
					raiserror 18505
					goto error_exit
				end
				select @notify_cnt = @notify_cnt + 1
			end
			else
			begin
				goto error_exit
			end

			/*
			** Warn the user that maxdumps is > 1 so using
			** a fixed file name may result in dump files
			** being overwritten but continue processing.
			*/
			select @temp_maxdumps = int_value
				from master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
				and object_type = @OBJTYPE
				and object = @object
				and object_info1 = @CFG_MAXDUMPS

			if (@temp_maxdumps > 1)
			begin
				/*
				** WARNING:  The maxdumps value for this dump
				** condition is greater than 1.  Using a
				** configured file name may cause the dump file
				** to be overwritten if more than one
 				** shared memory dump is performed.
				*/
				raiserror 19439
			end
		end
		else
		begin
			/*
			** Drop the dump file name entry for this
			** condition.
			*/
			if (@@error = 0)
			begin
				select @not_status 
					= attrib_notify(@DUMPCOND_CLASS,/*cl*/
						@attrib, 	/*attrib*/
						@OBJTYPE,    	/*type*/ 
						@object, 	/*object*/
						@CFG_FILENAME,	/*info1*/
						NULL, 		/*info2*/
						NULL, 		/*info3*/
						NULL, 		/*cinfo*/
						NULL,		/*intval*/
						NULL,	 	/*charval*/
						NULL, 		/*textval*/
						NULL, 		/*imageval*/
						NULL,		/*comment*/
						@ATTR_DROP)

				if (@not_status = 0)
				begin
					/*
					** 18505, "Notification failed. Condition not set."
					*/
					raiserror 18505
					goto error_exit
				end
				select @notify_cnt = @notify_cnt + 1
			end
			else
			begin
				goto error_exit
			end
		end
	end

	if (@optarg1 is not NULL or @optarg2 is not NULL or @optarg3 is not NULL
		or @optarg4 is not NULL or @optarg5 is not NULL) 
	begin
		select @counter = 0
		while (@counter < 5)
		begin
			/*
			** Set @curarg to current argument's value
			*/
			if (@counter = 0)
				select @curarg = @optarg1
			else if (@counter = 1)
				select @curarg = @optarg2
			else if (@counter = 2)
				select @curarg = @optarg3
			else if (@counter = 3)
				select @curarg = @optarg4
			else if (@counter = 4)
				select @curarg = @optarg5

			/*
			** If arg is unset, go to next one
			*/
			if (@curarg is NULL)
			begin
				select @counter = @counter + 1
				continue
			end

			/*
			** Determine settings based on user's input
			*/
			if (@curarg = "include_page")
			begin
				select @opttype = @CFG_PAGECACHE
				select @optsetting = @CFG_INCLUDE
			end
			else if (@curarg = "omit_page")
			begin
				select @opttype = @CFG_PAGECACHE
				select @optsetting = @CFG_OMIT
			end
			else if (@curarg = "default_page")
			begin
				select @opttype = @CFG_PAGECACHE
				select @optsetting = @CFG_DEFAULT
			end
			else if (@curarg = "include_proc")
			begin
				select @opttype = @CFG_PROCCACHE
				select @optsetting = @CFG_INCLUDE
			end
			else if (@curarg = "omit_proc")
			begin
				select @opttype = @CFG_PROCCACHE
				select @optsetting = @CFG_OMIT
			end
			else if (@curarg = "default_proc")
			begin
				select @opttype = @CFG_PROCCACHE
				select @optsetting = @CFG_DEFAULT
			end
			else if (@curarg = "include_unused")
			begin
				select @opttype = @CFG_UNUSED
				select @optsetting = @CFG_INCLUDE
			end
			else if (@curarg = "omit_unused")
			begin
				select @opttype = @CFG_UNUSED
				select @optsetting = @CFG_OMIT
			end
			else if (@curarg = "default_unused")
			begin
				select @opttype = @CFG_UNUSED
				select @optsetting = @CFG_DEFAULT
			end
			else if (@curarg = "halt")
			begin
				select @opttype = @CFG_HALT
				select @optsetting = @CFG_INCLUDE
			end
			else if (@curarg = "no_halt")
			begin
				select @opttype = @CFG_HALT
				select @optsetting = @CFG_OMIT
			end
			else if (@curarg = "default_halt")
			begin
				select @opttype = @CFG_HALT
				select @optsetting = @CFG_DEFAULT
			end
			else if (@curarg = "cluster_all")
			begin
				select @opttype = @CFG_CLUSTER
				select @optsetting = @CFG_INCLUDE
			end
			else if (@curarg = "cluster_local")
			begin
				select @opttype = @CFG_CLUSTER
				select @optsetting = @CFG_OMIT
			end
			else if (@curarg = "default_cluster")
			begin
				select @opttype = @CFG_CLUSTER
				select @optsetting = @CFG_DEFAULT
			end
			else
			begin
				/*
				** 18507, "Invalid option mode %1!"
				*/
				raiserror 18507, @curarg
				goto error_exit
			end

			/*
			** Delete existing entry, if there is one
			*/
			if (@action = 'update'
			    and exists (select * from master.dbo.sysattributes
				where class = @DUMPCOND_CLASS
				and attribute = @attrib
				and object_type = @OBJTYPE
				and object = @object
				and object_info1 = @opttype))
			begin
				delete master.dbo.sysattributes
					where class = @DUMPCOND_CLASS
					and attribute = @attrib
					and object_type = @OBJTYPE
					and object = @object
					and object_info1 = @opttype
			end

			/*
			** There is no need to insert a row to set
			** option setting to default. Any previous
			** row should be deleted and the notification
			** function must be called.
			*/
			if (@optsetting != @CFG_DEFAULT)
			begin
				/*
				** Insert row into sysattributes table
				*/
				insert master.dbo.sysattributes
					(class, attribute, object_type, 
						object, object_info1, 
						int_value)
					values(@DUMPCOND_CLASS, @attrib, 
						@OBJTYPE, @object, @opttype,
						@optsetting)

				if (@@error = 0)
				begin
					select @not_status 
						= attrib_notify(
							@DUMPCOND_CLASS,/*cl*/
							@attrib,/*attrib */
							@OBJTYPE,/*type*/ 
							@object,/*object*/
							@opttype,/*info1*/
							NULL, 	/*info2*/
							NULL, 	/*info3*/
							NULL, 	/*cinfo*/
							@optsetting,/*intval*/
							NULL,	/*charval*/
							NULL, 	/*textval*/
							NULL, 	/*imageval*/
							NULL,	/*comment*/
							@ATTR_CHANGE)

					if (@not_status = 0)
					begin
						/*
						** 18505, "Notification failed. Condition not set."
						*/
						raiserror 18505
						goto error_exit
					end
					select @notify_cnt = @notify_cnt + 1
				end
				else
				begin
					goto error_exit
				end
			end
			else
			begin
				/*
				** Drop this option setting for this
				** condition.
				*/
				if (@@error = 0)
				begin
					select @not_status 
						= attrib_notify(
							@DUMPCOND_CLASS,/*cl*/
							@attrib,/*attrib */
							@OBJTYPE,/*type*/ 
							@object,/*object*/
							@opttype,/*info1*/
							NULL, 	/*info2*/
							NULL, 	/*info3*/
							NULL, 	/*cinfo*/
							NULL,	/*intval*/
							NULL,	/*charval*/
							NULL, 	/*textval*/
							NULL, 	/*imageval*/
							NULL,	/*comment*/
							@ATTR_DROP)

					if (@not_status = 0)
					begin
						/*
						** 18505, "Notification failed. Condition not set."
						*/
						raiserror 18505
						goto error_exit
					end
					select @notify_cnt = @notify_cnt + 1
				end
				else
				begin
					goto error_exit
				end
			end

			select @counter = @counter + 1
		end
	end

	/*
	** All rows successfully added for this condition.
	** Commit transaction.
	*/
	commit tran add_condition
end
/*
** Drop a dump condition
*/
else if (@action = 'drop')
begin
	exec sp_shmdumpdrop @type, @value, @attrib
end
/*
** Display current dump condition configuration
*/
else if (@action = 'display')
begin
	exec sp_shmdumpdisp @type
end
/*
** Execute the config action
*/
else if (@action = 'config')
begin
	exec sp_shmdumpconfig_config @type, @value
end

/*
** Indicate success
*/
return 0

/*
** An error occured while inserting rows into the sysattributes table.
** Check to see whether this was an add operation.  If so, remove any in-memory 
** entries added before error occured.  There is a possibility that the
** in-memory data structure will be left in a state that is not consistent
** with the sysattributes table entries.  This would be the case if we were
** performing an update of an existing dump condition and one or more
** rows had been successfully added to sysattributes before the failure
** occured.  In that case, the in-memory table would also have been updated.
** These updates are not transactional and we have no way of restoring them
** to their state prior to the execution of the stored procedure. This
** will only happen in the case of an update operation.  In the case of an 
** add operation, the in-memory entries will be removed by the call to
** attrib_notify() below. To correct this problem, drop and re-add the
** dump condition.
*/
error_exit:

	if (@action = 'add' and @notify_cnt > 0)
	begin
		/*
		** An error occured while adding a new dump
		** condition but the runtime has already been notified.
		** Remove the reference to this condition before
		** returning.
		*/
		select @not_status = attrib_notify(
				@DUMPCOND_CLASS,/*class*/
				@attrib,	/*attrib */
				@OBJTYPE,   	/*type*/ 
				@object,	/*object*/
				@CFG_PRIMARY,	/*info1*/
				NULL, 		/*info2*/
				NULL, 		/*info3*/
				NULL, 		/*cinfo*/
				NULL,		/*intval*/
				NULL,		/*charval*/
				NULL, 		/*textval*/
				NULL, 		/*imageval*/
				NULL,		/*comment*/
				@ATTR_DROP)

		if (@not_status = 0)
		begin
			/*
			** 18505, "Notification failed. Condition not set."
			*/
			raiserror 18505
		end
	end

	/*
	** Rollback any active transaction to undo changes
	** made to the sysattributes table.
	*/
	select @trancount = @@trancount

	if (@trancount > 0)
	begin
		/*
		** Rollback the current transaction
		*/
		rollback tran add_condition
	end

	return 18

/*
** End of sp_shmdumpconfig
*/
go
exec sp_procxmode 'sp_shmdumpconfig', 'anymode'
go
grant execute on sp_shmdumpconfig to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon')
begin
	drop procedure sp_sysmon
end
go
print "Installing sp_sysmon"
go

/*
** Messages for sysmon [Total 4]
** Generated by spgenmsgs.pl on Fri Jun 27 13:30:19 2003
** 
** 18179, "Invalid parameter '%1!'. Usage: sp_sysmon {'begin_sample'|{{'end_sample'|'hh:mm:ss'}[,section]}} [,@applmon={'appl_only'|'appl_and_login'|'no_appl'|'noclear'} [, @filter={cache wizard filter value|'noclear'} [, @dumpcounters={'y'|'n'|'noclear'|NULL} [, @option={'noclear'|NULL}]]]]
** 18532, "%1!: Invalid value for section parameter '%2!'."
** 18534, "Valid values are: 'kernel','wpm','parallel','taskmgmt','appmgmt','esp','housekeeper','monaccess','xactsum','xactmgmt','indexmgmt','mdcache','locks','dcache','pcache','memory','recovery','diskio','netio', 'cache wizard'"
** 19361, "sp_sysmon cannot be executed with the no clear option unless a
** sample interval is specified."
** 19363, "The specified interval is less than the time required to generate the
** baseline (%1! seconds). Please specify a longer sample interval."
** 19362, "It appears that the monitor counters have been cleared by another application since the beginning of the sample period. The sp_sysmon report cannot be run successfully. Please run the sp_sysmon report again ensuring that the monitor counters are not cleared during the sample period."
** 
** End spgenmsgs.pl output.
*/

if ((select object_id("#temp_sysmon_baseline")) is not NULL)
begin
        drop table #temp_sysmon_baseline
end
go

if ((select object_id("#tempmonitors")) is not NULL)
begin
        drop table #tempmonitors
end
go



if ((select object_id("#cachemap")) is not NULL)
begin
        drop table #cachemap
end
go

if ((select object_id("#devicemap")) is not NULL)
begin
        drop table #devicemap
end
go

if ((select object_id("#tempconfigures")) is not NULL)
begin
        drop table #tempconfigures
end
go

if ((select object_id("#pool_detail_per_cache")) is not NULL)
begin
        drop table #pool_detail_per_cache
end
go

if exists(select 1 from tempdb.dbo.sysobjects where name = 'tempcachestats'
								and uid = 1)
begin
	drop table tempdb.dbo.tempcachestats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where name = 'tempbufpoolstats'
								and uid = 1)
begin
	drop table tempdb.dbo.tempbufpoolstats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where name= 'tempobjstats'
								and uid = 1)
begin
	drop table tempdb.dbo.tempobjstats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where name= 'tempcachedobjstats'
								and uid = 1)
begin
	drop table tempdb.dbo.tempcachedobjstats
end
go

create procedure sp_sysmon
  @interval_or_option char(12)="", /* Time interval string, option
				** "begin_sample" or "end_sample"
				*/
  @section char(80)="NULL",	/* Optional section name		*/
  @applmon varchar(14)="no_appl",  /* Parameter to enable/disable
				** application on monitoring or number of top
				** objects to print output in the case of
				** "cache wizard"
				** Valid values are:
				**    "no_appl" - Application monitoring
				**                disabled (default)
				**    "appl_only" - Only applications monitored
				**    "appl_and_login" - Both applications and
				**                       logins monitored
				**    Any valid number
				*/
 @filter varchar(255)="NULL",	/* This parameter will be used only when the
				** section is 'cache wizard'
				*/
 @dumpcounters char(6)="n",
 @option varchar(6) = NULL	/* Accepts a qualifier such as 'noclear' */
as 
declare @CacheID smallint       /* Cache ID to map to buffer_N group */
declare @CacheName varchar(255)  /* Cache Name from cache id lookup */
declare @DiskName varchar(40)   /* Disk Name */
declare @PhysName varchar(127)  /* Physical disk Name from cache id lookup */
declare @grp int                /* For manipulation of the disk group*/
declare @Seconds int            /* Interval converted to seconds */
declare @Stat           int    	/* status from sysconfigures */
declare @RunStat        int     /* status from sysconfigures */
declare @return		int         /* return value */
declare @Cache_Status char(24)  /* cache status */
declare @Cache_Type  char(24)   /* cache type */
declare @ConfigSize  char(24)   /* config size */
declare @RunSize     char(24)   /* run size */
declare @Cfg_Cache_Repl char(24)/* config value of cache replacement policy*/
declare @Run_Cache_Repl char(24)/* run value of cache replacement policy */
declare @msg varchar(255)       /* message variable */
declare @mda_procname char(50)  /* call sp_sysmon_analyze_mda */
declare @rtn_status int         /* hold mda sproc return status codes */
declare @ClrStatTime datetime   /* time monitor counters cleared */
declare @GetStatTime datetime   /* time monitor counters sampled */
declare @blankline char(1)      /* to print blank line */
declare @rptline char(80)       /* formatted stats line for print statement */
declare @sample_time datetime   /* Time when sample was performed */
declare @clockticks int
declare @sample_period varchar(20) /* length of time sample lasted */
declare @section_line char(80)
declare @noclear int            /* whether to operate in noclear mode*/
declare @clear int              /* whether to operate in clear mode*/
declare @counters_cleared datetime /* time counters were cleared */
declare @start_table datetime   /* time baseline table creation started */
declare @end_table datetime     /* time baseline index creation ended */
declare @table_time int         /* time spent creating index */
declare @difference_time int    /* diff betwen interval and table creation */
declare @collect_interval char(12) /* interval parameter passed to collect */
declare @tempdbname varchar(30) /* assigned temporary database */
declare	@system_view	char(16), /* SDC system view */
	@instid		smallint, /* SDC instance ID */
	@outstr		varchar(255), /* for SDC dbcc set_scope */
	@scope		varchar(16)   /* for SDC dbcc set_scope */

declare @header_printed int             /* report header printed indicator */
declare @i      int             /* loop counter */
declare @active_instances int           /* SDC active instance # */
declare @active_instance_num int        /* counter for SDC active instance */
declare @instancename varchar(30)       /* instance name */

select @section_line = "==============================================================================="
select @blankline = " "

/* If no interval or option was passed, display usage */
if (@interval_or_option = "")
 begin
	  	raiserror 18179, @interval_or_option
        	return 1
 end

/*
** Determine whether to operate in clear or noclear mode.
** Any parameter except for @interval_or_option can specify the
** these options, so each parameter needs to be checked.
** If the clear or noclear option was specified, reset the
** parameter to its default value if appropriate.
*/
select @noclear = 0
select @clear = 0

if (@section = 'noclear')
begin
	select @noclear = 1
	select @section = "NULL"
end
else if (@applmon = 'noclear')
begin
	select @noclear = 1
	select @applmon = 'no_appl'
end
else if (@filter = 'noclear')
begin
	select @noclear = 1
	select @filter = "NULL"
end
else if (@option = 'noclear')
begin
	select @noclear = 1
end
else if (@dumpcounters = 'noclear')
begin
	select @noclear = 1
end

if (@section = 'clear')
begin
	select @clear = 1
	select @section = "NULL"
end
else if (@applmon = 'clear')
begin
	select @clear = 1
	select @applmon = 'no_appl'
end
else if (@filter = 'clear')
begin
	select @clear = 1
	select @filter = "NULL"
end
else if (@option = 'clear')
begin
	select @clear = 1
end
else if (@dumpcounters = 'clear')
begin
	select @clear = 1
end

select @header_printed = 0

/*
** Verify that at most one of clear and noclear options has
** been specified. 
*/
if (@noclear = 1 and @clear = 1)
begin
	/*
	** Invalid parameters.  Both noclear and clear cannot be specified
	** at the same time.
	*/
	raiserror 19449
	return 1
end

if (@interval_or_option = 'begin_sample'
	  	or @interval_or_option = 'end_sample')
begin
	/*
	** If begin_sample or end_sample are specified then we
	** must clear the counters.  Make sure that the noclear
	** option was not specified and set the mode to clear if
	** it was not.
	*/
	if (@noclear = 1)
	begin
		/*
		** sp_sysmon cannot be executed with the no clear option unless
		** a sample interval is specified.
		*/
		raiserror 19361
		return 1
	end

	select @clear = 1
end

/*
** If we have gotten this far and neither clear nor noclear were
** specified, set the mode to noclear by default
*/
if (@noclear = 0 and @clear = 0)
begin
	select @noclear = 1
end

/*
** Validate the value of section
*/
if (@interval_or_option = "begin_sample" and @section != "NULL")
 begin
	raiserror 18546 @msg,"sp_sysmon",@section
 end

if (@section not in ("kernel","wpm","parallel","taskmgmt","appmgmt","esp","housekeeper","monaccess","xactsum","xactmgmt","indexmgmt","mdcache","locks","dcache","pcache","memory","recovery","diskio","netio","repagent","cache wizard","NULL"))
begin
		raiserror 18532 @msg,"sp_sysmon",@section
		raiserror 18534 @msg,"sp_sysmon"
                return 1
end

/* determine command scope: instance or clusterwide */

	select @system_view = NULL
	select @instid = NULL
	select @scope = NULL
	select @active_instances = 1
	select @instancename = @@servername




/*
** Operating in noclear mode. Enable monitor counters and create 
** baseline table to save monitor counter values from start of session.  
** When not in noclear mode the counters are cleared and enabled in
** sp_sysmon_collect.
*/
create table #temp_sysmon_baseline (
		group_name  char(25),
		field_id    smallint,
		value       bigint

		)

if (@noclear = 1)
begin
	dbcc monitor("sample", "all", "on")
	dbcc monitor("sample", "spinlock_s", "on")
	if (@applmon != "no_appl")
	begin
		dbcc monitor("sample", "appl", "on")
	end

	dbcc monitor("select", "all", "on")
	dbcc monitor("select", "spinlock_s", "on")
	if (@applmon != "no_appl")
	begin
		dbcc monitor("select", "appl", "on")
	end

	dump tran tempdb with truncate_only

	/*
 	** If assigned temporary database is different than system
	** tempdb, then dump that one as well.
	*/
	select @tempdbname = db_name(@@tempdbid)
	if (@tempdbname != "tempdb")
	begin
		dump tran @tempdbname with truncate_only
	end

	/*
	** Measure table creation time and subtract
	** this from the time interval specified by the user.
	** If processing takes longer than the specified sample
	** interval then raise an error and terminate.
	*/
	select @start_table = getdate()

	/*
	** Copy counter values at beginning of sample
	** into the sysmon_monitors table
	*/

	insert into #temp_sysmon_baseline
		select group_name, field_id, value
		from master.dbo.sysmonitors holdlock


	select @end_table = getdate()
	select @table_time = datediff(second, @start_table, @end_table)

	/*
	** Adjust collection interval to account for table and
	** index creation time. Reverse the sign on the @table_time
	** value to get the dateadd function to perform subtraction.
	** This will subtract the value of @table_time from the value
	** of @interval_or_option specified by the user.  This will
	** adjust the period of time that sp_sysmon waits by subtracting
	** time already spent building the baseline table from the 
	** sample interval specified by the user.
	*/
	select @collect_interval = convert(char(12),
					dateadd(second,
					-(@table_time),
					convert(datetime,
					@interval_or_option)),
					108)

	select @difference_time = datediff(second, @collect_interval,
				@interval_or_option)

	if (@difference_time < 0)
	begin
		/*
		** The specified interval is less than the time
		** required to generate the baseline (%1! seconds).
		** Please specify a longer sample interval.
		*/
		raiserror 19363, @table_time
		/* restore dbcc execution scope */
		if (@scope = "instance")
		begin
			dbcc set_scope_in_cluster('instance')
		end
		else if (@scope = "cluster")
		begin
			dbcc set_scope_in_cluster('cluster')
		end
		
		return 1
	end
end
else
begin
	select @collect_interval = @interval_or_option
end

/*
** Execute sp_sysmon_collect 
*/

exec @return=sp_sysmon_collect @collect_interval,
				@section,
				@applmon,
				@noclear

/* restore dbcc execution scope */
if (@scope = "instance")
begin
	dbcc set_scope_in_cluster('instance')
end
else if (@scope = "cluster")
begin
	dbcc set_scope_in_cluster('cluster')
end


/*
** If there was an error or if the option was "begin_sample", return
*/

if @return = 1 or @interval_or_option = "begin_sample"
 begin
        return @return
 end

select @GetStatTime = getdate()

/*
** Place monitors information into a temp table. 
**
** WARNING: If you modify this to make changes in table schema,
** please look at 'crttemptables' file where the #tempmonitors
** is created for other sub-sysmon stored procedures.
*/

/*
** Create #tempmonitors table
**
** A create table command is used here rather than cloning the sysmonitors
** table using a select-into command in order to be compatible with
** the application monitor behavior.  The application monitors are deleted
** whenever a select is performed on the sysmonitors table.  As a result
** a select-into cannot be used to create the #tempmonitors table because
** doing so will also delete the application monitors from the sysmonitors
** table.
**
** WARNING: The schema of the #tempmonitors table must exactly match the
** schema of the sysmonitors table as defined in syscoldata.c. If the schema of
** the sysmonitors table is changed the create table command below must be
** updated.
*/
select @i = 0
select @active_instance_num = 0

while @active_instance_num < @active_instances         /* for each instance */
/* { */
begin



if ((select object_id("#tempmonitors")) is not NULL)
begin
	drop table #tempmonitors
end

create table #tempmonitors (
	field_name	char(79),
	group_name	char(25),
	field_id	smallint,
	value		int,
	description	varchar(255) null,

	nodeid          tinyint null)


if (@noclear = 0)
begin
	/*
	** OPERATING IN CLEAR THE MONITOR COUNTERS MODE
	** Copy sysmonitors to #tempmonitors if not operating in
	** no clear mode
	*/
	insert into #tempmonitors
	select *
	from master.dbo.sysmonitors holdlock

end
else
begin
	/*
	** Create clustered index on baseline table.  This is done
	** at this point so that this work is performed outside of the
	** sample interval.  Work performed during index creation will
	** not be reflected in the sysmon reports and time required to
	** create the baseline table during the sample is reduced.
	*/
	create clustered index tsbi
		on #temp_sysmon_baseline

		(group_name, field_id)


	/*
	** OPERATING IN NOCLEAR MODE - Only used when a time interval
	** is given.  Generate delta values for all monitor counters
	** except those for the configuration values, control
	** and high water marks and insert into #tempmonitors.
	** The case statement will handle cases of counter wrap and 
	** situations in which counter delta's are greater than the
	** capacity of the value column.
	*/
	insert into #tempmonitors
	  select s.field_name,
		s.group_name,
		s.field_id,
		case
		when (s.value >= b.value)
		  then
		  case
		  when ((convert(numeric, s.value) - convert(numeric, b.value))
                                >= convert(numeric, 2147483648))
			/*
			** The end counter value is greater than the start
			** value, but the difference is greater than the
			** maximum signed integer value.  In this case, set
			** the value of the delta to -1.
			*/
			then (-1)
		  else
			/*
			** The common case: end counter value is greater
			** then start counter value and the delta is less
			** than or equal to the maximum signed integer value.
			*/
			(s.value - b.value)
		  end
		else
		  case
		  when ((convert(numeric, b.value) - convert(numeric, s.value))
				< convert(numeric, 2147483648))
			/*
			** The counter wrapped (its value exceeded the maximum
			** signed integer value) during the sample period and
			** the total change in value exceeds the maximum 
			** signed integer value.  In this case, set the
			** delta value to -1.
			*/
			then (-1)	
		  else
			/*
			** The counter wrapped during the sample period
			** and the delta is less than or equal to the
			** maximum signed integer value.  In this case
			** calculate the delta by subtracting the current
			** value of the counter from its value at the
			** beginning of the sample period and then subtract
			** that value from the total range of the signed
			** integer.  This gives the actual change in
			** value during the sample period.
			*/
			(convert(int, (4294967295
				- (convert(numeric, b.value)
					- convert(numeric, s.value)))))
		  end
		end as value,
		s.description,

		s.nodeid

	  from master.dbo.sysmonitors s holdlock,
		#temp_sysmon_baseline b 
	  where b.group_name = s.group_name
	     and b.field_id = s.field_id
	     and b.group_name not in ('config', 'resource_stats', 'control')
	     and field_name not like "max%"
	     and field_name not like "%hwm"


	/*
	** Copy the static values into the
	** #tempmonitors table without performing
	** deltas
	*/
	insert into #tempmonitors
	  select *
	  from master.dbo.sysmonitors
	  where (group_name in ('config', 'resource_stats', 'control')
	    or field_name like "max%"
	    or field_name like "%hwm")

	

	/*
	** Check to see whether the monitor counters have been cleared
	** since the beginning of this session.  This is not
	** guaranteed to detect every time that the counters have been
	** cleared.  But if engine_0 clock_ticks is lower now than
	** when the sample was begun, then we know that the counters
	** have been cleared.
	*/
	select @clockticks = value from
		#tempmonitors
		where group_name = "engine_0"
		and field_name = "clock_ticks"

	if (@clockticks <= 0)
	begin
		/*
		** It appears that the monitor counters have been cleared
		** since the beginning of the sample period.  The
		** sp_sysmon report cannot be run successfully.
		** Please re-run the sp_sysmon report ensuring
		** that the monitor counters are not cleared during
		** the sample period.
		*/
		raiserror 19362
		print " "
		return 1
	end	
end

/*
** Create index on tempmonitors columns used in queries
** during report generation
*/

begin
	create clustered index tmci
		on #tempmonitors
		(group_name, field_id)
end

/*
** Print report header
*/
if (@header_printed = 0)
begin
	print @section_line
	print "      Sybase Adaptive Server Enterprise System Performance Report"
	print @section_line
	print @blankline
	select @rptline= "Server Version:"+space(8)+substring(@@version,1,56)
	print @rptline

	/*
	** Calculate length of the sample period based on engine 0 clock ticks
	** at start of sample period.  Subtract this from the end time to 
	** obtain the start of the sample period.
	*/

	begin
		select @Seconds = convert(int, value * (1.0 * @@timeticks/1000000))
			from #tempmonitors
			where field_name = 'clock_ticks'
			  and group_name = 'engine_0'
	end


	select @ClrStatTime = dateadd(second,-(@Seconds), @GetStatTime)

	select @sample_period = convert(char(12),
					dateadd(second, @Seconds, "00:00:00"),
					108)

	select @rptline = "Run Date:" + space(14) +
				convert(char(12), @GetStatTime, 107)
	print @rptline

	if (@interval_or_option != "end_sample")
	begin
		select @rptline = "Sampling Started at:  " +
			space(1) + convert(char(12), @ClrStatTime, 107) +
			space(1) + convert(char(8), @ClrStatTime, 108)
	end
	else
	begin
		select @rptline = "Statistics Cleared at:" +
			space(1) + convert(char(12), @ClrStatTime, 107) +
			space(1) + convert(char(8), @ClrStatTime, 108)
	end
	print @rptline

	if (@interval_or_option != "end_sample")
	begin
		select @rptline = "Sampling Ended at:    " +
			space(1) + convert(char(12), @GetStatTime, 107) +
			space(1) + convert(char(8), @GetStatTime, 108)
	end
	else
	begin
		select @rptline = "Statistics Sampled at:" +
			space(1) + convert(char(12), @GetStatTime, 107) +
			space(1) + convert(char(8), @GetStatTime, 108)
	end
	print @rptline

	select @rptline = "Sample Interval:      " +space(1)+ @sample_period
	print @rptline

	if (@noclear = 1)
	begin
		select @rptline = "Sample Mode:          " +space(1)+ "No Clear" 
	end
	else
	begin
		select @rptline = "Sample Mode:          " + space(1) + "Reset Counters"
	end
	print @rptline

	if (@noclear = 1)
	begin
		if (@system_view != "cluster")
		begin
			select @counters_cleared = dateadd(ss,
					-(value/(1000000/@@timeticks)),
					getdate())
				from master.dbo.sysmonitors
				where group_name = 'engine_0'
				and field_name = 'clock_ticks'
		end


		select @rptline = "Counters Last Cleared:" +
			space(1) + convert(char(12), @counters_cleared, 107) +
			space(1) + convert(char(8), @counters_cleared, 108)
		print @rptline
	end

	select @header_printed = 1
end



if @instancename is not null
begin
	select @rptline = "Server Name:" + space(11) + @instancename
end
else
begin
	select @rptline = "Server Name:" + space(11) + "Server is Unnamed"
end
print @rptline


begin
select @Seconds = convert(int, value * (1.0 * @@timeticks/1000000))
                from #tempmonitors
                where field_name = 'clock_ticks'
                  and group_name = 'engine_0'
end

/*
** End printing report header
*/

/*
** create a temp table for cache information
*/
if ((select object_id("#cachemap")) is not NULL)
begin
	drop table #cachemap
end

create table #cachemap (
        cid smallint, 
        name varchar(255), 
        group_name varchar(255), 
	cache_status            char(24) null, 
        cache_type              char(24) null, 
        cache_config_size       char(24) null, 
        cache_run_size          char(24) null, 
        config_replacement      char(24) null, 
        run_replacement         char(24) null)

/*
** fetch all cache related information
*/
if (@system_view != "cluster")
begin
	declare cache_info cursor for
 	select convert(varchar(30), co.name) ,convert(char(24),co.value),
		co.status, cu.status,
                convert(char(24),cu.value)
		from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
		where parent = 19
		and  co.config = 19
		and co.config = cu.config
		and co.name = cu.comment
		order by co.name
		for read only
end


open cache_info
  fetch cache_info into @CacheName,@ConfigSize,@Stat,@RunStat,@RunSize
while (@@sqlstatus = 0)
  begin
        select @CacheID = config_admin(15,0,0,0,NULL,@CacheName)

	if (@Stat & 2 = 2) 
	begin
              select @Cache_Type = "Mixed"
	end

	if (@Stat & 4 = 4) 
	begin
              select @Cache_Type = "Log Only"
	end

	if (@Stat & 1 = 1) 
	begin
              select @Cache_Type = "Default"
	end

	if (@Stat & 32 = 32)
        begin
            select @Cache_Status = "Active"
        end

        if (@Stat & 64 = 64)
        begin
             select @Cache_Status = "Pend/Act"
        end

        if (@Stat & 128 = 128)
        begin
             select @Cache_Status = "Act/Del"
        end


	/*
	**  Determine configured cache replacement policy
	*/
	if (@Stat & 256 = 256)
	begin
		select @Cfg_Cache_Repl = "relaxed LRU"
	end
	else
	begin
		select @Cfg_Cache_Repl = "strict LRU"
	end

	/*
	**  Determine running cache replacement policy
	*/
	if (@RunStat & 256 = 256)
	begin
		select @Run_Cache_Repl = "relaxed LRU"
	end
	else
	begin
		select @Run_Cache_Repl = "strict LRU"
	end


        insert into #cachemap values (@CacheID, @CacheName, "buffer_" +
                                        convert(varchar(3), @CacheID),
					@Cache_Status,
        				@Cache_Type  ,
        				@ConfigSize  ,
        				@RunSize     ,
        				@Cfg_Cache_Repl ,
        				@Run_Cache_Repl )
  	fetch cache_info into @CacheName,@ConfigSize,@Stat,@RunStat,@RunSize
  end
close cache_info
deallocate cursor cache_info



/*
** create a temp table for device information 
**
** WARNING: If you modify this to make changes in table schema,
** please look at 'crttemptables' file where the #devicemap
** is created for other sub-sysmon stored procedures.
*/
if ((select object_id("#devicemap")) is not NULL)
begin
	drop table #devicemap
end

create table #devicemap(name char(265),
                        phyname char(127),
                        group_name char(255))

/*
** fetch all device related information
*/

if (@system_view != "cluster")
begin
	declare disk_info cursor for
	select name,phyname,vdevno
	from master.dbo.sysdevices
	where (status & 16) != 16
	for read only
end


open disk_info
  fetch disk_info into @DiskName,@PhysName,@grp
while (@@sqlstatus = 0)
  begin
        insert into #devicemap values(@DiskName,@PhysName,"disk_"+convert(char(10),@grp))
        fetch disk_info into @DiskName,@PhysName,@grp
  end
close disk_info
deallocate cursor disk_info

/*
** Place config information into a temp table.
**
** WARNING: If you modify this to make changes in table schema,
** please look at 'crttemptables' file where the #tempconfigures
** is created for other sub-sysmon stored procedures.
*/
if ((select object_id("#tempconfigures")) is not NULL)
begin
	drop table #tempconfigures
end

select c.name as name,convert(varchar(255),r.value) as value into #tempconfigures
	from master..sysconfigures c, master..syscurconfigs r
	where r.config = c.config and c.parent != 19
	and not (c.parent in (1,10,14,0) and r.value = 0)




/*
** place pool information into a temp table
*/
if ((select object_id("#pool_detail_per_cache")) is not NULL)
begin
	drop table #pool_detail_per_cache
end
select name,convert(varchar(8),substring(co.comment, 1,
		charindex("K", co.comment) - 1) ) as io_size
	into #pool_detail_per_cache
	from master.dbo.sysconfigures co
	where co.parent = 19
	and co.comment like "%Buffer Pool%"


/*
** Handle the new sections
*/
if @section = "cache wizard"
begin
	/*
	** If the user specified the new sections, and did not specify
	** the parameters, set them to default.
	*/
	if @applmon = "no_appl"
	begin
		select @applmon = "10"
	end
	
	select @mda_procname = 'sp_sysmon_analyze_mda'
	
	if exists(select 1 from sybsystemprocs.dbo.sysobjects where
				sysstat & 7 = 4 and name = @mda_procname)
	begin
		exec @rtn_status = @mda_procname @Seconds, 'Y', @section,
						   @applmon,
						   @filter
		return @rtn_status
	end
end
else
begin

	/*
	** Execute sp_sysmon_analyze 
	*/
	exec sybsystemprocs..sp_sysmon_analyze @Seconds, 'Y', @section, 
						@applmon, @instid
end




if ((select object_id("#tempmonitors.tmci")) is not NULL)
begin
	drop index #tempmonitors.tmci
end
if ((select object_id("#temp_sysmon_baseline.tsbi")) is not NULL)
begin
	drop index #temp_sysmon_baseline.tsbi
end

select @active_instance_num = @active_instance_num + 1
select @i = @i + 1
end
/* } */

if (@section= "NULL")
begin
	print "=============================== End of Report ================================="
end
 
if (@dumpcounters = "y")
begin

	print ""
	print "==================== Start of Raw Monitor Counter Output ======================"
	print ""
	select field_name, group_name, field_id, value from #tempmonitors
	where value != 0

end

return 0
go
exec sp_procxmode 'sp_sysmon', 'anymode'
go
grant execute on sp_sysmon to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_memlog')
begin
	drop procedure sp_memlog
end
go
print "Installing sp_memlog"
go

/*
** SP_MEMLOG
**
** This file contains the definition of the sp_memlog system
** stored procedure.  This stored procedure is used to change settings
** of Memory Log.
** The sa_role is required to make any changes to the
** system configuration.
**
** Security: The sa_role role is required in order to change memlog settings.
**
** History:
** May 2006	frankl		Initial coding, based on sp_shmdumpconfig
*/

create procedure sp_memlog
/* -------------- Stored Procedure Parameters ----------------------- */
@action 	varchar(20) = "help",	/* action requested by user   */
@dumps_per_file	int         = 10	/* dump count value           */
as

/* ----------------- Declare Local Variables ------------------------ */
declare @object_info1	int, 		/* object_info1 column value  */
	@attrib   	int,		/* attribute column value     */
	@not_status 	int,		/* notification return status */
	@int_value	int

/*
** The following variables are treated as constants within this
** stored procedure. They are set below.
*/
declare @MEMLOG_CLASS	int,		/* sysattributes class        */
	@OBJTYPE	char(2),	/* sysattributes object typ   */
	@ATTR_ADD	int,		/* add notification value     */
	@ATTR_CHANGE	int,		/* change notification val    */
	@ATTR_DROP	int,		/* drop notification value    */
	@ATTR_FETCH	int		/* fetch notification value   */

/* ----------------- Setup and Validation ------------------------ */
set nocount on

/*
** Class ID and type defined in utils/attrib.lst
*/
select @MEMLOG_CLASS 	= 30
select @OBJTYPE		= "ML"

/*
** The following must correspond to values in sysattr.h
*/
select @ATTR_ADD 	= 1
select @ATTR_CHANGE	= 2
select @ATTR_DROP	= 3
select @ATTR_FETCH	= 4

/*
** Determine the attribute number and int_value for the attribute indicated
** by the @action.
**
** NOTE: The integer values used for attrib must correspond to values
** defined in utils/attrib.lst.  Any changes made here must also be made
** in attrib.lst, and vice versa.
**	0: suspend
**	1: sequence numbers
**	2: dump when full
**	3: dump destination
*/
create table #actions(attrib int, int_val int, action varchar(20))

insert #actions select 0, 0, 'enable logging'
insert #actions select 0, 1, 'disable logging'
insert #actions select 1, 0, 'disable sequence num'
insert #actions select 1, 1, 'enable sequence num'
insert #actions select 2, 0, 'no dump when full'
insert #actions select 2, 1, 'dump when full'

/*
** The following constants define record types for the melog dump destination
** defined in cinclude/memlog.h.
*/
insert #actions select 3, 0, 'dump to errorlog'
insert #actions select 3, 1, 'dump to file'
insert #actions select 3, 2, 'dump to shm'
insert #actions select 3, 3, 'dump to table'
insert #actions select 3, 4, 'disable dump'

/*
** End Common Definition Section
*/


if @action = 'help'
begin
usage:
	print ""
	print "Usage: sp_memlog 'help'"
	print "       sp_memlog 'list'"
	print "       sp_memlog 'enable logging' | 'disable logging'"
	print "       sp_memlog 'enable sequence num' | 'disable sequence num'"
	print "       sp_memlog 'dump to errorlog' | 'dump to file'"
	print "               | 'dump to shm' | 'dump to table' | 'disable dump'"
	print "       sp_memlog '[no ]dump when full' [, dumps_per_file]"

	return 0
end

if @action = 'list'
begin
	goto list
end

	/*
	** Change settings section
	*/
	if (proc_role("sa_role") < 1)
	begin
		return 2
	end

	/*
	** Translate @action to attrib and int_value.
	*/
	select @attrib = attrib, @int_value = int_val
	 from #actions
	 where action = @action 

	if @@rowcount = 0
	begin 
		/*
		** 18516, "Invalid action %1!"
		*/
		raiserror 18516, @action
		goto usage
	end 

	/*
	** Special case for 'dump when full': object_info1
	** becomes number of dumps per file.
	*/
	select @object_info1 = NULL

	if @attrib = 2
	begin
		select @object_info1 = @dumps_per_file
	end

	begin tran ChangeMemlog
	/*
	** Delete existing entry, if there is one
	*/
	delete master.dbo.sysattributes
		where class = @MEMLOG_CLASS
		and attribute = @attrib
		and object_type = @OBJTYPE

	/*
	** Insert new values
	*/
	insert master.dbo.sysattributes
		(class, attribute, object_type, 
			int_value, object_info1)
		values(@MEMLOG_CLASS, @attrib, @OBJTYPE, 
			@int_value, @object_info1)

	if (@@error = 0)
	begin
		select @not_status 
			= attrib_notify(@MEMLOG_CLASS,/*cl*/
				@attrib, 	/*attrib */
				@OBJTYPE,    	/*type*/ 
				NULL, 		/*object*/
				@object_info1,	/*info1*/
				0, 		/*info2*/
				NULL, 		/*info3*/
				NULL, 		/*cinfo*/
				@int_value,	/*intval*/
				NULL, 		/*charval*/
				NULL, 		/*textval*/
				NULL, 		/*imageval*/
				NULL,		/*comment*/
				@ATTR_CHANGE)

		if (@not_status = 0)
		begin
			/*
			** 18505, "Notification failed. Condition not set."
			*/
			raiserror 18505
			goto error_exit
		end
	end
	else
	begin
		goto error_exit
	end

	commit ChangeMemlog

list:
	/*
	** Display current setting based on what is in sysattributes
	*/
	print "Current settings"
	print ""
	select	act.action, 
		dumps_per_file = att.object_info1
          from	master.dbo.sysattributes att,
		#actions act
          where	att.class = @MEMLOG_CLASS
	    and object_type = @OBJTYPE
            and	act.attrib = att.attribute
            and	act.int_val = att.int_value

	/*
	** Indicate success
	*/
	return 0

error_exit:
	/*
	** An error occured while inserting rows into the sysattributes table.
	*/
	if (@@trancount > 0)
	begin
		/*
		** Rollback the current transaction
		*/
		rollback tran ChangeMemlog
	end

	return 18

/*
** End of sp_memlog
*/
go
exec sp_procxmode 'sp_memlog', 'anymode'
go
grant execute on sp_memlog to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_add_resource_limit')
begin
	drop procedure sp_add_resource_limit
end
go
print "Installing sp_add_resource_limit"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_add_resource_limit"
**
** 17231, "No login with the specified name exists."
** 17240, "'%1!' is not a valid name."
** 17260, "Can't run %1! from within a transaction."
** 17261, "Only the System Administrator (SA) may execute this procedure."
** 18182, "Timerange name must be non-NULL."
** 18199, "Unknown time range name '%1!'."
** 18202, "At least one of the login or application name must be non-NULL."
** 18203, "Limit type must be non-NULL.
** 18204, "Unknown limit type '%1!'."
** 18205, "Limit value must be non-NULL."
** 18206, "Illegal limit value %1!. Value must be non-negative."
** 18207, "Illegal action %1!."
** 18208, "Illegal enforcement-time value %1! for this limit type."
** 18209, "Illegal scope value %1! for this limit type."
** 18210, "Unknown starting time value '%1!' found in systime ranges."
** 18211, "Unknown ending time value '%1!' found in systimeranges."
** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
** 18213, "This user/application can have only one limit for each distinct combination of time range, limit type, enforcement time and scope."
** 18214, "New resource limit created."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins.
** 18779, "Unable to find the time range '%1!' with id '%2!' in systimeranges.
** 18781, "Unable to find a limit type with name '%1!' and id '%2!'."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_add_resource_limit
@name		varchar(255),	/* login to which limit applies */
@appname	varchar(255),	/* application to which limit applies */
@rangename	varchar(255),	/* timerange during limit applied */
@limittype	varchar(30),	/* what's being limited */
@limitvalue	int,		/* upper-bound value of limit */
@enforced	int = NULL,	/* before or during execution */
@action		int = 2,	/* what to do if limit is violated */
@scope		int = NULL	/* scope of limit */
as

declare	@limitid	smallint
declare	@rangeid	smallint
declare	@current_range	int
declare	@enforced_arg	int
declare	@action_arg	int
declare	@scope_arg	int
declare	@msg		varchar(1024)
declare	@start_dt	datetime
declare	@end_dt		datetime
declare	@cur_start_dt	datetime
declare	@cur_end_dt	datetime
declare	@startdaynum	int
declare	@enddaynum	int
declare	@cur_startdaynum	int
declare	@cur_enddaynum	int
declare @tmp_starttime	varchar(30)
declare @tmp_endtime	varchar(30)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0


if (proc_role("sa_role") = 0)
begin
	/*
	** 17261, "Only the System Administrator (SA) may execute this procedure."
	*/
	raiserror 17261
	return (1)
end



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_add_resource_limit', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_add_resource_limit"
	return (1)
end

if ( (@name is null) and (@appname is null) )
begin
	/*
	** 18202, "At least one of the login or application name must be non-NULL."
	*/
	raiserror 18202
	return (1)
end

/* Is login valid? */
if ( (@name is not null) and not exists
	(select * from master.dbo.syslogins where name = @name) )
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return(1)
end

/* Has a legal range been specified? */

select @rangename = rtrim(@rangename)

if (@rangename is null)
begin
	/*
	** 18182, "Timerange name must be non-NULL."
	*/
	raiserror 18182
	return(1)
end
else if not exists
	(select * from master.dbo.systimeranges where name = @rangename)
begin
	/*
	** 18199, "Unknown time range name '%1!'."
	*/
	raiserror 18199, @rangename
	return(1)
end

/* Has a legal limit type been specified? */
if (@limittype is null)
begin
	/*
	** 18203, "Limit type must be non-NULL.
	*/
	raiserror 18203
	return(1)
end
else if not exists
	(select * from master.dbo.spt_limit_types where name = @limittype)
begin
	/*
	** 18204, "Unknown limit type '%1!'."
	*/
	raiserror 18204, @limittype
	return(1)
end

/* Has a limit value been specified? */
if (@limitvalue is null)
begin
	/*
	** 18205, "Limit value must be non-NULL."
	*/
	raiserror 18205
	return(1)
end
else if (@limitvalue <= 0)
begin
	/*
	** 18206, "Illegal limit value %1!. Value must be non-negative."
	*/
	raiserror 18206, @limitvalue
	return(1)
end

/* Has a legal action been specified? */
/* If NULL, the default (batch abort) is taken */
if (@action is null)
begin
	select @action_arg = 2
end
else if ( (@action < 1) or (@action > 4) )
begin
	/*
	** 18207, "Illegal action %1!."
	*/
	raiserror 18207, @action
	return(1)
end
else
begin
	select @action_arg = @action
end

/* Has a legal enforcement time been specified? */
if (@enforced is NULL)
begin
	select @enforced_arg = enforced from master.dbo.spt_limit_types where name = @limittype
end
else if (((@enforced & (select enforced from master.dbo.spt_limit_types where name = @limittype)) != @enforced) or (@enforced = 0))
begin
	/*
	** 18208, "Illegal enforcement-time value %1! for this limit type."
	*/
	raiserror 18208, @enforced
	return(1)
end
else
begin
	select @enforced_arg = @enforced
end

/* Has a legal scope been specified? */
if (@scope is NULL)
begin
	select @scope_arg = scope from master.dbo.spt_limit_types where name = @limittype
end
else if (((@scope & (select scope from master.dbo.spt_limit_types where name = @limittype)) != @scope) or (@scope = 0))
begin
	/*
	** 18209, "Illegal scope value %1! for this limit type."
	*/
	raiserror 18209, @scope
	return(1)
end
else
begin
	select @scope_arg = @scope
end

/* Get the id# corresponding to the limit */
select @limitid = id from master.dbo.spt_limit_types where name = @limittype

/* Get the id# corresponding to the timerange */
select @rangeid = id from master.dbo.systimeranges
	where name = @rangename

/* Get the starting time for the range used by this limit */
select @tmp_starttime = starttime from master.dbo.systimeranges
	where id = @rangeid

/* Get the ending time for the range used by this limit */
select @tmp_endtime = endtime from master.dbo.systimeranges
	where id = @rangeid

/* Get the starting day for the range used by this limit */
select @startdaynum = startday from master.dbo.systimeranges
	where name = @rangename

/* Get the ending day for the range used by this limit */
select @enddaynum = endday from master.dbo.systimeranges
	where name = @rangename

/* Convert the starting time to datetime so we can do arithmetic */
select @start_dt = convert(datetime, @tmp_starttime)
if (@start_dt is null)
begin
	/*
	** 18210, "Unknown starting time value '%1!' found in systimeranges."
	*/
	raiserror 18210, @tmp_starttime
	return(1)
end

/* Convert the ending time to datetime so we can do arithmetic */
select @end_dt = convert(datetime, @tmp_endtime)
if (@end_dt is null)
begin
	/*
	** 18211, "Unknown ending time value '%1!' found in systimeranges."
	*/
	raiserror 18211, @tmp_endtime
	return(1)
end

/* Cursor result: ranges associated with limits currently imposed 
** upon the given user/application
*/
declare c1 cursor for 
	select distinct rangeid from master.dbo.sysresourcelimits
	where ( (name = @name) and (appname = @appname) ) or 
	( (name = @name) and (@appname is null) ) or
	( (name = @name) and (appname is null) ) or 
	( (name is null) and (appname = @appname) ) or 
	( (@name is null) and (appname = @appname) )

open c1

fetch c1 into @current_range

/* We need to peruse the cursor results to see if this new
** limit overlaps with another limit for this user/application.
*/
while (@@sqlstatus != 2)
begin

	if (@current_range != @rangeid)
	begin

		/* Get the start and end days for current range */
		select @cur_startdaynum = startday from 
			master.dbo.systimeranges
			where id = @current_range
		select @cur_enddaynum = endday from 
			master.dbo.systimeranges
			where id = @current_range

		/* Get the start and end times for current range */
		select @tmp_starttime = starttime from 
			master.dbo.systimeranges
			where id = @current_range
		select @tmp_endtime = endtime from 
			master.dbo.systimeranges
			where id = @current_range
		select @cur_start_dt = convert(datetime, @tmp_starttime)
		select @cur_end_dt = convert(datetime, @tmp_endtime)

		/* See if the limit overlaps with any other
		** limit defined for this user/application
		** (excepting limits defined for the exact
		** same timerange).
		*/

		/* This is the non-wrapping case, for starttime.
		** If (the current range doesn't wrap around the
		** end of the week)
		** and
		** (the days of the new limit's range
		** overlap with the current range)
		** and 
		** (the starttime of the new limit's range is after
		** the starttime of the current range)
		** and 
		** (the endtime of the new limit's range is before
		** the endtime of the current range, with 00:00
		** being taken as midnight)
		** then we have an overlap, so raise an error
		** and return.
		*/
		if 
		(@cur_startdaynum <= @cur_enddaynum) 
		and 
		(((@startdaynum >= @cur_startdaynum) and
		  (@startdaynum <= @cur_enddaynum)) or
		 ((@enddaynum >= @cur_startdaynum) and
		  (@enddaynum <= @cur_enddaynum)) or
		 ((@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum)))
		and
		(@start_dt >= @cur_start_dt) 
		and 
		((@start_dt < @cur_end_dt) or
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		begin
			/*
			** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
			*/
			raiserror 18212, @current_range
			return(1)
		end

		/* This is the wrapping case, for starttime.
		*/
		if
		(@cur_startdaynum > @cur_enddaynum) 
		and
		((@startdaynum >= @cur_startdaynum) or
		 (@startdaynum <= @cur_enddaynum) or
		 (@enddaynum >= @cur_startdaynum) or
		 (@enddaynum <= @cur_enddaynum) or
		 ((@startdaynum > @enddaynum) and
		  (@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum))) 
		and
		(@start_dt >= @cur_start_dt) 
		and 
		((@start_dt < @cur_end_dt) or
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		begin
			/*
			** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
			*/
			raiserror 18212, @current_range
			return(1)
		end
			
		/* This is the non-wrapping case, for endtime.
		** If (the current range doesn't wrap around the
		** end of the week)
		** and
		** (the days of the new limit's range
		** overlap with the current range)
		** and 
		** (the endtime of the new limit's range is before
		** the endtime of the current range, with 00:00
		** being taken as midnight)
		** and 
		** (the endtime of the new limit's range is after
		** the starttime of the current range)
		** then we have an overlap, so raise an error
		** and return.
		*/
		if 
		(@cur_startdaynum <= @cur_enddaynum) 
		and 
		(((@startdaynum >= @cur_startdaynum) and
		  (@startdaynum <= @cur_enddaynum)) or
		 ((@enddaynum >= @cur_startdaynum) and
		  (@enddaynum <= @cur_enddaynum)) or
		 ((@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum)))
		and
		((@end_dt <= @cur_end_dt) or 
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		and 
		(@end_dt > @cur_start_dt)
		begin
			/*
			** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
			*/
			raiserror 18212, @current_range
			return(1)
		end

		/* This is the wrapping case, for endtime.
		*/
		if 
		(@cur_startdaynum > @cur_enddaynum) 
		and
		((@startdaynum >= @cur_startdaynum) or
		 (@startdaynum <= @cur_enddaynum) or
		 (@enddaynum >= @cur_startdaynum) or
		 (@enddaynum <= @cur_enddaynum) or
		 ((@startdaynum > @enddaynum) and
		  (@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum))) 
		and
		((@end_dt <= @cur_end_dt) or 
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		and 
		(@end_dt > @cur_start_dt)
		begin
			/*
			** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
			*/
			raiserror 18212, @current_range
			return(1)
		end

		/* This is the non-wrapping case, where
		** the limit's timerange completely
		** covers the current range.
		*/
		if
		(@cur_startdaynum <= @cur_enddaynum) 
		and
		(((@startdaynum >= @cur_startdaynum) and
		  (@startdaynum <= @cur_enddaynum)) or
		 ((@enddaynum >= @cur_startdaynum) and
		  (@enddaynum <= @cur_enddaynum)) or
		 ((@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum)))
		and
		(@start_dt < @cur_start_dt) 
		and 
		( ((@end_dt > @cur_end_dt) and
		  ((datepart(hour, @cur_end_dt) != 0) or
		   (datepart(minute, @cur_end_dt) != 0) or
		   (datepart(second, @cur_end_dt) != 0)))
		  or
		  ((datepart(hour, @end_dt) = 0) and
		   (datepart(minute, @end_dt) = 0) and
		   (datepart(second, @end_dt) = 0)) )
		begin
			/*
			** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
			*/
			raiserror 18212, @current_range
			return(1)
		end
			
		/* This is the wrapping case, where
		** the limit's timerange completely
		** covers the current range.
		*/
		if
		(@cur_startdaynum > @cur_enddaynum) 
		and
		((@startdaynum >= @cur_startdaynum) or
		 (@startdaynum <= @cur_enddaynum) or
		 (@enddaynum >= @cur_startdaynum) or
		 (@enddaynum <= @cur_enddaynum) or
		 ((@startdaynum > @enddaynum) and
		  (@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum))) 
		and
		(@start_dt < @cur_start_dt) 
		and 
		( ((@end_dt > @cur_end_dt) and
		  ((datepart(hour, @cur_end_dt) != 0) or
		   (datepart(minute, @cur_end_dt) != 0) or
		   (datepart(second, @cur_end_dt) != 0)))
		  or
		  ((datepart(hour, @end_dt) = 0) and
		   (datepart(minute, @end_dt) = 0) and
		   (datepart(second, @end_dt) = 0)) )
		begin
			/*
			** 18212, "New limit would cause overlap with limits on range %1! for this user-application combination."
			*/
			raiserror 18212, @current_range
			return(1)
		end
			
	end

	fetch c1 into @current_range
end

/* Make sure we're not adding a duplicate */
if exists (select * from master.dbo.sysresourcelimits
	where 
	/*
	(
	   ((name = @name) and
	    (appname = @appname)) or
	   ((name = @name) and
	    (@appname is null)) or
	   ((@name is null) and
	    (appname = @appname))
	)
	*/
	name = @name
	and appname = @appname

	and rangeid = @rangeid 
	and limitid = @limitid
	and ((enforced & @enforced_arg) != 0)
	and ((scope & @scope_arg) != 0) )
begin
	/*
	** 18213, "This user/application can have only one limit for each distinct combination of time range, limit type, enforcement time and scope."
	*/
	raiserror 18213
	return(1)
end


/* Insert! */
insert master.dbo.sysresourcelimits values(@name, @appname, @rangeid, @limitid, @enforced_arg, @action_arg, @limitvalue, @scope_arg, 0)



dbcc recachelimits

/*
** 18214, "New resource limit created."
*/
exec sp_getmessage 18214, @msg output
print @msg

/*
** Okay, so we know that the limit has been added ...
** but are resource limits enabled?
*/

declare @rg_status int
select @rg_status = s.value from
	master.dbo.syscurconfigs s,
	master.dbo.sysconfigures sc
	where sc.config = s.config 
	and sc.name = "allow resource limits"
if (@rg_status = 0)
begin
/*
** 19373, "WARNING: This limit will not take effect until resource limits
** are enabled for this server. Use sp_configure 'allow resource limits', 1.
*/
	exec sp_getmessage 19373, @msg output
	print @msg
end

return(0)

clean_all:

        return (1)

go
exec sp_procxmode 'sp_add_resource_limit', 'anymode'
go
grant execute on sp_add_resource_limit to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_gen_timerange_id')
begin
	drop procedure sp_gen_timerange_id
end
go
print "Installing sp_gen_timerange_id"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

create procedure sp_gen_timerange_id
@newmaxid	int output
as

declare	@msg		varchar(250)
declare	@curmaxid	int
declare @curcount	int
declare @searchcount	int

/* Create a unique ID for the range */
select @curcount = count(*) from master.dbo.systimeranges
select @curmaxid = max(id) from master.dbo.systimeranges
if (@curcount = 0)
	select @newmaxid = 1
else if (@curcount >= 0.8 * convert(double precision, @curmaxid))
	/* More than 80% full */
	select @newmaxid = @curmaxid+1
else
begin
	/* Try five random numbers between 1 and @curmaxid+1 */
	select @newmaxid = 1 + convert(double precision, @curmaxid) * rand()
	select @searchcount = 1
	while (exists (select id from master.dbo.systimeranges
		           where id = @newmaxid))
	begin
		if (@searchcount = 5)
			break
		select @newmaxid = 1 + convert(double precision, @curmaxid) * rand()
		select @searchcount = @searchcount + 1
	end
	if (@searchcount = 5)
		select @newmaxid = @curmaxid + 1
end

return (0)

go
exec sp_procxmode 'sp_gen_timerange_id', 'anymode'
go
grant execute on sp_gen_timerange_id to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_add_time_range')
begin
	drop procedure sp_add_time_range
end
go
print "Installing sp_add_time_range"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_add_time_range"
**
** 17260, "Can't run %1! from within a transaction."
** 17261, "Only the System Administrator (SA) may execute thi
s procedure."
** 18182, "Timerange name must be non-NULL."
** 18183, "Starting day must be non-NULL."
** 18184, "Ending day must be non-NULL."
** 18185, "Starting time must be non-NULL."
** 18186, "Unknown startday %1!."
** 18187, "Unknown endday %1!."
** 18188, "Range '%1!' already exists."
** 18189, "Unknown starting time value %1!."
** 18190, "Unknown ending time value %1!."
** 18191, "Ending time must be later in the day than starting time."
** 18192, "New time range created. ID number is %1!."
** 18219, "Ending time must be non-NULL."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18819, "Time range '%1!' or id '%2!' already exists in systimeranges."
** 18881, "Unable to generate %1! for HA use. Please refer to documentation for details."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_add_time_range
@name		varchar(255),	/* range name */
@startday	varchar(30),	/* first day of range */
@endday		varchar(30),	/* last day of range */
@starttime	varchar(30),	/* time of day when range begins */
@endtime	varchar(30)	/* time of day when range ends */
as

declare	@msg		varchar(1024)
declare	@curmaxid	int
declare	@newmaxid	int
declare	@start_dt	datetime
declare	@end_dt		datetime
declare	@startdaynum	int
declare	@enddaynum	int
declare @curcount	int
declare @searchcount	int
declare @rtn_code	int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_add_time_range', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if (proc_role("sa_role") = 0)
begin
	/*
	** 17261, "Only the System Administrator (SA) may execute this procedure."
	*/
	raiserror 17261
	return (1)
end

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_add_time_range"
	return (1)
end

/* Validate all parameters */

select @name = rtrim(@name)

if (@name is null)
begin
	/*
	** 18182, "Timerange name must be non-NULL."
	*/
	raiserror 18182
	return (1)
end

if (@startday is null)
begin
	/*
	** 18183, "Starting day must be non-NULL."
	*/
	raiserror 18183
	return(1)
end

if (@endday is null)
begin
	/*
	** 18184, "Ending day must be non-NULL."
	*/
	raiserror 18184
	return(1)
end

if (@starttime is null)
begin
	/*
	** 18185, "Starting time must be non-NULL."
	*/
	raiserror 18185
	return(1)
end

if (@endtime is null)
begin
	/*
	** 18219, "Ending time must be non-NULL."
	*/
	raiserror 18219
	return(1)
end

if exists (select * 
	from master.dbo.systimeranges
		where upper(name) = upper(@name))
begin
	/*
	** 18188, "Range '%1!' already exists."
	*/
	raiserror 18188, @name
	return(1)
end

/* Get the start day's number based on the day name */
select @startdaynum = daytonum(@startday) 

if (@startdaynum = -1)
begin
	/*
	** 18186, "Unknown startday %1!."
	*/
	raiserror 18186, @startday
	return(1)
end

/* Get the end day's number based on the day name */
select @enddaynum = daytonum(@endday) 

if (@enddaynum = -1)
begin
	/*
	** 18187, "Unknown endday %1!."
	*/
	raiserror 18187, @endday
	return(1)
end

/* Make sure the time params are valid times */
select @start_dt = convert(datetime, @starttime)
select @end_dt = convert(datetime, @endtime)
if (@start_dt is null)
begin
	/*
	** 18189, "Unknown starting time value %1!."
	*/
	raiserror 18189, @starttime
	return(1)
end
if (@end_dt is null)
begin
	/*
	** 18190, "Unknown ending time value %1!."
	*/
	raiserror 18190, @endtime
	return(1)
end

/* Make sure the time params are in the right order.
** The exception is when endtime is 00:00, which can
** be taken to mean midnight.
*/
if ((datepart(hour, @end_dt) != 0) or
    (datepart(minute, @end_dt) != 0) or
    (datepart(second, @end_dt) != 0)) and
   (@start_dt > @end_dt)
begin
	/*
	** 18191, "Ending time must be later in the day than starting time."
	*/
	raiserror 18191
	return(1)
end

exec @rtn_code = sp_gen_timerange_id @newmaxid output
if (@rtn_code != 0)
	return (1)



/* Insert! */
insert master.dbo.systimeranges values(@name, @newmaxid, @startdaynum, @enddaynum, @starttime, @endtime)



dbcc waketimerange

/*
** 18192, "New time range created. ID number is %1!."
*/
exec sp_getmessage 18192, @msg output
print @msg, @newmaxid
return(0)

clean_all:



	return (1)
go
exec sp_procxmode 'sp_add_time_range', 'anymode'
go
grant execute on sp_add_time_range to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_resource_limit')
begin
	drop procedure sp_drop_resource_limit
end
go
print "Installing sp_drop_resource_limit"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_drop_resource_limit"
**
** 17231, "No login with the specified name exists."
** 17260, "Can't run %1! from within a transaction."
** 17261, "Only the System Administrator (SA) may execute this procedure."
** 18199, "Unknown time range name '%1!'."
** 18202, "At least one of the login or application name must be non-NULL."
** 18204, "Unknown limit type '%1!'."
** 18207, "Illegal action %1!."
** 18209, "Illegal scope value %1! for this limit type."
** 18215, "Resource limit dropped."
** 18220, "No such limit found in sysresourcelimits."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18776, "Please also run stored procedure '%1!' on the companion server '%2!'."
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
** 18779, "Unable to find the time range '%1!' with id '%2!' in systimeranges.
** 18781, "Unable to find a limit type with name '%1!' and id '%2!'."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_drop_resource_limit
@name		varchar(255),	/* login to which limit applies */
@appname	varchar(255),	/* application to which limit applies */
@rangename	varchar(255) = NULL,	/* timerange to which limit applies */
@limittype	varchar(255) = NULL,	/* what's being limited */
@enforced	int = NULL,		/* before or during execution */
@action		int = NULL,		/* what to do upon violation */
@scope		int = NULL		/* scope of limit */
as

declare	@limitid	smallint
declare	@rangeid	smallint
declare	@msg		varchar(1024)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0


if (proc_role("sa_role") = 0)
begin
	/*
	** 17261, "Only the System Administrator (SA) may execute this procedure."
	*/
	raiserror 17261
	return (1)
end



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_drop_resource_limit', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_drop_resource_limit"
	return (1)
end

if ( (@name is null) and (@appname is null) )
begin
	/*
	** 18202, "At least one of the login or application name must be non-NULL."
	*/
	raiserror 18202
	return (1)
end

/* If a user name was specified, make sure it's legal */
if ( (@name is not null) and not exists
	(select * from master.dbo.syslogins where name = @name) )
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return(1)
end

/* If a range name was specified, make sure it's legal */

select @rangename = rtrim(@rangename)

if ( (@rangename is not null) and not exists
	(select * from master.dbo.systimeranges where name = @rangename) )
begin
	/*
	** 18199, "Unknown time range name '%1!'."
	*/
	raiserror 18199, @rangename
	return(1)
end

/* If a limit type was specified, make sure it's legal */
if ( (@limittype is not null) and not exists
	(select * from master.dbo.spt_limit_types where name = @limittype) )
begin
	/*
	** 18204, "Unknown limit type '%1!'."
	*/
	raiserror 18204, @limittype
	return(1)
end

/* If an enforcement time was specified, make sure it's legal */
if ( (@enforced is not null) and (@limittype is not null) and 
     ((@enforced & (select enforced from master.dbo.spt_limit_types 
                    where name = @limittype)) != @enforced) )
begin
	/*
	** 18208, "Illegal enforcement-time value %1! for this limit type."
	*/
	raiserror 18208, @enforced
	return(1)
end

/* If an action was specified, make sure it's legal */
if ( (@action is not null) and ((@action < 1) or (@action > 4)) )
begin
	/*
	** 18207, "Illegal action %1!."
	*/
	raiserror 18207, @action
	return(1)
end

/* If a scope was specified, make sure it's legal */
if ( (@scope is not null) and (@limittype is not null) and 
     ((@scope & (select scope from master.dbo.spt_limit_types 
                 where name = @limittype)) != @scope) )
begin
	/*
	** 18209, "Illegal scope value %1! for this limit type."
	*/
	raiserror 18209, @scope
	return(1)
end

select @limitid = id from master.dbo.spt_limit_types where name = @limittype

select @rangeid = id from master.dbo.systimeranges where name = @rangename

/* Print a message (but still return successfully) if
** there was no such limit to drop.
*/
if ( (select count(*) from master.dbo.sysresourcelimits where
	( (((name = @name) and
	    (appname = @appname)) or
	   ((name = @name) and
	    (@appname is null)) or
	   ((@name is null) and
	    (appname = @appname))) and
	  ((@rangename is null) or (rangeid = @rangeid)) and 
	  ((@limittype is null) or (limitid = @limitid)) and 
	  ((@enforced is null) or ((enforced & @enforced) != 0)) and 
	  ((@action is null) or (action = @action)) and 
	  ((@scope is null) or ((scope & @scope) != 0)) )
     ) = 0 )
begin
	/*
	** 18220, "No such limit found in sysresourcelimits."
	*/
	exec sp_getmessage 18220, @msg output
	print @msg
	return(0)
end



/* Delete! */
delete from  master.dbo.sysresourcelimits where
	( (((name = @name) and
	    (appname = @appname)) or
	   ((name = @name) and
	    (@appname is null)) or
	   ((@name is null) and
	    (appname = @appname))) and
	  ((@rangename is null) or (rangeid = @rangeid)) and 
	  ((@limittype is null) or (limitid = @limitid)) and 
	  ((@enforced is null) or ((enforced & @enforced) != 0)) and 
	  ((@action is null) or (action = @action)) and 
	  ((@scope is null) or ((scope & @scope) != 0)) )



dbcc recachelimits

/*
** 18215, "Resource limit dropped."
*/
exec sp_getmessage 18215, @msg output
print @msg

return(0)

clean_all:

        return (1)
go
exec sp_procxmode 'sp_drop_resource_limit', 'anymode'
go
grant execute on sp_drop_resource_limit to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drop_time_range')
begin
	drop procedure sp_drop_time_range
end
go
print "Installing sp_drop_time_range"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_drop_time_range"
**
** 17260, "Can't run %1! from within a transaction."
** 17261, "Only the System Administrator (SA) may execute this procedure."
** 18182, "Timerange name must be non-NULL."
** 18194, "`at all times' range may not be dropped."
** 18195, "There are still limits using this range."
** 18196, "Time range '%1!' dropped."
** 18199, "Unknown time range name '%1!'."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
** 18779, "Unable to find the time range '%1!' with id '%2!' in systimeranges."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_drop_time_range
@name		varchar(255)	/* name of range to be dropped */
as

declare	@msg		varchar(1024)
declare	@rangeid	int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_drop_time_range', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if (proc_role("sa_role") = 0)
begin
	/*
	** 17261, "Only the System Administrator (SA) may execute this procedure."
	*/
	raiserror 17261
	return (1)
end

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_drop_time_range"
	return (1)
end

/* range name must be non-null */

select @name = rtrim(@name)

if (@name is null)
begin
	/*
	** 18182, "Timerange name must be non-NULL."
	*/
	raiserror 18182
	return (1)
end

if not exists (
	select * from master.dbo.systimeranges
		where upper(name) = upper(@name))
begin
	/*
	** 18199, "Unknown time range name '%1!'."
	*/
	raiserror 18199, @name
	return (1)
end

/* Get the id # associated with the range */
select @rangeid = id from master.dbo.systimeranges
	where upper(name) = upper(@name)

/* "at all times" cannot be dropped */
if (@rangeid = 1)
begin
	/*
	** 18194, "`at all times' range may not be dropped."
	*/
	raiserror 18194
	return (1)
end

/* Make sure there aren't any limits still using this range */
if exists (select * from master.dbo.sysresourcelimits
		where rangeid = @rangeid)
begin
	/*
	** 18195, "There are still limits using this range."
	*/
	raiserror 18195
	select * from master.dbo.sysresourcelimits 
		where rangeid = @rangeid
	return(1)
end



/* Delete! */
delete master.dbo.systimeranges
	where upper(name) = upper(@name)



dbcc waketimerange
/*
** 18196, "Time range '%1!' dropped."
*/
exec sp_getmessage 18196, @msg output
print @msg, @name

return(0)

clean_all:

	return (1)
go
exec sp_procxmode 'sp_drop_time_range', 'anymode'
go
grant execute on sp_drop_time_range to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_resource_limit')
begin
	drop procedure sp_help_resource_limit
end
go
print "Installing sp_help_resource_limit"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_help_resource_limit"
**
** 17231, "No login with the specified name exists."
** 18207, "Illegal action %1!."
** 18216, "Users other than the System Administrator (SA) may only view limits applicable to themselves."
** 18217, "Illegal limit time argument '%1!'."
** 18218, "Unknown limitday value '%1!'."
** 
*/

create procedure sp_help_resource_limit
@name		varchar(30) = NULL,	/* login to which limits apply */
@appname	varchar(30) = NULL,	/* application to which limits apply */
@limittime	varchar(30) = NULL,	/* time during which limits apply */
@limitday	varchar(30) = NULL,	/* day during which limits apply */
@scope		int = NULL,		/* scope of limits */
@action		int = NULL,		/* what to do if limits are exceeded */
@verbose	int = 0			/* 1 means describe, 0 means default */
as

declare	@rangeid	smallint
declare	@limittime_dt	datetime
declare	@limitdaynum	int
declare	@procval	int
declare	@has_sa_role	int

/*
** Check if the user executing the procedure
** has sa_role. We use show_role() because
** proc_role() will raise an error message
** if the role is not enabled for this user.
*/
if (charindex("sa_role", show_role()) > 0)
	select @has_sa_role = 1
else
	select @has_sa_role = 0

select @procval = 0

/* Is login valid? */
if ( (@name is not null) and not exists
	(select * from master.dbo.syslogins where name = @name) )
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return(1)
end

if ( (@has_sa_role = 0) and (@name is not null) and (@name != suser_name()) )
begin
	/*
	** 18216, "Users other than the System Administrator (SA) may only view limits applicable to themselves."
	*/
	raiserror 18216
	return(1)
end
else
begin
	/*
	** Call proc_role() with each role that the user has 
	** in order to send the success audit records.  
	** Note that this could mean 1 or 2 audit records.
	*/
	if (@has_sa_role = 1)
		select @procval = proc_role("sa_role")
end

/* Has a legal action been specified? */
if (@action is not null) and ( (@action < 1) or (@action > 4) )
begin
	/*
	** 18207, "Illegal action %1!."
	*/
	raiserror 18207, @action
	return(1)
end

/* Convert the limit time to datetime so we can do arithmetic */
if (@limittime is not null)
begin
	select @limittime_dt = convert(datetime, @limittime)
	if (@limittime_dt is null)
	begin
		/*
		** 18217, "Illegal limit time argument '%1!'."
		*/
		raiserror 18217, @limittime
		return(1)
	end
end

/* Convert the starting time to datetime so we can do arithmetic */
if (@limitday is not null)
begin
	select @limitdaynum = daytonum(@limitday)
	if (@limitdaynum = -1)
	begin
		/*
		** 18218, "Unknown limitday value '%1!'."
		*/
		raiserror 18218, @limitday
		return(1)
	end
end

if (@verbose = 0)
begin
/* Find the limits that apply */
select l.name, l.appname, rangename = r.name, l.rangeid, l.limitid, l.limitvalue, l.enforced, l.action, l.scope 
into #sphelpreslimit1rs
from master.dbo.sysresourcelimits l, master.dbo.systimeranges r
	where (l.rangeid = r.id)
and
(
  (l.name = @name) or
  (l.name is null) or
  ((@has_sa_role = 1) and (@name is null)) or
  ((suser_name() = @name) and (l.name is null))
) 
and
((@appname is null) or (l.appname = @appname)) 
and
((@scope is null) or (l.scope = @scope))
and
((@action is null) or (l.action = @action)) 
and
(
 ( 
  (r.startday <= r.endday) 
  and
  ((@limitday is null) or
   ((@limitdaynum >= r.startday) and
    (@limitdaynum <= r.endday)))
  and
  ((@limittime is null) or
  ((convert(datetime, r.starttime) <= @limittime_dt) and
   ((convert(datetime, r.endtime) > @limittime_dt) or
    ((datepart(hour, convert(datetime, r.endtime)) = 0) and
     (datepart(minute, convert(datetime, r.endtime)) = 0) and
     (datepart(second, convert(datetime, r.endtime)) = 0)))))
 )
 or
 (
  (r.startday >= r.endday)
  and
  ((@limitday is null) or
   ((@limitdaynum >= r.startday) or
    (@limitdaynum <= r.endday)))
  and
  ((@limittime is null) or
   ((convert(datetime, r.starttime) <= @limittime_dt) and
    ((convert(datetime, r.endtime) > @limittime_dt) or
     ((datepart(hour, convert(datetime, r.endtime)) = 0) and
      (datepart(minute, convert(datetime, r.endtime)) = 0) and
      (datepart(second, convert(datetime, r.endtime)) = 0)))))
 )
)
exec sp_autoformat @fulltabname = #sphelpreslimit1rs
drop table #sphelpreslimit1rs
end
else
begin
/* Find the limits that apply */
select l.name, l.appname, rangename = r.name, l.rangeid,
	case l.limitid
		when 1 then convert(char(15),
			"io_cost" + "(" + ltrim(str(l.limitid)) + ")")
		when 2 then convert(char(15),
			"elapsed_time" + "(" + ltrim(str(l.limitid)) + ")")
		when 3 then convert(char(15),
			"row_count" + "(" + ltrim(str(l.limitid)) + ")")
		when 4 then convert(char(15),
			"tempdb_space" + "(" + ltrim(str(l.limitid)) + ")")
	end AS "limitType",
	l.limitvalue, 
	case l.enforced
		when 1 then convert(char(16),"Compilation Time")
		when 2 then convert(char(16),"Execution Time")
		when 3 then convert(char(16),"Any Time")
	end AS "enforced",
	case l.action
		when 0 then convert(char(17),"No Action")
		when 1 then convert(char(17),"Warn")
		when 2 then convert(char(17),"Abort Batch")
		when 3 then convert(char(17),"Abort Transaction")
		when 4 then convert(char(17),"Kill Session")
	end AS "action",
	case l.scope
		when 1 then convert(char(11), "Query")
		when 2 then convert(char(11), "Batch")
		when 4 then convert(char(11), "Transaction")
		when 6 then convert(char(11), "Batch/Tran") 
	end AS "scope"
into #sphelpreslimit1rs_v
from master.dbo.sysresourcelimits l, master.dbo.systimeranges r
	where (l.rangeid = r.id)
and
(
  (l.name = @name) or
  (l.name is null) or
  ((@has_sa_role = 1) and (@name is null)) or
  ((suser_name() = @name) and (l.name is null))
) 
and
((@appname is null) or (l.appname = @appname)) 
and
((@scope is null) or (l.scope = @scope))
and
((@action is null) or (l.action = @action)) 
and
(
 ( 
  (r.startday <= r.endday) 
  and
  ((@limitday is null) or
   ((@limitdaynum >= r.startday) and
    (@limitdaynum <= r.endday)))
  and
  ((@limittime is null) or
  ((convert(datetime, r.starttime) <= @limittime_dt) and
   ((convert(datetime, r.endtime) > @limittime_dt) or
    ((datepart(hour, convert(datetime, r.endtime)) = 0) and
     (datepart(minute, convert(datetime, r.endtime)) = 0) and
     (datepart(second, convert(datetime, r.endtime)) = 0)))))
 )
 or
 (
  (r.startday >= r.endday)
  and
  ((@limitday is null) or
   ((@limitdaynum >= r.startday) or
    (@limitdaynum <= r.endday)))
  and
  ((@limittime is null) or
   ((convert(datetime, r.starttime) <= @limittime_dt) and
    ((convert(datetime, r.endtime) > @limittime_dt) or
     ((datepart(hour, convert(datetime, r.endtime)) = 0) and
      (datepart(minute, convert(datetime, r.endtime)) = 0) and
      (datepart(second, convert(datetime, r.endtime)) = 0)))))
 )
)
exec sp_autoformat @fulltabname = #sphelpreslimit1rs_v
drop table #sphelpreslimit1rs_v

end

return(0)

go
exec sp_procxmode 'sp_help_resource_limit', 'anymode'
go
grant execute on sp_help_resource_limit to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_modify_resource_limit')
begin
	drop procedure sp_modify_resource_limit
end
go
print "Installing sp_modify_resource_limit"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_modify_resource_limit"
**
** 17231, "No login with the specified name exists."
** 17260, "Can't run %1! from within a transaction."
** 17261, "Only the System Administrator (SA) may execute this procedure."
** 18182, "Timerange name must be non-NULL."
** 18199, "Unknown time range name '%1!'."
** 18202, "At least one of the login or application name must be non-NULL."
** 18203, "Limit type must be non-NULL."
** 18204, "Unknown limit type '%1!'."
** 18206, "Illegal limit value %1!. Value must be non-negative."
** 18207, "Illegal action %1!."
** 18208, "Illegal enforcement-time value %1! for this limit type."
** 18209, "Illegal scope value %1! for this limit type."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18776, "Please also run stored procedure '%1!' on the companion server '%2!'."
** 18779, "Unable to find the time range '%1!' with id '%2!' in systimeranges."
** 18781, "Unable to find a limit type with name '%1!' and id '%2!'."
** 
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_modify_resource_limit
@name		varchar(255),	/* login to which limit applies */
@appname	varchar(255),	/* application to which limit applies */
@rangename	varchar(255),	/* range during which limit is enforced */
@limittype	varchar(30),	/* what's being limited */
@limitvalue	int = NULL,	/* upper-bound value for limit */
@enforced	int,		/* before or during execution */
@action		int = NULL,	/* what to do if limit is violated */
@scope		int		/* scope of limit */
as

declare	@limitid	smallint
declare	@rangeid	smallint
declare	@enforced_arg	int
declare	@scope_arg	int
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_modify_resource_limit', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if (proc_role("sa_role") = 0)
begin
	/*
	** 17261, "Only the System Administrator (SA) may execute this procedure."
	*/
	raiserror 17261
	return (1)
end

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_modify_resource_limit"
	return (1)
end

if ( (@name is null) and (@appname is null) )
begin
	/*
	** 18202, "At least one of the login or application name must be non-NULL."
	*/
	raiserror 18202
	return (1)
end

/* Was a valid user name specified? */
if ( (@name is not null) and not exists
	(select * from master.dbo.syslogins where name = @name) )
begin
	/*
	** 17231, "No login with the specified name exists."
	*/
	raiserror 17231
	return (1)
end

/* Was a valid range name specified? */

select @rangename = rtrim(@rangename)

if (@rangename is null)
begin
	/*
	** 18182, "Timerange name must be non-NULL."
	*/
	raiserror 18182
	return(1)
end
else if not exists
	(select * from master.dbo.systimeranges where name = @rangename)
begin
	/*
	** 18199, "Unknown time range name '%1!'."
	*/
	raiserror 18199, @rangename
	return(1)
end

/* Was a valid limit type specified? */
if (@limittype is null)
begin
	/*
	** 18203, "Limit type must be non-NULL."
	*/
	raiserror 18203
	return(1)
end
else if not exists
	(select * from master.dbo.spt_limit_types where name = @limittype)
begin
	/*
	** 18204, "Unknown limit type '%1!'."
	*/
	raiserror 18204, @limittype
	return(1)
end

/* Was a valid limit value specified? */
if ( (@limitvalue is not null) and (@limitvalue <= 0) )
begin
	/*
	** 18206, "Illegal limit value %1!. Value must be non-negative."
	*/
	raiserror 18206, @limitvalue
	return(1)
end

/* Was a valid action specified? */
if ( (@action is not null) and ((@action < 1) or (@action > 4)) )
begin
	/*
	** 18207, "Illegal action %1!."
	*/
	raiserror 18207, @action
	return(1)
end

/* Was a valid enforcement time specified? */
if (@enforced is null)
begin
	select @enforced_arg = enforced from master.dbo.spt_limit_types where name = @limittype
end
else if (((@enforced & (select enforced from master.dbo.spt_limit_types where name = @limittype)) != @enforced) or (@enforced = 0))
begin
	/*
	** 18208, "Illegal enforcement-time value %1! for this limit type."
	*/
	raiserror 18208, @enforced
	return(1)
end
else
	select @enforced_arg = @enforced

/* Was a valid scope specified? */
if (@scope is NULL)
begin
	select @scope_arg = scope from master.dbo.spt_limit_types where name = @limittype
end
else if (((@scope & (select scope from master.dbo.spt_limit_types where name = @limittype)) != @scope) or (@scope = 0))
begin
	/*
	** 18209, "Illegal scope value %1! for this limit type."
	*/
	raiserror 18209, @scope
	return(1)
end
else
	select @scope_arg = @scope

select @limitid = id from master.dbo.spt_limit_types where name = @limittype

select @rangeid = id from master.dbo.systimeranges where name = @rangename

if (select count(*) from master.dbo.sysresourcelimits
	where 
	( (((name = @name) and
	    (appname = @appname)) or
	   ((name = @name) and
	    (@appname is null)) or
	   ((@name is null) and
	    (appname = @appname))) and
	  (rangeid = @rangeid) and
	  (limitid = @limitid) and
	  (enforced = @enforced_arg) and
	  (scope = @scope_arg) )
    ) = 0
begin
	/*
	** 18220, "No such limit found in sysresourcelimits."
	*/
	raiserror 18220
	return(1)
end



/* Modify the limit value */
if (@limitvalue is not null)
begin
update master.dbo.sysresourcelimits 
	set limitvalue = @limitvalue
		where 
		( (((name = @name) and
	   	    (appname = @appname)) or
	  	   ((name = @name) and
	  	    (@appname is null)) or
	   	   ((@name is null) and
	   	    (appname = @appname))) and
		  (rangeid = @rangeid) and
		  (limitid = @limitid) and
		  (enforced = @enforced_arg) and
		  (scope = @scope_arg) )


end

/* Modify the action */
if (@action is not null)
begin
update master.dbo.sysresourcelimits 
	set action = @action
		where 
		( (((name = @name) and
	   	    (appname = @appname)) or
	  	   ((name = @name) and
	  	    (@appname is null)) or
	   	   ((@name is null) and
	   	    (appname = @appname))) and
		  (rangeid = @rangeid) and
		  (limitid = @limitid) and
		  (enforced = @enforced_arg) and
		  (scope = @scope_arg) )


end

dbcc recachelimits



return(0)

clean_all:



	return (1)

go
exec sp_procxmode 'sp_modify_resource_limit', 'anymode'
go
grant execute on sp_modify_resource_limit to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_modify_time_range')
begin
	drop procedure sp_modify_time_range
end
go
print "Installing sp_modify_time_range"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_modify_time_range"
**
** 17260, "Can't run %1! from within a transaction."
** 17261, "Only the System Administrator (SA) may execute this procedure."
** 18182, "Timerange name must be non-NULL."
** 18186, "Unknown startday %1!."
** 18187, "Unknown endday %1!."
** 18189, "Unknown starting time value %1!."
** 18190, "Unknown ending time value %1!."
** 18191, "Ending time must be later in the day than starting time."
** 18197, "At least one of the starting day, ending day, starting time, or ending time must be non-NULL."
** 18199, "Unknown time range name '%1!'."
** 18200, "at all times' range may not be modified."
** 18201, "Modification would cause overlap with range %1!."
** 18773, "HA_LOG: HA consistency check failure in stored procedure '%1!' on companion server '%2!'"
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_modify_time_range
@name		varchar(255) = NULL,	/* range name */
@startday	varchar(30) = NULL,	/* first day of range */
@endday		varchar(30) = NULL,	/* last day of range */
@starttime	varchar(30) = NULL,	/* starting time */
@endtime	varchar(30) = NULL	/* ending time */
as

declare	@range_being_modified	smallint
declare	@current_range	smallint
declare	@start_dt	datetime
declare	@end_dt		datetime
declare	@cur_start_dt	datetime
declare	@cur_end_dt	datetime
declare	@startdaynum	int
declare	@enddaynum	int
declare	@cur_startdaynum	int
declare	@cur_enddaynum	int
declare @tmp_starttime	varchar(30)
declare @tmp_endtime	varchar(30)
declare @msg		varchar(1024)
declare @HA_CERTIFIED tinyint   /* Is the SP HA certified ? */
declare @retstat  int


select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_modify_time_range', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

if (proc_role("sa_role") = 0)
begin
	/*
	** 17261, "Only the System Administrator (SA) may execute this procedure."
	*/
	raiserror 17261
	return (1)
end

if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_modify_time_range"
	return (1)
end

/* Make sure we have at least the minimum of args */
if (@startday is null) and (@endday is null) and (@starttime is null) and (@endtime is null)
begin
	/*
	** 18197, "At least one of the starting day, ending day, starting time, or ending time must be non-NULL."
	*/
	raiserror 18197
	return(1)
end

/* Has a valid range name been specified? */

select @name = rtrim(@name)

if (@name is null)
begin
	/*
	** 18182, "Timerange name must be non-NULL."
	*/
	raiserror 18182
	return(1)
end
else
begin
	if not exists(select * from master.dbo.systimeranges
			where upper(name) = upper(@name))
	begin
		/*
		** 18199, "Unknown time range name '%1!'."
		*/
		raiserror 18199, @name
		return(1)
	end
	select @range_being_modified = id from master.dbo.systimeranges
		where upper(name) = upper(@name)
end

/* "at all times" cannot be modified */
if (@range_being_modified = 1)
begin
	/*
	** 18200, "at all times' range may not be modified."
	*/
	raiserror 18200
	return (1)
end

/* Get the start day's number based on the day name */
if (@startday is not null)
	select @startdaynum = daytonum(@startday) 
else
	select @startdaynum = startday from master.dbo.systimeranges
		where upper(name) = upper(@name)

if (@startdaynum = -1)
begin
	/*
	** 18186, "Unknown startday %1!."
	*/
	raiserror 18186, @startday
	return(1)
end

/* Get the end day's number based on the day name */
if (@endday is not null)
	select @enddaynum = daytonum(@endday) 
else
	select @enddaynum = endday from master.dbo.systimeranges
		where upper(name) = upper(@name)

if (@enddaynum = -1)
begin
	/*
	** 18187, "Unknown endday %1!."
	*/
	raiserror 18187, @endday
	return(1)
end

/* If we're modifying the start time, convert it to datetime
** so we can do arithmetic 
*/
if (@starttime is not null)
begin
	select @start_dt = convert(datetime, @starttime)
	if (@start_dt is null)
	begin
		/*
		** 18189, "Unknown starting time value %1!."
		*/
		raiserror 18189, @starttime
		return(1)
	end
end
else
	select @start_dt = convert(datetime, starttime)
		from master.dbo.systimeranges
			where upper(name) = upper(@name)

/* If we're modifying the end time, convert it to datetime
** so we can do arithmetic 
*/
if (@endtime is not null)
begin
	select @end_dt = convert(datetime, @endtime)
	if (@end_dt is null)
	begin
		/*
		** 18190, "Unknown ending time value %1!."
		*/
		raiserror 18190, @endtime
		return(1)
	end
end
else
	select @end_dt = convert(datetime, endtime)
		from master.dbo.systimeranges
			where upper(name) = upper(@name)

/* Make sure the start and end times are in the right order.
** The exception is when endtime is 00:00, which can
** be taken to mean midnight.
*/
if ((datepart(hour, @end_dt) != 0) or
    (datepart(minute, @end_dt) != 0) or
    (datepart(second, @end_dt) != 0)) and
   (@start_dt > @end_dt)
begin
	/*
	** 18191, "Ending time must be later in the day than starting time."
	*/
	raiserror 18191
	return(1)
end

/* Cursor result: ranges used by user/applications with at least
** 1 limit defined during @range_being_modified
*/
declare c1 cursor for 
select distinct rangeid from master.dbo.sysresourcelimits a
	where exists (select * from master.dbo.sysresourcelimits b
	where ((a.name = b.name) or (a.name is null) or (b.name is null)) and
	((a.appname = b.appname) or (a.appname is null) or (b.appname is null)) and
	(b.rangeid = @range_being_modified))
/*
order by name, appname
*/

open c1

fetch c1 into @current_range

/* We need to peruse the cursor results to see if modifying
** this range would cause a limit overlap for any given
** user/application.
*/
while (@@sqlstatus != 2)
begin

	if (@current_range != @range_being_modified)
	begin

		/* Get the start and end days for current range */
		select @cur_startdaynum = startday from 
			master.dbo.systimeranges
			where id = @current_range
		select @cur_enddaynum = endday from 
			master.dbo.systimeranges
			where id = @current_range

		/* Get the start and end times for current range */
		select @tmp_starttime = starttime from 
			master.dbo.systimeranges
			where id = @current_range
		select @tmp_endtime = endtime from 
			master.dbo.systimeranges
			where id = @current_range
		select @cur_start_dt = convert(datetime, @tmp_starttime)
		select @cur_end_dt = convert(datetime, @tmp_endtime)

		/* See if the modified range overlaps with any other
		** range used by limits for this user/application
		** (excepting limits defined for the exact
		** same timerange).
		*/

		/* This is the non-wrapping case, for starttime.
		** If (the current range doesn't wrap around the
		** end of the week)
		** and
		** (the days of the modified range
		** overlap with the current range)
		** and 
		** (the starttime of the modified range is after
		** the starttime of the current range)
		** and 
		** (the endtime of the modified range is before
		** the endtime of the current range, with 00:00
		** being taken as midnight)
		** then we have an overlap, so raise an error
		** and return.
		*/
		if 
		(@cur_startdaynum <= @cur_enddaynum) 
		and 
		(((@startdaynum >= @cur_startdaynum) and
		  (@startdaynum <= @cur_enddaynum)) or
		 ((@enddaynum >= @cur_startdaynum) and
		  (@enddaynum <= @cur_enddaynum)) or
		 ((@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum)))
		and
		(@start_dt >= @cur_start_dt) 
		and 
		((@start_dt < @cur_end_dt) or
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		begin
			/*
			** 18201, "Modification would cause overlap with range %1!."
			*/
			raiserror 18201, @current_range
			close c1
			return(1)
		end

		/* This is the wrapping case, for starttime.
		*/
		if
		(@cur_startdaynum > @cur_enddaynum) 
		and
		((@startdaynum >= @cur_startdaynum) or
		 (@startdaynum <= @cur_enddaynum) or
		 (@enddaynum >= @cur_startdaynum) or
		 (@enddaynum <= @cur_enddaynum)) 
		and
		(@start_dt >= @cur_start_dt) 
		and 
		((@start_dt < @cur_end_dt) or
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		begin
			/*
			** 18201, "Modification would cause overlap with range %1!."
			*/
			raiserror 18201, @current_range
			close c1
			return(1)
		end
			
		/* This is the non-wrapping case, for endtime.
		** If (the current range doesn't wrap around the
		** end of the week)
		** and
		** (the days of the modified range
		** overlap with the current range)
		** and 
		** (the endtime of the modified range is before
		** the endtime of the current range, with 00:00
		** being taken as midnight)
		** and 
		** (the endtime of the modified range is after
		** the starttime of the current range)
		** then we have an overlap, so raise an error
		** and return.
		*/
		if 
		(@cur_startdaynum <= @cur_enddaynum) 
		and 
		(((@startdaynum >= @cur_startdaynum) and
		  (@startdaynum <= @cur_enddaynum)) or
		 ((@enddaynum >= @cur_startdaynum) and
		  (@enddaynum <= @cur_enddaynum)) or
		 ((@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum)))
		and
		((@end_dt <= @cur_end_dt) or 
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		and 
		(@end_dt > @cur_start_dt)
		begin
			/*
			** 18201, "Modification would cause overlap with range %1!."
			*/
			raiserror 18201, @current_range
			close c1
			return(1)
		end

		/* This is the wrapping case, for endtime.
		*/
		if 
		(@cur_startdaynum > @cur_enddaynum) 
		and
		((@startdaynum >= @cur_startdaynum) or
		 (@startdaynum <= @cur_enddaynum) or
		 (@enddaynum >= @cur_startdaynum) or
		 (@enddaynum <= @cur_enddaynum)) 
		and
		((@end_dt <= @cur_end_dt) or 
		 ((datepart(hour, @cur_end_dt) = 0) and
		  (datepart(minute, @cur_end_dt) = 0) and
		  (datepart(second, @cur_end_dt) = 0)))
		and 
		(@end_dt > @cur_start_dt)
		begin
			/*
			** 18201, "Modification would cause overlap with range %1!."
			*/
			raiserror 18201, @current_range
			close c1
			return(1)
		end

		/* This is the non-wrapping case, where
		** the modified range completely
		** covers the current range.
		*/
		if
		(@cur_startdaynum <= @cur_enddaynum) 
		and
		(((@startdaynum >= @cur_startdaynum) and
		  (@startdaynum <= @cur_enddaynum)) or
		 ((@enddaynum >= @cur_startdaynum) and
		  (@enddaynum <= @cur_enddaynum)) or
		 ((@startdaynum <= @cur_startdaynum) and
		  (@enddaynum >= @cur_enddaynum)))
		and
		(@start_dt < @cur_start_dt) 
		and 
		( ((@end_dt > @cur_end_dt) and
		  ((datepart(hour, @cur_end_dt) != 0) or
		   (datepart(minute, @cur_end_dt) != 0) or
		   (datepart(second, @cur_end_dt) != 0)))
		  or
		  ((datepart(hour, @end_dt) = 0) and
		   (datepart(minute, @end_dt) = 0) and
		   (datepart(second, @end_dt) = 0)) )
		begin
			/*
			** 18201, "Modification would cause overlap with range %1!."
			*/
			raiserror 18201, @current_range
			close c1
			return(1)
		end
			
		/* This is the wrapping case, where
		** the modified range completely
		** covers the current range.
		*/
		if
		(@cur_startdaynum > @cur_enddaynum) 
		and
		((@startdaynum >= @cur_startdaynum) or
		 (@startdaynum <= @cur_enddaynum) or
		 (@enddaynum >= @cur_startdaynum) or
		 (@enddaynum <= @cur_enddaynum)) 
		and
		(@start_dt < @cur_start_dt) 
		and 
		( ((@end_dt > @cur_end_dt) and
		  ((datepart(hour, @cur_end_dt) != 0) or
		   (datepart(minute, @cur_end_dt) != 0) or
		   (datepart(second, @cur_end_dt) != 0)))
		  or
		  ((datepart(hour, @end_dt) = 0) and
		   (datepart(minute, @end_dt) = 0) and
		   (datepart(second, @end_dt) = 0)) )
		begin
			/*
			** 18201, "Modification would cause overlap with range %1!."
			*/
			raiserror 18201, @current_range
			close c1
			return(1)
		end
			
	end

	fetch c1 into @current_range
end

close c1

/* Can we even find a range to modify? */
if (select count(*) from master.dbo.systimeranges
	where upper(name) = upper(@name)) = 0
begin
	/*
	** 18242, "No such time range found in systimeranges."
	*/
	raiserror 18242
	return(1)
end



/* Update! */
if (@startday is not null)
begin
	update master.dbo.systimeranges
	set startday = @startdaynum where upper(name) = upper(@name)



end

if (@endday is not null)
begin
	update master.dbo.systimeranges
	set endday = @enddaynum where upper(name) = upper(@name)



end

if (@starttime is not null)
begin
	update master.dbo.systimeranges
	set starttime = @starttime where upper(name) = upper(@name)



end

if (@endtime is not null)
begin
	update master.dbo.systimeranges
	set endtime = @endtime where upper(name) = upper(@name)
end


dbcc waketimerange

return(0)

clean_all:

	return (1)
go
exec sp_procxmode 'sp_modify_time_range', 'anymode'
go
grant execute on sp_modify_time_range to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_showplan')
begin
	drop procedure sp_showplan
end
go
print "Installing sp_showplan"
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/* Messages for "sp_showplan"		18359
** 
** 18359, "The spid value must be a positive integer. To look up plans for cached statements, use sp_showplan -1, <statement id>."
** 18360, "If the batch id, context id, or statement number is specified, \
**         all three must be specified."
** 18361, "Batch id must be non-negative."
** 18362, "Context id must be non-negative."
** 18363, "Statement number must be positive."
** 19611, "The statement id value cannot be NULL or negative."
** 19612, "Could not find a plan for the statement id '%1!'."
*/

create procedure sp_showplan
 
@spid smallint,

@batch_id int = NULL output,
@context_id int = NULL output,
@stmt_num int = NULL output
as

	declare @error int
	declare @return_value int


	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1
	/*
	** If @spid is -1, assume that @batch_id is the id for a 
	** cached statement.
	*/
	if (@spid = -1)
	begin
		if (@batch_id is NULL or @batch_id < 0)
		begin
			/* 
			** 19611, "The statement id value cannot be 
			** NULL or negative." 
			*/
			raiserror 19611
			return (1)
		end
		else
		begin
			select @return_value = show_plan(@spid, @batch_id, -1, -1)
			if (@return_value < 0)
			begin
			/*
			** 19612, "Could not find a plan for the
			** statement id '%1!'." 
			*/
				raiserror 19612, @batch_id
		                return (1)
			end
		        else
                		return (0)
		end
	end

	/* 
	** sp_showplan is not being used for cached statements,
	** the spid value must be a positive integer.
	*/
	select @error = 0
        if (@spid is NULL)
		select @error = 1
	else if (@spid < 1)
		select @error = 1
	if (@error = 1)
	begin
		/* 
		** 18359, "The spid value must be a positive integer. 
		** To look up plans for cached statements, use 
		** sp_showplan -1, <statement id>.
		*/
		raiserror 18359
		return (1)
	end


	/* 
	** Batch id, context id, and statement number must be NULL or 
	** none may be NULL.
	*/
	select @error = 0
        if (@batch_id * @context_id * @stmt_num is NULL)
	begin
	        if (@batch_id is not NULL)
			select @error = 1
		else if (@context_id is not NULL)
			select @error = 1
		else if (@stmt_num is not NULL)
			select @error = 1
	end
	if (@error = 1)
	begin
		/* 18360, "If the batch id, context id, or statement number is specified, all three must be specified." */
		raiserror 18360
		return (1)
	end


	/* 
	** Batch id, context id, and statement number are all NULL or none are
	** NULL.  If all are NULL, call the builtin function 3 times:
	** 	1st to return the batch id, 
	**	2nd to return the context id, and
	**	3rd to display the query plan and return the current statement number.
	*/
        if (@batch_id is NULL)
	begin
		/* Pass -1 for unknown values. */
		select @return_value = show_plan(@spid, -1, -1, -1)
		if (@return_value < 0)
        	        return (1)
		else
			select @batch_id = @return_value

		select @return_value = show_plan(@spid, @batch_id, -1, -1)
		if (@return_value < 0)
        	        return (1)
		else
			select @context_id = @return_value

		select @return_value = show_plan(@spid, @batch_id, @context_id, -1)
		if (@return_value < 0)
        	        return (1)
		else
		begin
			select @stmt_num = @return_value
			return (0)
		end
	end


	/* 
	** Non-NULL parameter values must be non-negative.
	*/
	if (@batch_id < 0)
	begin
		/* 18361, "Batch id must be non-negative." */
		raiserror 18361
		return (1)
	end
	if (@context_id < 0)
	begin
		/* 18362, "Context id must be non-negative." */
		raiserror 18362
		return (1)
	end
	if (@stmt_num < 1)
	begin
		/* 18363, "Statement number must be positive." */
		raiserror 18363
		return (1)
	end


	/* 
	** Display the query plan for the specified statement number.
	*/
	select @return_value = show_plan(@spid, @batch_id, @context_id, @stmt_num)
	if (@return_value < 0)
		return (1)
	else
		return (0)

go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_listsuspect_page')
begin
	drop procedure sp_listsuspect_page
end
go
print "Installing sp_listsuspect_page"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_listsuspect_page"
**
** 17260, "Can't run %1! from within a transaction."
*/

create procedure sp_listsuspect_page
@dbname        varchar(30)=NULL
as
declare @dbid 			int,		 /* dbid of the database */
	@attrib_id 		int,
	@action			int,
	@object_type		varchar(2),
	@msg 			varchar(1024),
	@sptlang		int,
	@state			int,
	@old_state		int,
	@susgran		int,
	@class			int,
	@whichone		int   	/* which language? */

select @action = 2	    /* modify entry */
select @class = 10 
select @attrib_id = 2      /* attribute is SUSPECT PAGES */
select @object_type = 'D'

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end
/*
** Check for input params - dbname, objectid, and options
*/
if @dbname is null
	select @dbname = db_name()

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

	/*
	**  If @dbname not found, say so.
	*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	exec sp_getmessage 17421, @msg output
	print @msg
	return (1)
end


select "DBName" = convert(varchar(20), @dbname), 
	"Pageid" = convert(varchar(12),int_value),
	"Object" = convert(varchar(15), object_name(object_info1, @dbid)),
	"Index"	=  convert(varchar(4), object_info2),
   	"Access" = substring(char_value, 1, 9) 
   from master.dbo.sysattributes
   where class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid 

return (0)
go
exec sp_procxmode 'sp_listsuspect_page', 'anymode'
go
grant execute on sp_listsuspect_page to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_forceonline_page')
begin
	drop procedure sp_forceonline_page
end
go
print "Installing sp_forceonline_page"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */


/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 18438, "%1!: All pages/objects in database '%2!' are now online."
** 18439, "%1!: Failed because the suspect granularity for the database '%2!' is not
**           at page level "
** 18440, "%1!: Invalid option '%2!'. Use 'sa_on', 'sa_off', or 'all_users'."
** 18441, "%1!: The page '%2!' in '%3!' is either already online or is an invalid page. 
**			  Use sp_listsuspect_page to list suspect pages."
** 18442, "%1!: Failed to update cached info for page '%2!' of database '%3!'."
** 18443, "%1!: The page '%2!' of database '%3!' is now in state '%4!'."
** 18444, "%1!: The page '%2!' of database '%3!' is already in state '%4!'.
** 18445, "%1!: The remaining suspect pages in database '%2!' are:"
*/
create procedure sp_forceonline_page
@dbname    varchar(30),
@pgid		int,
@option	varchar(9),
@printopt	varchar(8)=NULL
as
declare @dbid 		int,		 /* dbid of the database */
	@class			int,
	@attrib_id 		int,
	@action			int,
	@object_type	varchar(2),
	@msg 			varchar(1024),
	@sptlang		int,
	@state			varchar(9),
	@old_state		varchar(9),
	@susgran		int,
	@num			int,
	@whichone		int   	/* which language? */

select @class = 10	    /* for suspect granularity */
select @action = 2	    /* modify entry */
select @attrib_id = 2      /* attribute is SUSPECT PAGES */
select @object_type = 'D'


select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

	/*
	**  If @dbname not found, say so.
	*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
begin
	/*
	**18524 , "%1!:Permission denied. This operation requires System Administrator (sa_role) role."                                
	*/
	raiserror 18524, "sp_forceonline_page"
	return (1)
end


if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	exec sp_getmessage 17428, @msg output
	print  "sp_forceonline_page: %1!", @msg
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_forceonline_page"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/


select @susgran = int_value from master.dbo.sysattributes
	where	class = @class AND
		attribute = 0 	AND
		object_type = @object_type	AND
		object = @dbid 

if (@susgran != 2)
begin
	/*
	** 18439, "%1!: Failed because the suspect granularity for the database '%2!' is not
	**           page level "
	*/
	raiserror 18439, "sp_forceonline_page", @dbname
	return(1)
end

if ((@option is NULL) OR ((@option != "sa_on") AND (@option != "sa_off")
    AND (@option != "all_users")))
begin
	/*
	** 18440,"%1!: Invalid option '%2!'. Use 'sa_on', 'sa_off', or 'all_users'."
	*/
	raiserror 18440, "sp_forceonline_page", @option 
	return(1)
end

/* check if the requested page is suspect page */
if not exists(select * from master.dbo.sysattributes
	where	class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type	AND
		object = @dbid AND
		int_value = @pgid)
begin
	/*
	** 18441, "%1!: The page '%2!' in '%3!' is either already online or is an invalid page. 
	** 			Use sp_listsuspect_page to list suspect pages."
	*/
	raiserror 18441, "sp_forceonline_page", @pgid, @dbname 
	return(1)
end			

/* get the current status of the page */
select @old_state = substring(char_value,1,9) from master.dbo.sysattributes
      where   class = @class AND
              attribute = @attrib_id  AND
              object_type = @object_type  AND
              object = @dbid AND
              int_value = @pgid

/* setup the local variables */
if (@option = "all_users")
begin
        /* this is to drop the item */
        select @action = 3
        select @state = "ALL_USERS"
end
else
begin
        select @action = 2
        if (@option = "sa_on")
                begin
                        select @state = "SA_ONLY"
                end
        else
                begin
                        select @state = "BLOCK_ALL"
                end
end
/* 
** first update the cached information and update the master..sysattributes
** only if the update of cached info is successful
*/

if (@state != @old_state)
begin
	if (attrib_notify(@class, @attrib_id, @object_type, @dbid, NULL, NULL,
		@pgid, NULL, NULL, @state, NULL, NULL, NULL, @action) = 1)
   begin	
		/*
     	** 18442,"%1!: Failed to update cached info for page '%2!' of database '%3!'."
		*/
		raiserror 18442, "sp_forceonline_page", @pgid, @dbname 
		return(1)
   end
end

/* Now update the master..sysattributes */
if (@option = "all_users")
begin
	/* this is to drop the item */
      	delete master.dbo.sysattributes
	where	class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type AND
		object = @dbid AND
		int_value = @pgid
end
else
begin
	if (@state != @old_state)
		update master.dbo.sysattributes
      	  	set char_value = @state 
        where class = @class AND
             	attribute = @attrib_id 	AND
            	object_type = @object_type AND
              	object = @dbid	   AND
	 	int_value = @pgid
end

/* Just say what happened */
if (@state != @old_state)
	begin
	/*
	** 18443, "%1!: The page '%2!' of database '%3!' is now in state '%4!'."
	*/
	exec sp_getmessage 18443, @msg output
	print @msg, "sp_forceonline_page", @pgid, @dbname, @state
	end
else
	begin
	/*
	** 18444, "%1!: The page '%2!' of database '%3!' is already in state '%4!'.
	*/
	exec sp_getmessage 18444, @msg output
	print @msg, "sp_forceonline_page", @pgid, @dbname, @state
	return(1)
	end

/* get the number of remaining suspect pages */
select @num = count(*)
   from master.dbo.sysattributes
   where	class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid 

/* if all pages are online, say so */
if (@num = 0)
begin
	/*
	** 18438, "%1!: All pages/objects in database '%2!' are now online."
	*/
	exec sp_getmessage 18438, @msg output
	print @msg, "sp_forceonline_page", @dbname 
	return(0)
end

if (@printopt = "no_print")
	return(0)

/* 
** if dropping suspect page then list out the remaining suspect 
** pages in the db, otherwise print the status of the page. 
*/
if @action = 3
begin
  /*
  ** 18445, "%1!: The remaining suspect pages in database '%2!' are:"
  */
   exec sp_getmessage 18445, @msg output
   print @msg, "sp_forceonline_page", @dbname 
   select "DBName" = @dbname, "Pageid" = convert(varchar(12),int_value),
   	"status" = substring(char_value,1,9) 
   from master.dbo.sysattributes
   where	class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid 
end
else
begin
   select "DBName" = @dbname, "Pageid" = convert(varchar(12),int_value),
   	"status" = substring(char_value,1,9) 
   from master.dbo.sysattributes
   where	class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid AND
    	int_value = @pgid
end
return (0)
go
exec sp_procxmode 'sp_forceonline_page', 'anymode'
go
grant execute on sp_forceonline_page to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_makesuspect_obj')
begin
	drop procedure sp_makesuspect_obj
end
go
print "Installing sp_makesuspect_obj"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
*/
/*
**************************  WARNING   WARNING   WARNING ************************
**************************  WARNING   WARNING   WARNING ************************
** This stored procedure is only meant for testing and testing ONLY - to test **
** the Recovery Fault Isolation (RFI) feature by simulating various types of  **
** corruptions and isolating them during recovery using RFI feature.          ** 
** This should never be used in any production environment.                   **
********************************************************************************
*/
create procedure sp_makesuspect_obj
@dbname	varchar(30) = NULL,
@objname	varchar(30) = NULL,
@indid	int = 0,
@logtype int = -2,
@pgtype int = -2,
@errtype int = -2,
@errorcnt int = 0,
@errdelay int = 0
as
declare @dbid 			int,		 /* dbid of the database */
	@attrib_id 		int,
	@action			int,
	@object_type		varchar(2),
	@msg 			varchar(250),
	@charvalue		varchar(255),
	@sptlang		int,
	@whichone		int,   	/* which language? */
	@error_index		int,
	@shift16		int,
	@objid			int,
	@class			int,
	@indid_offset		int,
	@logtype_offset		int,
	@pgtype_offset		int,
	@errtype_offset		int,
	@errorcnt_offset	int,
	@errdelay_offset	int



select @attrib_id = 5  		/* attribute is SUSPECT error */
select @object_type = 'D'
select @class = 10 

select @indid_offset = 1
select @logtype_offset = 9
select @pgtype_offset = 17
select @errtype_offset = 25
select @errorcnt_offset = 33
select @errdelay_offset = 41

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end


/*
**  If no @dbname given, assume the current database
*/

if @dbname is null
	select @dbname = db_name()

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = dbid from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

/* get the object id  */
if @objname is null
	select @objid = -1
else
	select @objid = object_id(@dbname + '..' + @objname)

if @objid is null AND @objname != "simobj" AND @objname != "allocobj"
BEGIN
	/*
	**	xxxx0, Suspect error value %2 is not valid
	*/
	/*exec sp_getmessage xxxx0, @msg output
	print @msg */
	print "Invalid Object in the database"
	return(1)
END
if @objname = "simobj"
begin
select @objid = 0
select @errtype = 0
select @pgtype = 0
select @errorcnt = 0
select @errdelay = 0
end

/*
** If only dbname is provided, then display the setting
*/

if @errtype = -2
begin
     if (@objid = -1)
     begin
	select "DBName" = convert(varchar(15), @dbname),
                "Obj" = convert(varchar(15), object_name(object_info1, @dbid)),
                "Indid"  = substring(char_value,@indid_offset,5),
                "LogType" = substring(char_value,@logtype_offset,5),
                "PageType" = substring(char_value,@pgtype_offset,5),
                "ErrType" = substring(char_value,@errtype_offset,5),
                "Delay" = substring(char_value,@errorcnt_offset,5),
                "TotalNum"  = substring(char_value,@errdelay_offset,5)
	from master.dbo.sysattributes
	where  class = @class AND
	attribute    = @attrib_id 	AND
	object_type  = @object_type	AND
	object 	= @dbid 
     end
     else
     begin
	select "DBName" = convert(varchar(15), @dbname),
                "Obj" = convert(varchar(15), object_name(object_info1, @dbid)),
                "Indid"  = substring(char_value,@indid_offset,5),
                "LogType" = substring(char_value,@logtype_offset,5),
                "PageType" = substring(char_value,@pgtype_offset,5),
                "ErrType" = substring(char_value,@errtype_offset,5),
                "Delay" = substring(char_value,@errorcnt_offset,5),
                "TotalNum"  = substring(char_value,@errdelay_offset,5)
	from master.dbo.sysattributes
	where  class = @class AND
	attribute    = @attrib_id 	AND
	object_type  = @object_type	AND
	object 	= @dbid AND
	object_info1 = @objid AND
	substring(char_value,0,8) = convert(char(8), @indid)
     end


/*	select 	"DB Name" = @dbname,
**		"Error Type" = @errortype,
**		"Error Freq" = @error_freq 
*/
	return(0)
end

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
	return(1)

if @dbid = 1
begin
	/*
	** 17422, "The 'master' database's options can not be changed."
	*/
	raiserror 17422
	return (1)
end

if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	raiserror 17428
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_makesuspect_obj"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/


if (@errtype < -1) OR (@errtype > 50) or
   (@pgtype < -1) or (@pgtype > 8) or 
   (@logtype < -1) or (@logtype > 58) or 
    (@errorcnt < 0) or (@errorcnt > 999999) or
    (@errdelay < 0) or (@errdelay > 999999)
BEGIN
	/*
	**	xxxx0, Suspect error value %2 is not valid
	*/
	/*exec sp_getmessage xxxx0, @msg output
	print @msg */
	print "Invalid suspect error value"
	return(1)
END
select @charvalue = convert(char(8),@indid) + convert(char(8),@logtype)+
			convert(char(8),@pgtype) + convert(char(8),@errtype) +
			convert(char(8),@errorcnt) + convert(char(8),@errdelay) 

/*
** if an entry already exists for this database then delet the entry,
** and insert a new row for this database.
*/
IF exists(select * from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type AND
		object = @dbid AND
		object_info1 = @objid	AND
		substring(char_value,@indid_offset,8) = convert(char(8), @indid) AND
		substring(char_value,@logtype_offset,8) = convert(char(8), @logtype) AND
		substring(char_value,@pgtype_offset,8) = convert(char(8), @pgtype) AND
		substring(char_value,@errtype_offset,8) = convert(char(8), @errtype)  )
begin
	/* save the error index and delete the row */
	select @error_index = object_info2 from master.dbo.sysattributes where
                class = @class AND
                attribute = @attrib_id  AND
                object_type = @object_type AND
                object = @dbid AND
                object_info1 = @objid   AND
                substring(char_value,@indid_offset,8) = convert(char(8), @indid) AND
                substring(char_value,@logtype_offset,8) = convert(char(8), @logtype) AND
                substring(char_value,@pgtype_offset,8) = convert(char(8), @pgtype) AND
                substring(char_value,@errtype_offset,8) = convert(char(8), @errtype)
        delete master.dbo.sysattributes
                where   class = @class AND
                attribute = @attrib_id  AND
                object_type = @object_type AND
                object = @dbid	 AND
	        object_info1 = @objid	 AND
                substring(char_value,@indid_offset,8) = convert(char(8), @indid) AND
                substring(char_value,@logtype_offset,8) = convert(char(8), @logtype) AND
                substring(char_value,@pgtype_offset,8) = convert(char(8), @pgtype) AND
                substring(char_value,@errtype_offset,8) = convert(char(8), @errtype)
end
else
begin
	/* create a new error index which is got by incrementing the previous highest
		error index */
	select @error_index = 0
	if (@objname = "simobj")
		select @error_index = 0
	else
	begin
		select @error_index = 1
		while exists(select * from master.dbo.sysattributes where
			class = @class AND
                	attribute = @attrib_id  AND
                	object_type = @object_type AND
			object_info2 = @error_index)
		begin
			select @error_index = @error_index + 1
		end
	end
end
insert master.dbo.sysattributes
        (class, attribute, object_type,object,object_info1, object_info2, char_value)
        values(@class, @attrib_id, @object_type, @dbid, @objid, @error_index, @charvalue)



/*
** Display the setting 
*/

select "DBName" = convert(varchar(15), @dbname),
                "Obj" = convert(varchar(15), object_name(object_info1, @dbid)),
                "Indid"  = substring(char_value,@indid_offset,5),
                "LogType" = substring(char_value,@logtype_offset,5),
                "PageType" = substring(char_value,@pgtype_offset,5),
                "ErrType" = substring(char_value,@errtype_offset,5),
                "Delay" = substring(char_value,@errorcnt_offset,5),
                "TotalNum"  = substring(char_value,@errdelay_offset,5)
from master.dbo.sysattributes
                where   class = @class AND
                attribute = @attrib_id  AND
                object_type = @object_type AND
                object = @dbid   AND
                object_info1 = @objid    AND
                substring(char_value,@indid_offset,8) = convert(char(8), @indid) AND
                substring(char_value,@logtype_offset,8) = convert(char(8), @logtype) AND
                substring(char_value,@pgtype_offset,8) = convert(char(8), @pgtype) AND
                substring(char_value,@errtype_offset,8) = convert(char(8), @errtype)


/*
** xxxx3, "The new suspect granularity will become effective
**			during next load/boot time recovery"
*/
/*exec sp_getmessage xxxx1, @msg output
print @msg */
print "This error value will effective with next recovery of db"
return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_forceonline_db')
begin
	drop procedure sp_forceonline_db
end
go
print "Installing sp_forceonline_db"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
*/

create procedure sp_forceonline_db
@dbname        varchar(30),
@option	varchar(9)
as
declare @dbid 			int,		 /* dbid of the database */
	@class			int,
	@attrib_id 		int,
	@action			int,
	@object_type	varchar(2),
	@msg 			varchar(1024),
	@sptlang		int,
	@state			int,
	@old_state		int,
	@susgran		int,
	@num			int,
	@pgid			int,
	@whichone		int   	/* which language? */

select @class = 10	    /* for suspect granularity */
select @action = 2	    /* modify entry */
select @attrib_id = 2      /* attribute is SUSPECT PAGES */
select @object_type = 'D'

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end
/*
** Check for input params - dbname, pageid, and options
*/


/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

	/*
	**  If @dbname not found, say so.
	*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	exec sp_getmessage 17421, @msg output
	print @msg
	return (1)
end

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
begin
	/*
	** , "'%1!':Permission denied. This operation requires System Administrator (sa_role) role."                                
	*/
	exec sp_getmessage 18524, @msg output
	print @msg, "sp_forceonline_db"
	return (1)
end


if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	exec sp_getmessage 17428, @msg output
	print  "sp_forceonline_db: %1!", @msg
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	exec sp_getmessage 17260, @msg output
	print @msg, "sp_forceonline_db"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/


select @susgran = object_info1 from master.dbo.sysattributes
	where	class = @class AND
		attribute = 0 	AND
		object_type = @object_type	AND
		object = @dbid 


if ((@option is NULL) OR ((@option != "sa_on") AND (@option != "sa_off")
    AND (@option != "all_users")))
begin
	/*
	** "%1!: Invalid option '%2!'. Use 'sa_on', 'sa_off', or 'all_users'."
	*/
	exec sp_getmessage 18440, @msg output
	print @msg, "sp_forceonline_db", @option 
	return(1)
end

select @num = count(*) from master.dbo.sysattributes
   where class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type AND
   	object = @dbid 

if (@num = 0)
begin
	/*
	** "%1!: No suspect pages in database '%2!'. Use sp_listsuspect_page to list suspect pages."
	*/
	exec sp_getmessage 18448, @msg output
	print @msg, "sp_forceonline_db", @dbname 
	return(1)
end	

declare suspect_page cursor for
	select object_info3 from master.dbo.sysattributes
	   where class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type AND
		object = @dbid 
open suspect_page
fetch suspect_page into @pgid

while (@@sqlstatus = 0)
begin
	exec sp_forceonline_page @dbname, @pgid, @option, "no_print"
	fetch suspect_page into @pgid
end	
close suspect_page
deallocate cursor suspect_page
		

return (0)

go
exec sp_procxmode 'sp_forceonline_db', 'anymode'
go
grant execute on sp_forceonline_db to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_listsuspect_db')
begin
	drop procedure sp_listsuspect_db
end
go
print "Installing sp_listsuspect_db"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */


/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 18530, "The database '%1!' has %2! suspect pages belonging to %3! objects"
*/

create procedure sp_listsuspect_db
as
declare @dbid 			int,		 /* dbid of the database */
	@class			int,
	@attrib_id 		int,
	@action			int,
	@object_type	varchar(2),
	@msg 			varchar(1024),
	@sptlang		int,
	@state			int,
	@old_state		int,
	@susgran		int,
	@numpgs			int,
	@numobjs		int,
	@dbname			varchar(40),
	@pgid			int,
	@whichone		int   	/* which language? */

select @class = 10	    /* for suspect granularity */
select @action = 2	    /* modify entry */
select @attrib_id = 1      /* attribute is SUSPECT PAGES */
select @object_type = 'D'

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

declare suspect_db cursor for
	select object from master.dbo.sysattributes
	   where class = @class AND
		attribute = 0 AND
		object_type = @object_type
open suspect_db
fetch suspect_db into @dbid

while (@@sqlstatus = 0)
begin
	select @numpgs = count(*) from master.dbo.sysattributes
  	 where class = @class AND
   		attribute = 2 AND
   		object_type = @object_type AND
   		object = @dbid 

	select @numobjs = count(*) from master.dbo.sysattributes
  	 where class = @class AND
   		attribute = 3 AND
   		object_type = @object_type AND
   		object = @dbid

	/*
	** 18530, "The database '%1!' has %2! suspect pages belonging to %3! objects"
	*/
	if (@numpgs > 0)
	begin
		select @dbname = db_name(@dbid)
		exec sp_getmessage 18530, @msg output
   	print @msg, @dbname, @numpgs, @numobjs	 
	end
	fetch suspect_db into @dbid
end	
close suspect_db
deallocate cursor suspect_db
		
return (0)
go
exec sp_procxmode 'sp_listsuspect_db', 'anymode'
go
grant execute on sp_listsuspect_db to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_listsuspect_object')
begin
	drop procedure sp_listsuspect_object
end
go
print "Installing sp_listsuspect_object"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_listsuspect_object"
**
** 17260, "Can't run %1! from within a transaction."
*/

create procedure sp_listsuspect_object
@dbname        varchar(30)=NULL
as
declare @dbid 			int,		 /* dbid of the database */
	@attrib_id 		int,
	@action			int,
	@object_type		varchar(2),
	@msg 			varchar(250),
	@sptlang		int,
	@state			int,
	@old_state		int,
	@susgran		int,
	@class			int,
	@whichone		int   	/* which language? */

select @action = 2	    /* modify entry */
select @class = 10 
select @attrib_id = 3      /* attribute is SUSPECT OBJECTS */
select @object_type = 'D'

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end
/*
** Check for input params - dbname, objectid, and options
*/
if @dbname is null
	select @dbname = db_name()

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

	/*
	**  If @dbname not found, say so.
	*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

select "DBName" = convert(varchar(20), @dbname),
        "Objid" = convert(varchar(12),int_value),
        "Object" = convert(varchar(15), object_name(object_info1, @dbid)),
        "Index" =  convert(varchar(4), object_info2),
        "Access" = substring(char_value, 1, 9)
   from master.dbo.sysattributes
   where class = @class AND
        attribute = @attrib_id  AND
        object_type = @object_type      AND
        object = @dbid

return (0)
go
exec sp_procxmode 'sp_listsuspect_object', 'anymode'
go
grant execute on sp_listsuspect_object to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_forceonline_object')
begin
	drop procedure sp_forceonline_object
end
go
print "Installing sp_forceonline_object"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */


/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 18438, "%1!: All pages/objects in database '%2!' are now online."
** 18439, "%1!: Failed because the suspect granularity for the database '%2!' is not
**           at page level "
** 18440, "%1!: Invalid option '%2!'. Use 'sa_on', 'sa_off', or 'all_users'."
** 18575, "%1!: "The object with objid '%2!' and indid '%3!' in database '%4!' is either 
**		already online or is an invalid object. Use sp_listsuspect_object to list 
**		suspect objects."
** 18576, "%1!: Failed to update cached info for object-id '%2!' and index-id '%3!' 
**		of database '%4!'."
** 18577, "%1!: The object with object-id '%2!' and index-id '%3!' of database '%4!' is 
**		now in state '%5!'."
** 18578, "%1!: The object with object-id '%2!' and index-id '%3!' of database '%4!' is 
**		already in state '%5!'."
** 18579, "%1!: The remaining suspect objects in database '%2!' are:"
*/

create procedure sp_forceonline_object
@dbname    varchar(30),
@objname   varchar(255),
@indid		int,
@option	varchar(9),
@printopt	varchar(8)=NULL
as
declare @dbid 		int,		 /* dbid of the database */
	@class			int,
	@attrib_id 		int,
	@action			int,
	@object_type	varchar(2),
	@msg 			varchar(1024),
	@sptlang		int,
	@state			varchar(9),
	@old_state		varchar(9),
	@susgran		int,
	@num			int,
	@objid			int,
	@whichone		int   	/* which language? */

select @class = 10	    /* for suspect granularity */
select @action = 2	    /* modify entry */
select @attrib_id = 3      /* attribute is SUSPECT OBJECTS */
select @object_type = 'D'


select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

/* get object id */
select @objid = object_id(@dbname+'..'+@objname)

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

	/*
	**  If @dbname not found, say so.
	*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
begin
	/*
	**18524 , "%1!:Permission denied. This operation requires System Administrator (sa_role) role."                                
	*/
	raiserror 18524, "sp_forceonline_object"
	return (1)
end


if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	exec sp_getmessage 17428, @msg output
	print  "sp_forceonline_object: %1!", @msg
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_forceonline_object"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/


select @susgran = int_value from master.dbo.sysattributes
        where   class = @class AND
                attribute = 0   AND
                object_type = @object_type      AND
                object = @dbid

if (@susgran != 2)
begin
	/*
	** 18439, "%1!: Failed because the suspect granularity for the database '%2!' is not
	**           page level "
	*/
	raiserror 18439, "sp_forceonline_object", @dbname
	return(1)
end

if ((@option is NULL) OR ((@option != "sa_on") AND (@option != "sa_off")
    AND (@option != "all_users")))
begin
	/*
	** 18440,"%1!: Invalid option '%2!'. Use 'sa_on', 'sa_off', or 'all_users'."
	*/
	raiserror 18440, "sp_forceonline_object", @option 
	return(1)
end

/* check if the requested object is suspect object */
if not exists(select * from master.dbo.sysattributes
	where	class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type	AND
		object = @dbid AND
		object_info1 = @objid AND
		object_info2 = @indid)
begin
	/*
	** 18575, "%1!: "The object with objid '%2!' and indid '%3!' in database '%4!' is either 
	**		already online or is an invalid object. Use sp_listsuspect_object to list 
	**		suspect objects."
	*/
	raiserror 18575, "sp_forceonline_object", @objid, @indid, @dbname 
	return(1)
end			

/* get the current status of the page */
select @old_state = substring(char_value,1,9) from master.dbo.sysattributes
      where   class = @class AND
              attribute = @attrib_id  AND
              object_type = @object_type  AND
              object = @dbid AND
	      object_info1 = @objid AND
	      object_info2 = @indid
/* setup the local variables */
if (@option = "all_users")
begin
        /* this is to drop the item */
        select @action = 3
        select @state = "ALL_USERS"
end
else
begin
        select @action = 2
        if (@option = "sa_on")
                begin
                        select @state = "SA_ONLY"
                end
        else
                begin
                        select @state = "BLOCK_ALL"
                end
end

/* 
** first update the cached information and update the master..sysattributes
** only if the update of cached info is successful
*/

if (@state != @old_state)
begin
	if (attrib_notify(@class, @attrib_id, @object_type, @dbid, @objid, @indid,
		NULL, NULL, NULL, @state, NULL, NULL, NULL, @action) = 1)
   begin	
		/*
		** 18576, "%1!: Failed to update cached info for object-id '%2!' and index-id '%3!' 
		**		of database '%4!'."
		*/
		raiserror 18576, "sp_forceonline_object", @objid, @indid, @dbname 
		return(1)
   end
end

/* Now update the master..sysattributes */
if (@option = "all_users")
begin
	/* this is to drop the item */
      	delete master.dbo.sysattributes
	where	class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type AND
		object = @dbid AND
	      object_info1 = @objid AND
	      object_info2 = @indid
end
else
begin
	if (@state != @old_state)
		update master.dbo.sysattributes
      	  	set char_value = @state 
        where class = @class AND
             	attribute = @attrib_id 	AND
            	object_type = @object_type AND
              	object = @dbid	   AND
	      object_info1 = @objid AND
	      object_info2 = @indid
end

/* Just say what happened */
if (@state != @old_state)
	begin
	/*
	** 18577, "%1!: The object with object-id '%2!' and index-id '%3!' of database '%4!' is 
	**		now in state '%5!'."
	*/
	exec sp_getmessage 18577, @msg output
	print @msg, "sp_forceonline_object", @objid, @indid, @dbname, @option 
	end
else
	begin
	/*
	** 18578, "%1!: The object with object-id '%2!' and index-id '%3!' of database '%4!' is 
	**		already in state '%5!'."
	*/
	exec sp_getmessage 18578, @msg output
	print @msg, "sp_forceonline_object", @objid, @indid, @dbname, @option 
	return(1)
	end

/* get the number of remaining suspect objects */
select @num = count(*)
   from master.dbo.sysattributes
   where	class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid 

/* if all objects are online, say so */
if (@num = 0)
begin
	/*
	** 18438, "%1!: All pages/objects in database '%2!' are now online."
	*/
	exec sp_getmessage 18438, @msg output
	print @msg, "sp_forceonline_object", @dbname 
	return(0)
end

if (@printopt = "no_print")
	return(0)

/* 
** if dropping suspect object then list out the remaining suspect 
** objects in the db, otherwise print the status of the object. 
*/
if @action = 3
begin
  /*
  ** 18579, "%1!: The remaining suspect objects in database '%2!' are:"
  */
   exec sp_getmessage 18579, @msg output
   print @msg, "sp_forceonline_object", @dbname 
   select "DBName" = @dbname, "Objid" = convert(varchar(12),int_value),
	"Object" = convert(varchar(15), object_name(object_info1, @dbid)),
        "Index" =  convert(varchar(4), object_info2),
	 "status" = substring(char_value,1,9)
   from master.dbo.sysattributes
   where	class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid 
end
else
begin
   select "DBName" = @dbname, "Objid" = convert(varchar(12),int_value),
	"Object" = convert(varchar(15), object_name(object_info1, @dbid)),
        "Index" =  convert(varchar(4), object_info2),
	 "status" = substring(char_value,1,9)
   from master.dbo.sysattributes
   where	class = @class AND
   	attribute = @attrib_id 	AND
   	object_type = @object_type	AND
   	object = @dbid AND
	      object_info1 = @objid AND
	      object_info2 = @indid
end
return (0)
go
exec sp_procxmode 'sp_forceonline_object', 'anymode'
go
grant execute on sp_forceonline_object to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setsuspect_error')
begin
	drop procedure sp_setsuspect_error
end
go
print "Installing sp_setsuspect_error"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
*/

/*  *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING 
**
**  This procedure is solely for testing and debugging purposes only.
**           DO NOT USE IT ON PRODUCTION SYSTEMS.
*/

create procedure sp_setsuspect_error
@dbname	varchar(255) = NULL,
@errornum int = -1
as
declare @dbid 			int,		 /* dbid of the database */
	@attrib_id 		int,
	@action			int,
	@object_type		varchar(2),
	@msg 			varchar(1024),
	@class			int,
	@errortype		int,
	@error_freq		int,
	@sptlang		int,
	@sysdbid		int,
	@comment		varchar(255),
	@whichone		int   	/* which language? */

select @attrib_id = 4  		/* attribute is SUSPECT error */
select @object_type = 'D'
select	@errortype = 80 
select	@error_freq = 80
select @class = 10



if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end


/*
**  If no @dbname given, assume the current database
*/

if @dbname is null
	select @dbname = db_name()

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = dbid from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	exec sp_getmessage 17421, @msg output
	print @msg
	return (1)
end

if @dbname in ("master", "model", "tempdb", "sybsecurity", "sybsystemprocs", "sybsystemdb")
begin
        /*
        ** 18523, "'%1!': Not allowed for System databases."
        */
        raiserror 18523, "sp_setsuspect_error"
        return (1)
end

/*
** If only dbname is provided, then display the setting
*/

if @errornum = -1
begin

	select 	"DBName" = @dbname, "Error Num" = int_value
	from master.dbo.sysattributes
	where  class = @class AND
	attribute    = @attrib_id 	AND
	object_type  = @object_type	AND
	object 	     = @dbid

	return(0)
end

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
begin
	/*
	** 18524, "'%1!':Permission denied. This operation requires System Administrator (sa_role) role."                                
	*/
	exec sp_getmessage 18524, @msg output
	print @msg, "sp_setsuspect_error"
	return (1)
end


if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	exec sp_getmessage 17428, @msg output
	print  "sp_setsuspect_error: '%1!'", @msg
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	exec sp_getmessage 17260, @msg output
	print @msg, "sp_setsuspect_error"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1


/*
** if an entry already exists for this database then update the entry,
** otherwise insert a new row for this database.
** When updating, change only the config value (object_info2) and not the
** current value (int_value). The config value will take effect only
** during the next boot/load time recovery of the database, during which
** time the current value will be updated to the config value.
*/
IF not exists(select * from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type AND
		object = @dbid AND
		int_value = @errornum)
begin
	select @comment = "This error number will be added to the errors Recovery Fault Isolation can isolate"
        insert master.dbo.sysattributes
        (class, attribute, object_type,object,object_info1,int_value)
        values(@class, @attrib_id, @object_type, @dbid,@errornum,
	        @errornum)
end



/*
** Display the setting 
*/

select "Database Name" = @dbname,
	"Error Num" = int_value
from master.dbo.sysattributes
where   class = @class AND
attribute =  @attrib_id    AND
object_type =@object_type  AND
object = @dbid AND
int_value = @errornum


/*
** 18526, "'%1!': The new values will become effective during the next recovery of the database."
*/
exec sp_getmessage 18526, @msg output
print @msg, "sp_setsuspect_error", @dbname
return (0)
go
exec sp_procxmode 'sp_setsuspect_error', 'anymode'
go
grant execute on sp_setsuspect_error to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setsuspect_granularity')
begin
	drop procedure sp_setsuspect_granularity
end
go
print "Installing sp_setsuspect_granularity"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**			database options."                                
** 18523, "%1!: Not allowed for System databases."
** 18524, "%1!: Permission denied. This operation requires System Administrator (sa_role) role."                                
** 18525, "%1!: Suspect granularity option '%2!' is not valid."
** 18526, "%1!: The new values will become effective during the next recovery of the database."
** 18527, "%1!: Object level suspect granularity is not supported in this release."
*/

create procedure sp_setsuspect_granularity
@dbname	varchar(255) = NULL,
@susgran	varchar(8)  = NULL,
@option	varchar(10) = NULL /* valid options - read_only and offline (only to be used during testing) */
as
declare @dbid 				int,		 /* dbid of the database */
	@attrib_id 			int,
	@action				int,
	@object_type 			varchar(2),
	@msg 				varchar(1024),
	@cur_susgran			int,
	@cfg_susgran			int,
	@display_susgran_cur 		varchar(10),
   	@display_susgran_cfg 		varchar(10),
	@susgran_val			int,
	@default_susgran		int,
	@suspectpagebit			int,
	@class				int,
	@sysdbid			int,
	@option_val			varchar(10)

select @action = 1			/* add or modify entry */
select @attrib_id 	= 0  		/* attribute is SUSPECT GRANULARITY */
select @object_type = 'D'
select @default_susgran = 0
select @cur_susgran = 0
select @cfg_susgran = 0
select @suspectpagebit = 32
select @class = 10

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1


/*
**  If no @dbname given, assume the current database
*/

if @dbname is null
	select @dbname = db_name()

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

/*
**  If @dbname not found, say so.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	exec sp_getmessage 17421, @msg output
	print  "sp_setsuspect_granularity: '%1!'", @msg
	return (1)
end

if @dbname in ("master", "model", "tempdb", "sybsecurity", "sybsystemprocs", "sybsystemdb")
begin
	/*
	** 18523, "'%1!': Not allowed for System databases."
	*/
	raiserror 18523, "sp_setsuspect_granularity"
	return (1)
end
/*
** If only dbname is provided, then display the setting
*/

if @susgran is NULL
	goto display_settings

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
begin
	/*
	** 18524, "'%1!':Permission denied. This operation requires System Administrator (sa_role) role."                                
	*/
	raiserror 18524, "sp_setsuspect_granularity"
	return (1)
end


if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	exec sp_getmessage 17428, @msg output
	print  "sp_setsuspect_granularity: %1!", @msg
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_setsuspect_granularity"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/

if ((@susgran != "page") AND (@susgran != "object" )
		AND (@susgran != "database"))
BEGIN
	/*
	**	18525, %1!: Suspect granularity option '%2!' is not valid.
	*/
	raiserror 18525, "sp_setsuspect_granularity", @susgran
	return(1)
END
if (@susgran = "object" )
BEGIN
	/*
	** 18527, %1!: Object level suspect granularity is not supported in 
	** 		this release.
	*/
	raiserror 18527, "sp_setsuspect_granularity", @susgran
	return(1)
END
if (@option != "read_only") AND (@option != "offline") AND (@option != "read/write") AND (@option = "")
begin
        /*
        **      18525, %1!: Suspect granularity option '%2!' is not valid.
        */
	raiserror 18525, "sp_setsuspect_granularity", @option
        return(1)
end


if @susgran = "page"
	select @susgran_val = 2
if @susgran = "object"
	select @susgran_val = 1
if @susgran = "database"
	select @susgran_val = 0

/*
** if an entry already exists for this database then update the entry,
** otherwise insert a new row for this database.
** When updating, change only the config value (object_info2) and not the
** current value (int_value). The config value will take effect only
** during the next boot/load time recovery of the database, during which
** time the current value will be updated to the config value.
*/
if exists(select * from master.dbo.sysattributes where
		class = @class AND
		attribute 	= @attrib_id 	AND
		object_type = @object_type	AND
		object = @dbid)
begin
	/* get the configured suspect granularity value and the option value */
	select 	@cur_susgran = int_value,
		@cfg_susgran = object_info2,
		@option_val = substring(char_value, 1, 10)
	from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id AND
		object_type = @object_type AND
		object = @dbid

	/* 
	** if configured granularity is different from new value or the 
	** configured option is different from new value then the 
	** entry must be updated.
	*/
	if (@cfg_susgran != @susgran_val  OR
	   	@option_val != @option)
	begin
	    update master.dbo.sysattributes
	    set object_info2 = @susgran_val, 
	         char_value = @option
	    where class = @class AND
	          attribute = @attrib_id  AND
	          object_type = @object_type AND
	          object = @dbid
	end
	/*
	** If the requested suspect granularity is database and the current
	** suspect granularity also happens to be database, then this represents
	** the default setting for the database that does not require any entry
	** in master..sysattributes. So delete the entry.
	*/
	if (@susgran = "database" AND @cur_susgran = 0)
	begin
		delete master.dbo.sysattributes
	        where class = @class AND
                  attribute = @attrib_id  AND
                  object_type = @object_type AND
                  object = @dbid

		select @cfg_susgran = 0
	end
end
else
begin
  insert master.dbo.sysattributes
        (class, attribute, object_type,object,int_value,object_info2,char_value)
        values(@class, @attrib_id, @object_type, @dbid,
        @default_susgran, @susgran_val, @option)

	/* This is the first time, so clear the bit in status2 field of sysdatabases */
	update master.dbo.sysdatabases
	set status2 = status2 & @suspectpagebit
	where dbid = @dbid
end



/*
** Display the setting 
*/
display_settings:

select 	@cur_susgran = int_value, 
	@cfg_susgran = object_info2,
	@option_val = substring(char_value, 1, 10)
from master.dbo.sysattributes
	where   class = @class AND
	attribute   = @attrib_id   AND
	object_type = @object_type AND
	object = @dbid

if (@cur_susgran = 2) select @display_susgran_cur = 'page'
if (@cur_susgran = 1) select @display_susgran_cur = 'object'
if (@cur_susgran = 0) select @display_susgran_cur = 'database'
if (@cfg_susgran = 2) select @display_susgran_cfg = 'page'
if (@cfg_susgran = 1) select @display_susgran_cfg = 'object'
if (@cfg_susgran = 0) select @display_susgran_cfg = 'database'

if @option_val is NULL
	select	@option_val = "read/write"
select 	"DB Name"= convert(varchar(20), @dbname),
	"Cur. Suspect Gran." = convert(varchar(10), @display_susgran_cur),
   	"Cfg. Suspect Gran." = convert(varchar(10), @display_susgran_cfg),
	"Online mode" = @option_val 

if @susgran is NULL
	return 0

/*
** 18526, "'%1!': The new values will become effective during the next recovery of the database."
*/
exec sp_getmessage 18526, @msg output
print @msg, "sp_setsuspect_granularity", @dbname
return (0)
go
exec sp_procxmode 'sp_setsuspect_granularity', 'anymode'
go
grant execute on sp_setsuspect_granularity to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setsuspect_threshold')
begin
	drop procedure sp_setsuspect_threshold
end
go
print "Installing sp_setsuspect_threshold"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 18523, "'%1!': Not allowed for System databases."
** 18524, "'%1!': Permission denied. This operation requires System Administrator (sa_role) role."                                
** 18526, "'%1!': The new values will become effective during the next recovery of the database."
** 18528, sp_setsuspect_threshold: Suspect Threshold value '%1!' is not valid
** 18529, sp_setsuspect_threshold: Not allowed because '%1!' has database level suspect granularity 
*/

create procedure sp_setsuspect_threshold
@dbname	varchar(255) = NULL,
@threshold	int = NULL
as
declare @dbid 			int,		 /* dbid of the database */
	@attrib_id 		int,
	@action			int,
	@object_type		varchar(2),
	@msg 			varchar(1024),
	@cur_threshold		int,
	@cfg_threshold		int,
	@default_threshold	int,
	@sptlang		int,
	@class			int,
	@whichone		int,   	/* which language? */
	@cfg_susgran		int,
	@sysdbid		int

select @attrib_id = 1  		/* attribute is SUSPECT THRESHOLD */
select @object_type = 'D'
select @default_threshold = 20
select @cur_threshold = 20 
select @cfg_threshold = 20
select @class = 10
select @cfg_susgran = 0

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid,  @whichone = 0

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end


/*
**  If no @dbname given, assume the current database
*/

if @dbname is null
	select @dbname = db_name()

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

/*
**  If @dbname not found, say so.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	exec sp_getmessage 17421, @msg output
	print  "sp_setsuspect_threshold: '%1!'", @msg
	return (1)
end

if @dbname in ("master", "model", "tempdb", "sybsecurity", "sybsystemprocs", "sybsystemdb")
begin
	/*
	** 18523, "%1!:Not allowed for System databases."
	*/
	raiserror 18523, "sp_setsuspect_threshold"
	return (1)
end

/*
** If only dbname is provided, then display the setting
*/

if @threshold is NULL
begin

	select 	@cur_threshold = int_value, 
		@cfg_threshold = object_info2
	from master.dbo.sysattributes
	where  class = @class AND
	attribute    = @attrib_id 	AND
	object_type  = @object_type	AND
	object 	     = @dbid

	select 	"DB Name" = @dbname,
		"Cur. Suspect threshold" = @cur_threshold,
		"Cfg. Suspect threshold" = @cfg_threshold
	return(0)
end

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
begin
	/*
	** 18524, "%1!:Permission denied. This operation requires System Administrator (sa_role) role."                                
	*/
	raiserror 18524, "sp_setsuspect_threshold"
	return (1)
end


if db_name() != "master"
begin
	/*
	** 17428, "You must be in the 'master' database in order to change database options."                                
	*/
	exec sp_getmessage 17428, @msg output
	print  "sp_setsuspect_threshold: %1!", @msg
	return (1)
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, "sp_setsuspect_threshold"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1

/*
** Check to see that the input params are correct and then hook up with
** Sysattributes table to enter data.
*/

if (@threshold < 0) 
BEGIN
	/*
	** 18528, sp_setsuspect_threshold: Suspect Threshold value '%1!' is not valid
	*/
	raiserror 18528, @threshold
	return(1)
END

/* get the configured suspect granularity value */
select 	
    @cfg_susgran = object_info2	
from master.dbo.sysattributes
where   class = @class AND
attribute   = 0   AND
object_type = @object_type AND
object = @dbid

/* if configured suspect granularity is database, then return error */
if (@cfg_susgran = 0)
begin
	/*
	** 18529, sp_setsuspect_threshold: Not allowed because '%1!' has database level suspect granularity 
	*/
	raiserror 18529, @dbname
	return(1)
end


/*
** if an entry already exists for this database then update the entry,
** otherwise insert a new row for this database.
** When updating, change only the config value (object_info2) and not the
** current value (int_value). The config value will take effect only
** during the next boot/load time recovery of the database, during which
** time the current value will be updated to the config value.
*/
IF exists(select * from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type	AND
		object = @dbid)
begin
        update master.dbo.sysattributes
        set object_info2 = @threshold
                where   class = @class AND
                attribute = @attrib_id  AND
                object_type = @object_type AND
                object = @dbid
end
else
begin
        insert master.dbo.sysattributes
        (class, attribute, object_type,object,int_value,object_info2)
        values(@class, @attrib_id, @object_type, @dbid,
        @default_threshold, @threshold)
end



/*
** Display the setting 
*/

select "Database Name" = @dbname,
	"Cur. Suspect Threshold" = int_value, 
	"Cfg. Suspect Threshold" = object_info2
from master.dbo.sysattributes
where   class = @class AND
attribute =  @attrib_id    AND
object_type =@object_type  AND
object = @dbid

/*
** 18526, "'%1!': The new values will become effective during the next recovery of the database %2!."
*/
exec sp_getmessage 18526, @msg output
print @msg, "sp_setsuspect_threshold", @dbname
return (0)
go
exec sp_procxmode 'sp_setsuspect_threshold', 'anymode'
go
grant execute on sp_setsuspect_threshold to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dbrecovery_order')
begin
	drop procedure sp_dbrecovery_order
end
go
print "Installing sp_dbrecovery_order"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** 17260, "Can't run %1! from within a transaction." 
** 17421, "No such database -- run sp_helpdb to list databases."
** 17422, "The 'master' database's options can not be changed."
** 17428, "You must be in the 'master' database in order to change
**	database options."                                
** 18600, "%1!: Illegal option. The only legal option is 'force'."
** 18601, "%1!: The database %2! has no user specified recovery order."
** 18602, "%1!: The database %2! already has the user specified recovery order of %3!."
** 18603, "%1!: The recovery order %2! is already in use for database %3!"
** 18604, "%1!: Invalid recovery order. The next valid recovery order is: %2!"
** 18605, "%1!: The database '%2!' has no user specified recovery order.
** 18607, "%1!: No databases have user specified recovery order. All databases will 
**             be recovered in database id order."
** 18608, "%1!: Delete row from master.dbo.sysattributes failed. Command aborted."
** 18609, "%1!: Update row of master.dbo.sysattributes failed. Command aborted."
** 18610, "%1!: Insert row to master.dbo.sysattributes failed. Command aborted."
** 19110, "%1: Illegal mode for recovery order. The only legal modes are 
**	  'strict' or 'relax'."
** 19995, "You must define the recovery order of the database '%1!' before 
**	   defining the recovery order of any database that uses it as a template 
**	   database."
** 19996, "The recovery order of database '%1!' cannot precede the recovery order 
**	'%2!' of its template database '%3!'."
** 19997, "You must delete the recovery order of any database that uses this 
**	  database as template before changing the template database recovery order."
*/
create procedure sp_dbrecovery_order
@dbname	varchar(30) = NULL,
@rec_order	int = -123456,
@option 	char(6) = NULL,
@mode	 	char(10) = NULL
as
declare @dbid 	 		int,		 /* dbid of the database */
	@dbid1 			int,		 /* dbid of the database */
	@dbid2 			int,		 /* dbid of the database */
	@attrib_id 		int,
	@dbname1		sysname,
	@name			sysname,
	@object_type 		varchar(2),
	@msg 			varchar(250),
	@sysattr_over		int,
	@sysdb_over		int,
	@order			int,
	@class			int,
	@sysdbid		int,
	@high_rec_order		int,
	@exists			int,
	@procname		varchar(20),
	@error_status		int,
	@templatedb		sysname,
	@template_order		int

select @attrib_id 	= 6  		/* attribute is  RECOVERY ORDER */
select @object_type = 'D'
select @class = 10
select @sysattr_over = 0
select @sysdb_over = 0
select @exists = 0
select @procname = "sp_dbrecovery_order"
select @error_status = 0

if @@trancount = 0
begin --{
	set chained off
end --}

set transaction isolation level 1

/* First, Check all the parameters */

/*
**  If no @dbname given, display the recovery order of all databases
*/

if @dbname is null
	goto display_settings_all

/*
**  Verify the database name and get the @dbid 
*/
select @dbid = db_id(@dbname) 

/*
**  If @dbname not found, say so.
*/
if @dbid is NULL
begin --{
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end --}

if @dbname in ("master", "model", "tempdb", "sybsecurity", "sybsystemprocs", "sybsystemdb")
begin --{
	/*
	** , "'%1!':Not allowed for System databases."
	*/
	raiserror 18523, @procname 
	return (1)
end --}

/* The database recovery order cannot be set for an archive database. */
if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid
			and   (status3 & 4194304) = 4194304)
begin --{
	/* Cannot run '%1!' on an archive database." */
	raiserror 19424, @procname
	return (1)
end --}

/* In SDC, specify rec order for local system tempdb is not allowed either */
if @@clustermode = "shared disk cluster"  
begin --{
	declare @localsystempdbbit int
	select @localsystempdbbit = number
		from master.dbo.spt_values
		where type = "D3" and name = "local system temp db"

   	if exists (select 1 from master.dbo.sysdatabases where dbid = @dbid and 
		(status3 & @localsystempdbbit) = @localsystempdbbit)
	begin --{
		raiserror 18523, @procname
		return (1)
	end --}
end --}


/*
** If only dbname is provided, then display the settings for the database
*/
if (@rec_order = -123456)
        goto display_settings

if @option is not null 
begin --{
	if @option != "force"
	begin --{
		/* 18600, "%1!: Illegal option. The only legal option is 'force'." */
		raiserror 18600, @procname
		return(1)
	end --}
end --}

if @mode is not null 
begin --{
	if (@mode not in ("strict", "relax"))
	begin --{
		raiserror 19110, @procname
		return(1)
	end --}
end --}
else
begin --{
	/* Default mode is relax */
	select @mode = "relax"
end --}

/*
** the following logic till the label "display_settings" is for setting the
** the recovery order
*/

/*
**  Only the Accounts with SA role can execute it.
**  Call proc_role() with the required SA role.
*/
if (proc_role("sa_role") < 1)
	return (1)

if db_name() != "master"
begin --{
	/*
	** 17428, "You must be in the 'master' database in order to change database options." 
	*/
	raiserror 17428
	return (1)
end --}

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin --{
	/*
	** 17260, "Can't run %1! from within a transaction." 
	*/
	raiserror 17260, @procname
	return (1)
end --}
else
begin --{
	set chained off
end --}

set transaction isolation level 1

/*
** If this database is being used as a template, its recovery order
** cannot be changed.
*/
select s.name, s.def_remote_loc as templatedb
into #template
from master.dbo.sysattributes a,
master.dbo.sysdatabases s
where   db_id(s.name) = a.object and
	s.name != @dbname and
	def_remote_loc = @dbname and
	class = @class and
	attribute = @attrib_id and
	object_type = @object_type
if (@@rowcount > 0)
begin --{
	exec sp_autoformat #template
	raiserror 19997
	return (1)
end --}

/*
** if the command is for deleting the recovery order, then delete the row and
** update the rest 
*/
if @rec_order = -1 
begin --{
	/* first note the current recovery order if it exists */
	if not exists (select * from master.dbo.sysattributes
		where  class = @class AND
			attribute = @attrib_id  AND
			object_type = @object_type AND
			object = @dbid)
	begin --{
		/* print error and exit */
		/* 18601, "%1!: The database %2! has no user specified recovery order." */
		raiserror 18601, @procname,@dbname
		return (1)
	end --}
	select @rec_order = int_value from master.dbo.sysattributes
	where  class = @class AND
                        attribute = @attrib_id  AND
                        object_type = @object_type AND
                        object = @dbid
	/* now delete the row and update the rest within a transaction.*/
	begin transaction delete_update

      	delete master.dbo.sysattributes
      	where  class = @class AND
      		attribute = @attrib_id  AND
      		object_type = @object_type AND
      		object = @dbid
	if (@@error != 0)
	begin --{
		/* 18608, "%1!: Delete row from master.dbo.sysattributes failed. Command aborted." */
		raiserror 18608, @procname
		rollback tran delete_update
		select @error_status = 1
		goto display_settings_all
	end --}
      /* 
      ** now fixup the recovery order of the databases with higher recovery order
      ** by decrementing by one
      */
      	select @rec_order = @rec_order + 1
      	while (exists (select * from master.dbo.sysattributes 
      		where  class = @class AND
      			attribute = @attrib_id  AND
      			object_type = @object_type AND
      			int_value = @rec_order))
      	begin --{
      		update master.dbo.sysattributes
      		set int_value = @rec_order -1 
      		where  class = @class AND
      			attribute = @attrib_id  AND
      			object_type = @object_type AND
      			int_value = @rec_order

		if (@@error != 0)
		begin --{
			/* 18609, "%1!: Update row of master.dbo.sysattributes failed. Command aborted."*/
			raiserror 18609, @procname
			rollback tran delete_update
			select @error_status = 1
			goto display_settings_all
		end --}
      		select @rec_order = @rec_order + 1
      	end --}
	commit transaction delete_update
	goto display_settings_all
end --}

/*
** We must define the recovery order of a template before defining
** the recovery order of any database that uses it as a template
** database. This must be done after testing it's not -1, that
** would be smaller than anyone else, but it's used to delete
** the entry.
*/
select @templatedb = def_remote_loc
from master.dbo.sysdatabases
where name=@dbname

if (@templatedb is not null)
begin -- {
	select @template_order=int_value
	from master.dbo.sysattributes 
	where	object = db_id(@templatedb) and
		class = @class and
		attribute = @attrib_id and
		object_type = @object_type
	
	if (@template_order is NULL)
	begin --{
		raiserror 19995, @templatedb
		return (1)
	end --}
	
	if (@rec_order <= @template_order)
	begin --{
		raiserror 19996, @dbname, @template_order, @templatedb
		return (1)
	end --}
end --}

/*
** if an entry already exists for this database print error, display the order and exit
*/
if exists(select * from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type	AND
		object = @dbid)
begin --{
	select @order = int_value from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id  AND
		object_type = @object_type      AND
		object = @dbid
	/* 18602, "%1!: The database %2! already has the user specified recovery order of %3!." */
	raiserror 18602, @procname, @dbname, @order
	return (1)
end --}

/*
** If there is another database at this order, then display error and exit
*/

if exists(select * from master.dbo.sysattributes where
		class = @class AND
		attribute = @attrib_id 	AND
		object_type = @object_type	AND
		int_value = @rec_order) 
begin --{
	select @dbid1 = object from master.dbo.sysattributes where
		class = @class AND
                attribute = @attrib_id  AND
                object_type = @object_type      AND
                int_value = @rec_order
	select @exists = 1
	if (@dbid != @dbid1 AND @option is null) 
	begin --{
		select @dbname1 = db_name(@dbid1)
		/* 18603, "%1!: The recovery order %2! is already in use for database %3!." */
		raiserror 18603, @procname,@rec_order, @dbname1 
		return (1)
	end --}
end --}


/* find the highest existing user defined recovery order */
select @high_rec_order = max(int_value) from master.dbo.sysattributes where
                class = @class AND
                attribute = @attrib_id  AND
                object_type = @object_type      

/* if no recovery order exists, initialize high_recovery_order */
if (@high_rec_order is NULL)
	select @high_rec_order = 0

/* the next valid recovery order is one greater than the current high */
select @high_rec_order = @high_rec_order + 1

/* Check for validity of the requested recovery order. 
** It should be between 1 and high_rec_order OR 
** if less than high_rec_order then it must have "force" option.
*/
if ((@rec_order < 1) OR (@rec_order > @high_rec_order) OR
    ((@rec_order < @high_rec_order) AND @option != "force"))
begin --{
	/* 18604, "%1!: Invalid recovery order. The next valid recovery order is: %2!" */
	raiserror 18604, @procname,  @high_rec_order
	return(1)
end --}

/* 
** now the specified recovery order is equal to high_rec_order or
** between 1 and current maximum user specified recovery order with "force" option.
*/

/* if  between 1 and high_rec_order then increment all the recovery orders greater 
** than the rec_order and then insert the new row */
begin transaction update_insert

if (@rec_order < @high_rec_order)
begin --{
	while (1 = 1)
	begin --{
		if (@high_rec_order <= @rec_order)
			break
         	update master.dbo.sysattributes
         	set int_value = @high_rec_order
         	where  class = @class AND
               		attribute = @attrib_id  AND
                	object_type = @object_type AND
			int_value = @high_rec_order - 1	 
		if (@@error != 0)
		begin --{
			/* 18609, "%1!: Update row of master.dbo.sysattributes failed. Command aborted." */
			raiserror 18609, @procname
			rollback transaction update_insert
			select @error_status = 1
			goto display_settings_all
		end --}
		select @high_rec_order = @high_rec_order - 1
	end --}
end --}
insert master.dbo.sysattributes
        (class, attribute, object_type,object,int_value,comments)
        values(@class, @attrib_id, @object_type, @dbid,@rec_order, @mode)
if (@@error != 0)
begin --{
	/* 18610, "%1!: Insert row to master.dbo.sysattributes failed. Command aborted." */	
	raiserror 18610, @procname
	rollback transaction update_insert
	select @error_status = 1
	goto display_settings_all
end --}

commit transaction update_insert
goto display_settings_all


/*
** Display the setting - only one db 
*/
display_settings:
if exists (select * from master.dbo.sysattributes
		where class = @class AND
                attribute = @attrib_id AND
                object_type = @object_type AND
                object = @dbid)
begin --{
	select 	"Database Name" = convert(varchar(13), @dbname), 
		"Database id" =  "    " + convert(varchar(6), @dbid), 
		"Recovery Order" =  "   " + convert(varchar(6), int_value),
		"Mode" = "   " + convert(varchar(6), comments)
				 from master.dbo.sysattributes
	where class = @class AND
		attribute = @attrib_id AND
		object_type = @object_type AND
		object = @dbid
end --}
else
begin --{
	/* 18601, "%1!: The database '%2!' does not have user specified recovery order." */
	raiserror 18601, @procname, @dbname
end --}
return (@error_status)
		

/*
** Display the setting - ALL 
*/
display_settings_all:
if exists (select * from master.dbo.sysattributes
                where class = @class AND
                attribute = @attrib_id AND
                object_type = @object_type)
begin --{
	print "The following databases have user specified recovery order:"
	select 	"Database Name"  = convert(varchar(20), db_name(object)),
		"Database Id"    = "    " + convert(varchar(6), object),
		"Recovery Order" = "    " + convert(varchar(6), int_value),
		"Mode" = "   " + convert(varchar(6), comments)
			 from master.dbo.sysattributes
	where class = @class AND
                attribute = @attrib_id AND
                object_type = @object_type
                order by int_value
	print "The rest of the databases will be recovered in default database id order."
end --}
else
begin --{
	/* 18607, "%1!: No databases have user specified recovery order. All data
	**		bases will be recovered in database id order."
	*/
	raiserror 18607, @procname
end --}
return(@error_status)	
go
exec sp_procxmode 'sp_dbrecovery_order', 'anymode'
go
grant execute on sp_dbrecovery_order to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dbcc_scale_factor')
begin
	drop procedure sp_dbcc_scale_factor
end
go
print "Installing sp_dbcc_scale_factor"
go

/*
** Messages for "sp_dbcc_scale_factor"	
*/

/*
** This procedure takes three parameters
** a size in kilobytes                  (input)
** a scale factor (1024 or 1024 * 1024) (output)
** a display unit, char 'K', 'M', 'G'   (output)
**
** The cutoff boundaries are set at
** > 10 G (10485760 k) => G, scale 1024 * 1024
** > 10 M (10240 k) => M, scale 1024
** else K, scale 1
**
** Call using
**	execute sp_dbcc_scale_factor <unit to scale>,
**		@scale_factor = @<name for factor> output,
**		@scale_letter = @<name for unit> output
**
** where name for factor represents ant int
** 	 name for unit represents a char(1)
**
** It is installed in sybsystemprocs for use by
** sp_plan_dbccdb and later for use if dbccdb is installed
** by sp_dbcc_evaluatedb.
**
** RESOLVE:
** Future Issue:
**
** size_in_k is an int.
** int on SQL server is 2^31 max ~ 2 10^9
** hence will not allow us to go past 2 10^12 bytes
** or 2 TB. This can be solved my making the input a
** numeric, in which case callers would also need
** to use a numeric as input value. We will not address this here.
*/

create procedure sp_dbcc_scale_factor 
( 
	@size_in_k	int,
	@scale_factor	int output,
	@scale_letter	char(1) output
)
as
begin
	if @@trancount = 0
	begin
      	  set chained off
	end
 
	set transaction isolation level 1
	set nocount on
	if (@size_in_k > 10485760)
	begin
		select @scale_factor = (1024 * 1024)
		select @scale_letter = 'G'
	end
	else
	begin
		if (@size_in_k > 10240)
		begin
			select @scale_factor = 1024
			select @scale_letter = 'M'
		end
		else
		begin
			select @scale_factor = 1
			select @scale_letter = 'K'
		end
	end
end
go
exec sp_procxmode 'sp_dbcc_scale_factor', 'anymode'
go
grant execute on sp_dbcc_scale_factor to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_plan_dbccdb')
begin
	drop procedure sp_plan_dbccdb
end
go
print "Installing sp_plan_dbccdb"
go

/*
** Messages for "sp_plan_dbccdb"	
**
** 17421, "No such database -- run sp_helpdb to list databases."
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
** 17260, "Can't run %1! from within a transaction."
** 18454, "Recommended size for %1! database is %2!MB (data = %3!MB, log = %4!MB).", 
** 18456, "Recommended devices for %1! are:"
** 18457, "No suitable devices for %1! in master..sysdevices."
** 18458, "Recommended values for workspace size, cache size and worker process count are:"
** 18459, "%1! database already exists with size %2!MB."
*/

create procedure sp_plan_dbccdb ( 
	@dbname varchar(255) = null )
as
declare @dbid smallint, @dbid1 smallint, @dbid2 smallint
declare @dbcc_dbid int
declare @scanws_size int
declare	@textws_size int
declare	@cache_size int
declare	@wt_count smallint
declare	@devsize int
declare @name varchar(255)
declare	@ldev varchar(255), @physdev varchar(255)
declare @dbcc_dbname varchar(255)
declare @dbccdb_size int
declare @log_size int, @data_size int
declare @size float
declare @msg varchar(1024) 
declare @min_wssize int			/* minimum size of workspace */
declare @new_min_wssize int		/* revised minimum size of workspace */
declare @min_cachesize int		/* minimum size of cache */
declare @KB_per_page int		/* number of KB per page */
declare @divideby int
declare @displayunit char
declare @divideby_cm int
declare @displayunit_cm char
declare @dbo int
declare @dummy int
declare	@scratchdb sysname
declare @qrystr varchar(312)
declare @adb_stat int
declare @comp_size int			/* compression status */
declare @comp_stat int			/* compression status */
declare @compdata_stat int		/* data compression status */
declare @complog_stat int		/* log compression status */
declare @status3 int			/* status3 from sysdatabases */
declare @adb_dbid int			/* archive database id */

/*
** These variables are used for formatting the output
*/
declare @str1 char(30), @str2 char(8), @str3 char(8)
declare @str4 char(6), @str5 char(9), @str6 char(20)
declare @longstr varchar(255)
declare @tempcol varchar(30)

/*
** Disallow this procedure within a transaction since it 
** creates temporary tables
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_plan_dbccdb"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1
set nocount on

/* Get the number of KB per page */
select @KB_per_page = @@maxpagesize / 1024

/* Locate the archive database status */
select @adb_stat=number from master.dbo.spt_values
where name="archive database" and type="D3"

select @compdata_stat=number from master.dbo.spt_values
where name="compressed data" and type="D3"

select @complog_stat=number from master.dbo.spt_values
where name="compressed log" and type="D3"

select @comp_stat = @compdata_stat | @complog_stat

/*
** create tables for storing temporary results and declare
** cursors on them
*/
create table #dbcc_dblist(dbid int, ldev_name varchar(30), status3 int) 
			
declare cursor_dbcc_dblist cursor  for
	select dbid, status3 from #dbcc_dblist 

/*
** Insert dbid and devname for all valid normal databases in 
** #dbcc_dblist. The status3 is used to find whether an archive
** database has compressed data or log. Set it to 0 for non-archive
** databases.
*/
insert #dbcc_dblist(dbid, ldev_name, status3) 
	select distinct su.dbid, dev.name, 0
	from master..sysdevices dev, master..sysusages su,
		master..sysdatabases sd
	where su.dbid = sd.dbid and dev.cntrltype = 0 and
		su.vdevno = dev.vdevno and
		sd.status3 & @adb_stat = 0
		
/*
** Add dbid and devname for all the archive databases.
*/
declare cursor_adb cursor for
	select dbid, status3 from master.dbo.sysdatabases
	where (status3 & @adb_stat) != 0
		
open cursor_adb
fetch cursor_adb into @adb_dbid, @status3
while (@@sqlstatus = 0)
begin
	/*
	** Read the scratch database name from sysattributes.
	*/
	select @scratchdb = convert(sysname, char_value)
	from master.dbo.sysattributes
	where class=28
		and object_type="D"
		and object=@adb_dbid
		and attribute=0

	if (db_id(@scratchdb) is not null)
	begin
		/*
		** Add dump devices (location = 5) to the list
		** of used devices.
		*/
		select @qrystr = 'insert #dbcc_dblist(dbid, ldev_name, status3) ' +
			'select distinct @adb_dbid, dev.name, @status3 ' +
			'from master..sysdevices dev, '+ 
				@scratchdb + '.dbo.sysaltusages sa '+
			'where sa.dbid=@adb_dbid and ' +
				'sa.location = 5 and ' +
				'dev.status & 4 = 4 and ' +
				'sa.vdevno = dev.vdevno '
		exec (@qrystr)
	end
	fetch cursor_adb into @adb_dbid, @status3
end
close cursor_adb
deallocate cursor cursor_adb

create table #dbcc_devlist( ldev_name varchar(255), devsize int, flag int)

/*
** Get logical and physical names and size in KB of all physical devices
** in the system that have atleast 1MB space and set the flag to 0
*/
insert #dbcc_devlist(ldev_name, devsize, flag)
	select name, ((high-low) + 1) * @KB_per_page, 0
	from master..sysdevices
	where cntrltype = 0 and ((high-low) + 1) >= 512
		and status & 4 = 0
/*
** For each device in #dbcc_devlist, set the flag to 1 if the device
** is being used by a database in #dbcc_dblist
*/
update #dbcc_devlist set flag = 1 
	from #dbcc_dblist dl, #dbcc_devlist dev
	where dl.ldev_name = dev.ldev_name 

/* Validate the given database */
select @dbo = 0
if (@dbname is not null) 
begin
	select @dbid = dbid
	from master..sysdatabases where name = @dbname

	if (@dbid is null)
	begin
		/*
		** 17421, "No such database -- run sp_helpdb to list databases."
		*/
		raiserror 17421
		return (1)
	end

	delete from #dbcc_dblist where dbid != @dbid
	exec sybsystemprocs.dbo.sp_is_valid_user @dbo output, @dbname
end

/*
** Only the Database Owner (DBO) or
** Accounts with SA role can execute it.
*/
if ((@dbo != 1) and charindex("sa_role", show_role()) < 1)
begin
	/* 
	** Call proc_role() to generate the appropriate
	** audit record.
	*/
	select @dummy = proc_role("sa_role")
	if (@dbname is null) 
		/*
		** 18990, "You must be the System Administrator (SA) 
		** to execute this procedure with a NULL database name 
		** (dbname) parameter.
		*/
		raiserror 18990
	else
		/*
		** 17230, "You must be the System Administrator (SA) 
		** or the Database Owner (dbo) to execute this 
		** procedure."
		*/
		raiserror 17230

	return (1)
end

/*
** The minimum size of a workspace is 24 pages
*/
select @min_wssize = 24 

/*
** Create a temporary table for storing the configuration information
*/
create table #dbcc_config(dbid int, dbname varchar(30) null, 
		scanws_size int null, textws_size int null, 
		wt_count smallint null, cache_size int null,
		comp_size int null)
declare cursor_dbcc_config cursor for
	select dbname, scanws_size, textws_size, wt_count, 
		cache_size, comp_size
	from #dbcc_config 

/*
** The data_size determines the amount of space set to store fault data
** and statistics data (50KB + 500KB) for each checkstorage run. 
** We multiply this by 5 so that there enough space to store 5 instances 
** of results. If the dbcc database is dbccalt, we need space only for 
** storing results from dbccdb, otherwise we need space to store results 
** from all databases in master..sysdatabase except model, tempdb and 
** sybsystemprocs. log_size is set to 2MB (This is an arbitrary size.)
*/
if (@dbname = "dbccdb")
begin
	select @dbcc_dbname = "dbccalt"
	select @log_size = 2048
	select @data_size = 3000
end
else
begin
	select @dbcc_dbname = "dbccdb"
	select @log_size = 2048
	/*
	** Select all databases except model, tempdb and sybsystemprocs
	*/
	select @data_size = 3000 * (count(*) - 3)
		from master..sysdatabases
end

/*
** For each dbid in #dbcc_dblist table, calculate the configuration parameters
*/
open cursor_dbcc_dblist
fetch cursor_dbcc_dblist into @dbid, @status3
while (@@sqlstatus = 0) 
begin

	/*
	** Get the database name
	*/
	select @name = db_name(@dbid) 

	/*
	** check if there is already an entry for this database. 
	** If so, continue with the next entry. The table #dbcc_dblist
	** can have multiple rows for a database if that databse resides
	** on multiple devices. We need to calculate the parameters
	** only once.
	*/
	if exists (select 1 from #dbcc_config where dbid = @dbid)
	begin
		fetch cursor_dbcc_dblist into @dbid, @status3
		continue
	end

	/*
	** Get the number of devices used by this database
	** Scale the number of worker processes based on the device count
	*/
	select @wt_count = count(*) from #dbcc_dblist 
		where #dbcc_dblist.dbid = @dbid

	if (@wt_count < 1)
		select @wt_count = 1
	else
		if (@wt_count > 128)
			select @wt_count = 128

	/*
	** Minimum cache size is 640K * @wt_count
	*/
	select @min_cachesize = 640 * @wt_count

	/*
	** The minimum workspace size depends on the number of worker
	** processes too. So adjust the value.
	*/
	select @new_min_wssize = ((@wt_count + 1) * 8)
	if (@new_min_wssize < @min_wssize)
		select @new_min_wssize = @min_wssize

	/*
	** Get the scanws size for this database which is 1.2% of 
	** database size. It is in units of pages.
	** If it's an archive database, the disk map has to be
	** found in sysaltusages in the scratch database.
	*/
	if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid 
			and (status3 & @adb_stat) != 0)
	begin
		/*
		** The original diskmap is stored in the sysaltusages catalog
		** in the scratch database with a location = 4.
		** Read the scratch database name from sysattributes first.
		*/
		select @scratchdb = convert(sysname, char_value)
		from master.dbo.sysattributes
		where 	class=28
			and object_type="D"
			and object=@dbid
			and attribute=0

		select @qrystr = 
			'select @scanws_size=ceiling(sum(size) * 0.012) from ' +
				@scratchdb + '.dbo.sysaltusages '+
			'where dbid=@dbid and location = 4'
		exec (@qrystr)

		/*
		** Set recommended compression pool size to 4MB per thread
		** if database is compressed.
		*/
		if ((@status3 & @comp_stat) != 0)
		begin
			select @comp_size = 4096 * @wt_count
		end
		else
		begin
			select @comp_size = 0
		end
	end
	else
	begin
		select @scanws_size = ceiling(sum(size) * 0.012) 
		from master..sysusages 
		where dbid = @dbid
		select @comp_size = 0
	end

	/*
	** set the size to the next multiple of 8 which is the unit
	** of allocation
	*/
	select @scanws_size = ((@scanws_size / 8) + 1) * 8 
	/*
	** Set the text workspace size to 25% of scan workspace and round
	** it off to a multiple of 8.
	*/ 
	select @textws_size = ceiling(@scanws_size * 0.25)
	select @textws_size = ((@textws_size / 8) + 1) * 8 

	/*
	** The minimum size required for workspaces are @new_min_wssize pages.
	** Set the sizes to @new_min_wssize if the current value is less 
	** than this.
	*/
	if (@scanws_size < @new_min_wssize)
	begin
		select @scanws_size = @new_min_wssize
	end
	if (@textws_size < @new_min_wssize)
	begin
		select @textws_size = @new_min_wssize
	end

	/*
	** For small databases (size < 20MB), increase the size of 
	** scanws by 8 pages. This is because checkstorage uses one 
	** full extent (8 pages) for page mapping. As a result 1.2%
	** of database size may not be enough for scanws if database is
	** small.
	*/
	if (@scanws_size <= 128)
		select @scanws_size = @scanws_size + 8
	/*
	** convert workspace sizes into KB
	*/
	select @scanws_size = @scanws_size * @KB_per_page
	select @textws_size = @textws_size * @KB_per_page

	/*
	** Set the cache size to 20% of total workspace size.
	** The cache size is actually the size of 16K(or 64K) buffer
	** pool. The actual cache size must be @cache_size + 512K
	**
	** NOTE: since scanws ~ Sum(max two db size) * 1.2%
	** 		textws ~ scanws/4
	**	 then these quantities are comparable in size.
	**	 Cache will be set to 20% of the sum, so it
	**	 will always be less magnitude than these
	**	 quantities. So later, we can safely use
	**	 a single scale factor, divideby, so scale the
	**	 display unit. If however, these units are allowed
	**	 in the future to become asymmetric (eg vastly
	**	 different in magnitude) then one should consider
	** 	 using the approach in sp_dbcc_evaluatedb to
	**	 scale the quantities individually.
	*/
	select @cache_size = 
			ceiling((@scanws_size + @textws_size) * 0.2)
	if (@cache_size < @min_cachesize)
	begin
		select @cache_size = @min_cachesize
	end

	/*
	** Insert the values calculated for this database into
	** #dbcc_config table. This table is used for report generation
	*/
	insert into #dbcc_config(dbid, dbname, scanws_size, textws_size,
			wt_count, cache_size, comp_size) 
		values(@dbid, @name, @scanws_size, @textws_size, 
			@wt_count, @cache_size, @comp_size)

	fetch cursor_dbcc_dblist into @dbid, @status3
end

close cursor_dbcc_dblist

print ""

/*
** Calculate (in MB) the size of dbccdb database. Even though 
** checkstorage can be run concurrently on multiple databases,
** it is highly unlikely that users will run checkstorage on
** more than two databases concurrently. So determine the size of
** dbccdb based on the two largest databases in the server.
*/

select @dbid1 = dbid from #dbcc_config 
	group by dbid having sum(scanws_size) = max(sum(scanws_size)) 
	
select @dbid2 = dbid from #dbcc_config where dbid != @dbid1 
	group by dbid having sum(scanws_size) = max(sum(scanws_size)) 

select @size = (sum(scanws_size) + sum(textws_size)) 
	from #dbcc_config 
	where dbid = @dbid1 or dbid = @dbid2

/*
** calculate the total size for data and log (in MB). The workspace size 
** is increased by 20% to accommodate future expansion.
** NOTE: ceiling needs a float type to work. Add decimal point to
** 	achieve this.
*/
select @data_size = ceiling((@data_size + (@size * 1.2)) / 1024) 
select @log_size = ceiling(@log_size / 1024.0)
select @dbccdb_size = @data_size + @log_size 

/*
** 18454, "Recommended size for %1! database is %2!MB (data = %3!MB, log = %4!MB).", 
*/
exec sp_getmessage 18454, @msg output
print @msg, @dbcc_dbname, @dbccdb_size, @data_size, @log_size

print ""

/*
** If @dbcc_dbname exists, report so. Otherwise recommend a device
** for @dbcc_dbname
*/
select @dbcc_dbid = db_id(@dbcc_dbname)
if (@dbcc_dbid is not null)
begin
	select @dbccdb_size = (sum(size) * @KB_per_page) / 1024
		from master..sysusages 
		where dbid = @dbcc_dbid
	/*
	** 18459, "%1! database already exists with size %2!MB"
	*/
	exec sp_getmessage 18459, @msg output
	print @msg, @dbcc_dbname, @dbccdb_size
end
else
begin

	/*
	** Delete all devices which are being used by databases.
	** This is indicated by flag > 0
	*/
	delete from #dbcc_devlist where flag != 0

	/*
	** Get the total size of all free devices in MB. If the total
	** size is atleast @dbccdb_size, these devices can be used for
	** dbcc database.
	*/
	select @size = (sum(devsize) / 1024) from #dbcc_devlist 

	if (@size >= @dbccdb_size)
	begin
		/*
		** 18456, "Recommended devices for %1! are:"
		*/
		exec sp_getmessage 18456, @msg output
		print @msg, @dbcc_dbname
		print ""
		select "Logical Device Name" = ldev_name, 
				"Device Size (KB)" = devsize
		from #dbcc_devlist 
	end
	else
	begin
		/*
		** 18457, "No suitable devices for %1! in master..sysdevices"
		*/
		exec sp_getmessage 18457, @msg output
		print @msg, @dbcc_dbname
	end
end
print ""

/*
** Format and print the configuration parameters
*/
select @str1 = "dbname"
select @str2 = "scan ws"
select @str3 = "text ws"
select @str4 = "cache"
select @str5 = "comp mem"
select @str6 = "process count"
/*
** 18458, "Recommended values for workspace size, cache size and worker process count are:"
*/
exec sp_getmessage 18458, @msg output
print @msg
print ""
print  "%1! %2! %3! %4! %5! %6!", 
	@str1, @str2, @str3, @str4, @str5, @str6

open cursor_dbcc_config
fetch cursor_dbcc_config into @name, @scanws_size, @textws_size, @wt_count,
		@cache_size, @comp_size


while (@@sqlstatus = 0) 
begin
	/*
	** sizes are in KB. Find out the appropriate unit to use for
	** displaying these values.
	** NOTE: problem if size gets larger than MAXINT. This
	** represents 2 TB. Change input parameter and sproc
	** sp_dbcc_scale_factor if this limit is reached.
	*/
	execute sp_dbcc_scale_factor @cache_size,
		@scale_factor = @divideby output,
		@scale_letter = @displayunit output

	execute sp_dbcc_scale_factor @comp_size,
		@scale_factor = @divideby_cm output,
		@scale_letter = @displayunit_cm output

	/*
	** Convert all values to varchar for formatting purpose
	*/
	select @str1 = @name
	select @str2 = convert(varchar(8), ceiling(1.0 * @scanws_size / @divideby)) 
					+ @displayunit
	select @str3 = convert(varchar(8), ceiling(1.0 * @textws_size / @divideby)) 
					+ @displayunit
	select @str4 = convert(varchar(8), ceiling(1.0 * @cache_size / @divideby)) 
					+ @displayunit
	select @str5 = convert(varchar(9), ceiling(1.0 * @comp_size / @divideby_cm)) 
					+ @displayunit_cm
	select @str6 = convert (char(3), @wt_count)
	print  "%1! %2! %3! %4! %5! %6!", 
		@str1, @str2, @str3, @str4, @str5, @str6
	fetch cursor_dbcc_config into @name, @scanws_size, 
		@textws_size, @wt_count, @cache_size, @comp_size
end
print ""

close cursor_dbcc_config

/*
** Clean-up all temporary tables
*/
deallocate cursor cursor_dbcc_dblist
deallocate cursor cursor_dbcc_config

drop table #dbcc_dblist
drop table #dbcc_devlist
drop table #dbcc_config

return(0)

go
exec sp_procxmode 'sp_plan_dbccdb', 'anymode'
go
grant execute on sp_plan_dbccdb to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_reptostandby')
begin
	drop procedure sp_reptostandby
end
go
print "Installing sp_reptostandby"
go

/*
** Message for "sp_reptostandby"
** 17260, "Can't run %1! from within a transaction."
** 18407, "Usage: sp_reptostandby dbname [ , { ALL | L1 | NONE } ]"
** 18408, "The stored procedure must be executed with the name of
**         the current database."
** 18409, "The built-in function '%1!' failed. Please see the 
**         other messages printed along with this message."
** 18410, "The replication status of '%1!' is corrupt. Please contact 
**         Sybase Technical Support."
** 18411, "The replication status for database '%1!' is '%2!'."
** 18412, "The replication status for database '%1!' is already set to 
**         '%2!'. The replication status is not changed."
** 18413, "Due to a system failure, the replication status for '%1!' 
**         has not been changed."
** 18414, "The replication status for database '%1!' has been set to '%2!'."
** 18415, "ALL"
** 18416, "NONE"
** 18417, "L1"
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) 
**         or a user with REPLICATION authorization may execute this 
**         stored procedure."
*/
create procedure sp_reptostandby
@dbname		varchar(255) = NULL,
@setflag	varchar(20) = NULL,
@use_index	varchar(10) = NULL	/* Use index for off-row columns */
as
declare @all		varchar(20)
declare @none		varchar(20)
declare @l1		varchar(20)
declare @msg		varchar(1024)
declare	@off		varchar(20)
declare @procval	int
declare @dbuid		int
declare @curdb		varchar(255)
declare @dbid		int
declare @objid		int
declare @rep_constant	smallint
declare @tmpstr		varchar(200)
declare @curstat	int
declare @newstat	int
declare @sptlang	int
declare @curindstat	int
declare @lt_rep_all	int
declare @lt_rep_l1	int
declare	@lt_setrep_tipsa_index 
			int
declare @lt_rep_get_failed
			int
declare @lt_sqlrep_upd
			int
declare @lt_sqlrep_del
			int
declare @lt_sqlrep_inssel
			int
declare @lt_sqlrep_selinto
			int
declare @sqlrepmask
			int


/*
** sp_reptostandby cannot be executed inside a transaction
*/
 
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
	raiserror 17260, "sp_reptostandby"
        return (1)
end
 
set chained off
set transaction isolation level 1

/*
** Initialize the parameter settings 
*/
exec sp_getmessage 18415, @all out
exec sp_getmessage 18416, @none out
exec sp_getmessage 18417, @l1 out
exec sp_getmessage 19895, @off out


/*
** Set up the constants 
*/
select @rep_constant = -32768,
	@lt_rep_get_failed = -2,	/* LT_REP_GET_FAILED */
	@lt_rep_all = 2048,		/* LT_REP_ALL */
	@lt_rep_l1 = 4096,		/* LT_REP_L1 */
	@lt_setrep_tipsa_index = 8,	/* LT_SETREP_TIPSA_INDEX */
	@lt_sqlrep_upd = 32,		/* LT_SQLREP_UPD */
	@lt_sqlrep_del = 64,		/* LT_SQLREP_DEL */
	@lt_sqlrep_inssel = 128,	/* LT_SQLREP_INSSEL */
	@lt_sqlrep_selinto = 256	/* LT_SQLREP_SELINTO */


/*
** Set 'sptlang' for proper printing of object information.  Used mainly
** for the 'select' statement which is executed when we are invoked with
** no parameters.  Copied from similar code in 'sp_help'
*/
select @sptlang = @@langid
if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	   select @sptlang = 0
end

select @setflag = upper(@setflag),
       @use_index = lower(@use_index)

/* check the syntax */

if ((@dbname is NULL) or 
    (@setflag is not NULL and @setflag not in (@all, @l1, @none)) or
    (@use_index is not NULL and @use_index  not in ("use_index")))
begin
	/*
	** 18407, "Usage: sp_reptostandby dbname [ , { ALL | L1 | NONE }
	**					 [,  use_index ] ]
	*/
	raiserror 18407
	return (1)
end

select @newstat = 0

if (@use_index = ("use_index"))
begin
	/* Set LT_SETREP_TIPSA_INDEX */
	select @newstat = 8
end

/* Determine the database */
select @curdb = db_name()

/*
** make sure the procedure is executed with the name of the current
** database
*/
if (@dbname != @curdb)
begin
	/*
	** 18408, "The stored procedure must be executed with the name of the
	**         current database."
	*/
	raiserror 18408
	return (1)
end

/*
** Verify the database name and get the @dbuid
*/
select @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/* Do security check */

/*
** You must be SA, dbo or have replication role to execute this sproc.
** First check if we are the DBO. 
*/
if (suser_id() != @dbuid)
begin
        /*
        ** check if we have sa_role or replication_role. If show_role()
        ** does not find both "sa_role" and the "replication_role"
        ** then we print out a message. 
        ** Note: show_role does not print any message.
        */
        if ( charindex ("sa_role", show_role())  = 0  and
             charindex ("replication_role", show_role()) = 0  )
        begin
		/*
		** 18418, "Only the System Administrator (SA), the Database
		**         Owner (dbo) or a user with REPLICATION authorization
		**         may execute this stored procedure."
		*/
		raiserror 18418
		return (1)
        end
        else
        begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
        end
end

/*
** First, determine the current replication status of the database.
*/
select @curstat = getdbrepstat()
if (@curstat = @lt_rep_get_failed)
begin
	/*
	** "The built-in function getdbrepstat() failed. Please see the
	**  other messages printed along with this message."
	*/
	raiserror 18409, "getdbrepstat"
	return (1)
end

/*
** Get current dbid
*/
select @dbid = db_id()

/*
** Process the case where we simply return the replication status
*/
if (@setflag is NULL)
begin
	if (@curstat & @lt_rep_all = @lt_rep_all)
	begin
		select @tmpstr = @all
	end
	else if (@curstat & @lt_rep_l1 = @lt_rep_l1) 
	begin
		select @tmpstr = @l1
	end
	else 
	begin
		select @tmpstr = @none
	end
	
	if (@curstat & @lt_setrep_tipsa_index = @lt_setrep_tipsa_index) 
	begin
		select @tmpstr = @tmpstr + ", using index"
	end

	select @sqlrepmask = 
		@lt_sqlrep_upd | @lt_sqlrep_del | @lt_sqlrep_inssel | @lt_sqlrep_selinto

	/*
	** 18411, "The replication status for database '%1!' is '%2!'"
	*/
	exec sp_getmessage 18411, @msg output
	print @msg, @dbname, @tmpstr

	if ((@curstat & @sqlrepmask) != 0)
	begin
		select @tmpstr = " "
		if ((@curstat & @lt_sqlrep_upd) = @lt_sqlrep_upd)
			select @tmpstr = @tmpstr + "u"
		if ((@curstat & @lt_sqlrep_del) = @lt_sqlrep_del)
			select @tmpstr = @tmpstr + "d"
		if ((@curstat & @lt_sqlrep_inssel) = @lt_sqlrep_inssel)
			select @tmpstr = @tmpstr + "i"
		if ((@curstat & @lt_sqlrep_selinto) = @lt_sqlrep_selinto)
			select @tmpstr = @tmpstr + "s"
	end
	else
		select @tmpstr = @off 

	/*
	** 19893, "The replication mode for database '%1!' is '%2!'"
	*/
	exec sp_getmessage 19893, @msg output
	print @msg, @dbname, @tmpstr

	return (0)
end

/*
** We are setting the replication status; figure out the new status
*/
if (@setflag = @all)
begin
	select @newstat = @newstat | @lt_rep_all
end
else if (@setflag = @l1)
begin
	select @newstat = @newstat | @lt_rep_l1
end

/*
** If there is no change in status, simply return
*/
if (((@curstat & @lt_rep_all) = (@newstat & @lt_rep_all)) and
	((@curstat & @lt_rep_l1) = (@newstat & @lt_rep_l1)))
	
begin
	/*
	** 18412, "The replication status for database '%1!' is already 
	** set to '%2!'. The replication status is not changed."
	*/
	exec sp_getmessage 18412, @msg output
	print @msg, @dbname, @setflag

	return (0)
end 

/* Do set */
if (setdbrepstat(@newstat, 0) != 1)
begin
	/*
	** 18413, "Due to a system failure, the replication status
	** for '%1!' has not been changed."
	*/
	raiserror 18413, @dbname
	return (1)
end
	
/* Display status message */
/*
** 18414, "The replication status for database '%1!' has been set to '%2!'."
*/
exec sp_getmessage 18414, @msg output
print @msg, @dbname, @setflag

return(0)

go
exec sp_procxmode 'sp_reptostandby', 'anymode'
go
grant execute on sp_reptostandby to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setrepdbmode')
begin
	drop procedure sp_setrepdbmode
end
go
print "Installing sp_setrepdbmode"
go

/*
** Message for "sp_setrepdbmode"
** 17260, "Can't run %1! from within a transaction."
** 18408, "The stored procedure must be executed with the name of
**         the current database."
** 18409, "The built-in function '%1!' failed. Please see any 
**         other messages printed along with this message."
** 18410, "The replication status of '%1!' is corrupt. Please contact 
**         Sybase Technical Support."
** 18411, "The replication status for database '%1!' is '%2!'."
** 18412, "The replication status for database '%1!' is already set to 
**         '%2!'. The replication status is not changed."
** 18413, "Due to a system failure, the replication status for '%1!' 
**         has not been changed."
** 18414, "The replication status for database '%1!' has been set to '%2!'."
** 18418, "Only the System Administrator (SA), the Database Owner (dbo) 
**         or a user with REPLICATION authorization may execute this 
**         stored procedure."
*/
create procedure sp_setrepdbmode
@dbname		varchar(255) = NULL,
@setflag	varchar(20) = NULL,
@setmode	varchar(20) = NULL
as
declare @msg		varchar(1024)
declare @off		varchar(20)
declare @on		varchar(20)
declare @procval	int
declare @dbuid		int
declare @curdb		varchar(255)
declare @dbid		int
declare @objid		int
declare @rep_constant	smallint
declare @tmpstr		varchar(200)
declare @curstat	int
declare @newstat	int
declare @sptlang	int
declare	@setrep_status	int
declare	@lt_sqlrep_upd 	int
declare	@lt_sqlrep_del 	int
declare @lt_sqlrep_inssel  int
declare	@lt_sqlrep_selinto int
declare @sqlrepmask 	int
declare	@lt_rep_all	int
declare	@lt_rep_l1	int
declare @lt_rep_get_failed int

declare @update		char(1)	/* 'u' string used for sql replication */
declare @delete		char(1)	/* 'd' string used for sql replication */
declare @inserts	char(1)	/* 'i' string used for sql replication */
declare @selinto	char(1)	/* 's' string used for sql replication */
declare @sqlrep		varchar(4) /* 'udis' string used for sql replication */
declare @sqlrep_syntax	int	/* Are we using a valid substring of 'udis'? */

/* SQL replication threshold */
declare @threshold	   char(9) 	/* Used to check stored proc syntax */
declare @current_threshold int		/* Current database threshold */
declare @threshold_value   int		/* Integer value from @setflag */
declare @threshold_syntax  smallint 	/* Used to check stored proc syntax */
declare @threshold_max     int		/* Max value for sql threshold */
declare @outvalue	   varchar(10)  /* Used to stored tmp values */

/*
** sp_setrepdbmode cannot be executed inside a transaction
*/
 
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
	raiserror 17260, "sp_reptostandby"
        return (1)
end
 
set chained off
set transaction isolation level 1

/*
** Set up the constants 
*/
select @rep_constant = -32768,
	@setrep_status = 0,
	@lt_rep_get_failed = -2,	/* LT_GET_REP_FAILED */
	@lt_sqlrep_upd = 32,		/* LT_SQLREP_UPD */
	@lt_sqlrep_del = 64,		/* LT_SQLREP_DEL */
	@lt_sqlrep_inssel = 128,	/* LT_SQLREP_INSSEL */
	@lt_sqlrep_selinto = 256,	/* LT_SQLREP_SELINTO */
        @lt_rep_all = 2048,		/* LT_REP_ALL */
        @lt_rep_l1 = 4096,		/* LT_REP_L1 */
	@threshold_max = 10000   	/* LT_SQLREP_MAX_THRESHOLD */

select @sqlrep = name 
	from master.dbo.spt_values
	where type = 'SQ'
	and number = 1

exec sp_getmessage 19895, @off out
exec sp_getmessage 19897, @on out
exec sp_getmessage 19931, @threshold out

if (@sqlrep is NULL or @on is NULL or @off is NULL or @threshold is NULL)
begin
	/*
	** 18413, "Due to a system failure, the replication status
	** for '%1!' has not been changed."
	*/
	raiserror 18413, @dbname
	return (1)
end

select @update	= substring(@sqlrep,1,1)
select @delete	= substring(@sqlrep,2,1)
select @inserts	= substring(@sqlrep,3,1)
select @selinto	= substring(@sqlrep,4,1)

/*
** Set 'sptlang' for proper printing of object information.  Used mainly
** for the 'select' statement which is executed when we are invoked with
** no parameters.  Copied from similar code in 'sp_help'
*/
select @sptlang = @@langid
if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	   select @sptlang = 0
end

select @setflag = lower(@setflag)
select @setmode = lower(@setmode)

/* check the syntax */
if (@dbname is NULL)  
begin
	/*
	** 19887, "Usage: sp_setrepdbmode dbname [, 'UDIS' [, 'on' | 'off']
	**				| 'threshold' [,'value']] 
	*/
	raiserror 19887
	return (1)
end


/* Determine the database */
select @curdb = db_name()

/*
** make sure the procedure is executed with the name of the current
** database
*/
if (@dbname != @curdb)
begin
	/*
	** 18408, "The stored procedure must be executed with the name of the
	**         current database."
	*/
	raiserror 18408
	return (1)
end

/*
** Verify the database name and get the @dbuid
*/
select @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/* Do security check */

/*
** You must be SA, dbo or have replication role to execute this sproc.
** First check if we are the DBO. 
*/
if (suser_id() != @dbuid)
begin
        /*
        ** check if we have sa_role or replication_role. If show_role()
        ** does not find both "sa_role" and the "replication_role"
        ** then we print out a message. 
        ** Note: show_role does not print any message.
        */
        if ( charindex ("sa_role", show_role())  = 0  and
             charindex ("replication_role", show_role()) = 0  )
        begin
		/*
		** 18418, "Only the System Administrator (SA), the Database
		**         Owner (dbo) or a user with REPLICATION authorization
		**         may execute this stored procedure."
		*/
		raiserror 18418
		return (1)
        end
        else
        begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
        end
end

/*
** Get current dbid
*/
select @dbid = db_id()

select @sqlrepmask =
	@lt_sqlrep_upd | @lt_sqlrep_del | @lt_sqlrep_inssel | @lt_sqlrep_selinto

/*
** Check that the arguments to this procedure are acceptable for
** further processing. The arguments are @setflag and @setmode.
*/
select  @sqlrep_syntax = 0, 
	@threshold_syntax = 0

/*
** @sqlrep_syntax is set to 1 if @setflag is a valid substring of 
** 'udis', and to 0 otherwise.
*/
exec sp_sqlrep_check_syntax @setflag,
			@sqlrep,
			@sqlrep_syntax output


/*
** We display sp_setrepdbmode status in the following cases
**
**	1.- 'sp_setrepdbmode <database name>'
**	2.- 'sp_setrepdbmode <database name>', <string>'
** 	3.- 'sp_setrepdbmode <database name>', 'threshold'
**
*/
if ((@setflag is null) or
    (@setmode is null and @sqlrep_syntax = 1) or
    (@setmode is null and @setflag = @threshold))
begin
	/*
	** First, determine the current replication status of the database.
	*/
	select @curstat = getdbrepstat()
	if (@curstat = @lt_rep_get_failed)
	begin
		/*
		** "The built-in function getdbrepstat() failed. Please see any
		**  other messages printed along with this message."
		*/
		raiserror 18409, "getdbrepstat"
		return (1)
	end

	if ((@curstat & @sqlrepmask) != 0) 
	begin
		select @tmpstr = " "
		if ((@curstat & @lt_sqlrep_upd) = @lt_sqlrep_upd)
			select @tmpstr = @tmpstr + "u"
		if ((@curstat & @lt_sqlrep_del) = @lt_sqlrep_del)
			select @tmpstr = @tmpstr + "d"
		if ((@curstat & @lt_sqlrep_inssel) = @lt_sqlrep_inssel)
			select @tmpstr = @tmpstr + "i"
		if ((@curstat & @lt_sqlrep_selinto) = @lt_sqlrep_selinto)
			select @tmpstr = @tmpstr + "s"
	end
	else
		select @tmpstr = @off 

	/* Get the current replication threshold */
	select @current_threshold = getrepdbthreshold(@dbid)
	if (@current_threshold < 0)
	begin
		/*
		** "The built-in function getrepthreshold() failed.
		** Please see any other messages printed along with
		** this message."
		*/
		raiserror 18409, "getrepdbthreshold"
		return (1)
	end

	/*
	** 19893, "The replication mode for database '%1!' is '%2!'"
	*/
	exec sp_getmessage 19893, @msg output
	print @msg, @dbname, @tmpstr

	/*
	** 19932, "The replication threshold for '%1!' is '%2!'"
	*/
	exec sp_getmessage 19932, @msg output
	select @outvalue = convert(varchar(10), @current_threshold)
	print @msg, @dbname, @outvalue
	return (0)
end

select @setflag = ltrim(rtrim(@setflag))

if (@setflag = @threshold)
begin
	select @threshold_syntax = 1
end
else
if (@sqlrep_syntax = 1 and @setmode not in (@on, @off, NULL))
begin
	select @sqlrep_syntax = 0 
end

if (@sqlrep_syntax = 0 and @threshold_syntax = 0)
begin
	/*
	** 19887, "Usage: sp_setrepdbmode dbname [, 'UDIS' [, 'on' | 'off']
	**				| 'threshold' [,'value']] 
	*/
	raiserror 19887
	return (1)
end

if (@sqlrep_syntax = 1)
begin
	/*
	** First, determine the current replication status of the database.
	*/
	select @curstat = getdbrepstat()
	if (@curstat = @lt_rep_get_failed)
	begin
		/*
		** "The built-in function getdbrepstat() failed. Please see any
		**  other messages printed along with this message."
		*/
		raiserror 18409, "getdbrepstat"
		return (1)
	end

	/* Database replication level has to be set */
	if ((@curstat & @lt_rep_all != @lt_rep_all) and 
		(@curstat & @lt_rep_l1 != @lt_rep_l1))
	begin
		/*
		** 19888: The attempt to set the replication mode failed. Please,
		** set the database replication level to 'ALL' or to 'L1' using
		** the stored procedure sp_reptostandby prior to setting the
		** replication mode.
		*/
		raiserror 19888
		return(1)
	end

	/* Interpret the input string: "udis" */
	if (charindex("u", @setflag) > 0)
	begin
		select @setrep_status = @setrep_status | @lt_sqlrep_upd 
	end
	if (charindex("d", @setflag) > 0)
	begin
		select @setrep_status = @setrep_status | @lt_sqlrep_del 
	end
	if (charindex("i", @setflag) > 0)
	begin
		select @setrep_status = @setrep_status | @lt_sqlrep_inssel 
	end
	if (charindex("s", @setflag) > 0)
	begin
		select @setrep_status = @setrep_status | @lt_sqlrep_selinto 
	end

	if (@setmode = @off)
	begin
		select @setrep_status = 0
	end
		
	/* No Change; we're done. */
	if ((@setrep_status & @sqlrepmask) = (@curstat & @sqlrepmask))
	begin
		/*
		** 18412, "The replication status for database '%1!' is already 
		** set to '%2!'. The replication status is not changed."
		*/
		exec sp_getmessage 18412, @msg output
		if (@setmode = @off)
			print @msg, @dbname, @setmode
		else
			print @msg, @dbname, @setflag
		return(0)
	end

	/* Do set */
	if (setdbrepstat(@setrep_status, 1) != 1)
	begin
		/*
		** 18413, "Due to a system failure, the replication status
		** for '%1!' has not been changed."
		*/
		raiserror 18413, @dbname
		return (1)
	end
		
	/* Let user know what we did. */
	if (@setmode = @off)
	begin
		/*
		** 19893, "The replication mode for database '%1!' is '%2!'."
		*/
		exec sp_getmessage 19893, @msg output
		print @msg, @dbname, @off
	end
	else
	begin
		/* Display status message */
		/*
		** 19893, "The replication mode for database '%1!' is '%2!'."
		*/
		exec sp_getmessage 19893, @msg output
		print @msg, @dbname, @setflag 
	end
	return(0)
end
else
/* We are changing the sql replication threshold */
if (@threshold_syntax = 1)
begin
	if (@setmode is null)
	begin
		/* Get the current replication threshold */
		select @current_threshold = getrepdbthreshold(@dbid)

		if (@current_threshold < 0)
		begin
			/*
			** "The built-in function getrepthreshold() failed.
			** Please see any other messages printed along with
			** this message."
			*/
			raiserror 18409, "getrepdbthreshold"
			return (1)
		end

		/*
		** 19932, "The replication threshold for '%1!' is '%2!'."
		*/
		exec sp_getmessage 19932, @msg output
		select @outvalue = convert(varchar(10), @current_threshold)
		print @msg, @dbname, @outvalue
		return(0)
	end

	select @threshold_value = convert(int, @setmode)

	if ((@threshold_value < 0) or (@threshold_value > @threshold_max))
	begin
		/*
		** 19934, "The replication threshold provided for
		**        '%1!' is '%2!'. Please choose a
		**        threshold larger than 0 and smaller than '%3!'."
		*/
		select @outvalue = convert(varchar(10), @threshold_max)
		raiserror 19934, @dbname, @setmode, @outvalue
		return (1)
	end

	if (setrepdbthreshold(@dbid, @threshold_value) != 1)
	begin
		/*
		** 18409, "The built-in funtion '%1!' failed. Please see
		**         any other messages printed along with this
		**         message."
		*/
		raiserror 18409, "setrepdbthreshold"
		return (1)
	end

	/* 
	** We have requested to reset the threshold to the default value.
	*/
	if (@threshold_value = 0)
	begin
		select @current_threshold = getrepdbthreshold(@dbid)
		/*
		** 19950, " The replication threshold for '%1!' has been reset 
		**	    to '%2!'."
		*/
		exec sp_getmessage 19950, @msg output
		select @outvalue = convert(varchar(10), @current_threshold)
		print @msg, @dbname, @outvalue
		return(0)	
	end

        /*
        ** 19932, 'The replication threshold for '%1!' is '%2!'."
        */
        exec sp_getmessage 19932, @msg output
        print @msg, @dbname, @setmode
        return(0)


end
go
exec sp_procxmode 'sp_setrepdbmode', 'anymode'
go
grant execute on sp_setrepdbmode to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_config_rep_agent')
begin
	drop procedure sp_config_rep_agent
end
go
print "Installing sp_config_rep_agent"
go

/*
** Messages for "sp_config_rep_agent"	18373
**
** 17260, "Can't run %1! from within a transaction."
** 17410, "Configuration option doesn't exist."
** 17411, "Configuration option is not unique."
** 17421, "No such database -- run sp_helpdb to list databases."
** 17431 "true"
** 17432 "false"
** 17756, "The execution of the stored procedure '%1!' in database
**         '%2!' was aborted because there was an error in writing the
**         replication log record."
** 18373, "SQL Server is not currently configured to use Replication Agent threads. Use sp_configure to set this property."
** 18374, "Database '%1!' is not configured to use Replication Agent. Run sp_config_rep_agent without parameters to see a list of databases that use Replication Agent. Use the ENABLE option of sp_config_rep_agent to configure a database to use this feature."
** 18375, "You are not authorized to execute this stored procedure. Only the System Administrator (SA), the Database Owner (DBO) or a user with replication_role authorization can execute this stored procedure."
** 18381, "You must be in the specified database '%1!' to configure its Replication Agent thread."
** 18382, "Database '%1!' is already configured to use Replication Agent. Request to enable Replication Agent has been ignored."
** 18383, "Replication Agent enabled for database '%1!'. The Replication Agent thread needs to be started using sp_start_rep_agent."
** 18384, "Replication Agent disabled for database '%1!'. The secondary truncation point in the database is preserved."
** 18385, "Replication Agent disabled for database '%1!'. The secondary truncation point in the database is no longer active."
** 18423, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, enable, <rs_servername>,<rs_username>,<rs_password>. Replication Agent was not enabled for this database."
** 18424, "Failed to enable Replication Agent for database '%1!'."
** 18426, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, disable [,'preserve secondary truncpt']. Replication Agent was not disabled for database '%1!'."
** 18427, "Failed to disable Replication Agent for database '%1!'."
** 18428, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, '%1!',<value>. Replication Agent configuration has not been changed."
** 18429, "Incorrect syntax for sp_config_rep_agent. Usage: sp_config_rep_agent <dbname>, '%1!', {true| false}. Replication Agent configuration has not been changed."
** 18430, "Replication Agent configuration changed for database '%1!'."
** 18431, "Failed to configure the Replication Agent for database '%1!'."
** 18432, "Replication Agent configuration changed for database '%1!'. The changes will take effect the next time the Replication Agent thread is started."
** 18895, "Illegal send buffer size '%1!' specified, legal send buffer sizes are 2K, 4K, 8K and 16K."
** 18896, "Illegal data limits filter mode '%1!' specified, legal filter modes are off, stop, truncate, and skip."
*/
create procedure sp_config_rep_agent
@dbname varchar(30) = NULL,	        /* database name - optional */
@configname varchar(30) = NULL,		/* option to configure */
@configvalue varchar(255) = NULL,	/* value */
@rs_username varchar(30) = NULL,  	/* used only for 'enable' */
@rs_password varchar(30) = NULL		/* used only for 'enable' */
as

declare @dbid 			int	/* dbid of the database */
declare @dbuid 			int	/* id of the owner of the database */
declare @msg 			varchar(1024)
declare @sptlang		int
declare @true 			varchar(10)
declare @false 			varchar(10)
declare @procval	 	int
declare @type		 	int	/* Type of the config. parameter */
declare @hidden		 	int	/* whether parameter is hidden */
declare @dynamic		int	/* whether parameter is dynamic */
declare @attrib_id		int	/* id of the parameter */
declare @preserve_trunc_pt 	int	/*  whether to preserve trunc. pt */
declare @intvalue		int	/* converted from char parameter */
declare @charvalue		varchar(255) /* copy of char parameter */
declare @attrname		varchar(30)
declare @realoption		varchar(30) /* real option - user may type
					       in abbreviation */
declare @action			int
declare @oldvalue		int
declare @tracenum		int
declare @configcount		int
declare @class			int
declare @curdbname		varchar(30)
declare	@has_sa_role		int		/* User has SA role. */
declare	@has_repl_role		int		/* User has REPLICATION role. */
declare @dbstatus3		int		/* Database's status3         */
declare @tempdb_mask		int		/* Mask indicating this is a
						** temporary database */

select @class =11 /* temporary till we get checked in, denotes the syattr class. */
/* If we're in a transaction, disallow this */
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_config_rep_agent"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1

/*
** Initialize 'true' and 'false' strings
*/
/* 17431, "true" */
exec sp_getmessage 17431, @true out
/* 17432, "false" */
exec sp_getmessage 17432, @false out

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

/* 
** Initialize the mask for temporary databases
*/
select @tempdb_mask =  number
from master.dbo.spt_values
where   type = "D3" and name = "TEMPDB STATUS MASK"

/* Use lower case */
select @configname = lower(@configname)

if (@dbname is not NULL)
begin
	/*
	**  Verify the database name and get the @dbid and @dbuid
	*/
	select @dbid = dbid, @dbuid = suid, @dbstatus3 = status3
		from master.dbo.sysdatabases
			where name = @dbname

	/*
	**  If @dbname not found, say so and list the databases.
	*/
	if @dbid is NULL
	begin
		/*
		** 17421, "No such database -- run sp_helpdb to list databases."
		*/
		raiserror 17421
		return (1)
	end

	/*
	** Verify that this database is not being shutdown, or the shutdown
	** is complete after a HA takeover.
	**      status3 = 8    : Database is being shutdown
	**      status3 = 4096 : Shutdown of the database is complete
	** or it is a temporary database.
	*/
	if (((@dbstatus3 & 8) = 8) or
	    ((@dbstatus3 & 4096) = 4096) or
	    ((@dbstatus3 & @tempdb_mask) != 0))
	 begin
		raiserror 18374, @dbname
		return (1)
	end

end

/*
** Check SA and REPLICATION role.
** Keep their status in local variables for auditing later.
*/
select @has_sa_role = charindex ("sa_role", show_role())
select @has_repl_role = charindex ("replication_role", show_role())

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role or replication role can execute it.
**  First check if we are the DBO if the database name is specified.
*/
if (@dbname is NULL) or (suser_id() != @dbuid)
begin
       	/* Check if we have sa_role or replication_role. */
        if ( @has_sa_role = 0  and @has_repl_role = 0 )
        begin
		/*
		** Audit failure. This will result in three messages, but
		** we will live with that until there is a better 'proc_role()'
		** interface.
		*/
		select @procval = proc_role("sa_role")
		select @procval = proc_role("replication_role")

		/* 18375, "You are not authorized to execute this stored 
		** procedure. Only the System Administrator (SA), the 
 		** Database Owner (DBO) or a user with replication_role 
                ** authorization can execute this stored procedure."
		*/
		raiserror 18375
		return (1)
        end
end

/* Audit success(es) */
if ( @has_sa_role > 0 )
	select @procval = proc_role("sa_role")
if ( @has_repl_role > 0 )
	select @procval = proc_role("replication_role")

/* 
** Create a temporary table with the names of all configuration parameters.
** The first column is the configuration parameter 
** The second column is the sysattributes attribute id. For options that
** 	are not in sysattributes, for example enable,disbale, etc, use -1.
** The third column is the optiontype, which can be
** 	0 (not in sysattributes),
**	1 (char),
**	2 (int),
**	3 (boolean).
** The fourth column is true if column is hidden, and false otherwise.
**	A hidden column is not displayed.
** The fifth column is true if the variable is dynamic and false
**	otherwise. A dynamic variable takes effect immediately.
** There is no relevance between the attribute ids and 
**	RA_CFG_CFG_XXXX defines in $DBMS/include/rep_priv.h
*/
create table #rep_ag_options (optionname varchar(30),attrib_id int, 
optiontype int, hidden int, dynamic int)

insert into #rep_ag_options values("enable",-1,0,1,0)
insert into #rep_ag_options values("disable",-1,0,1,0)
insert into #rep_ag_options values("rs servername",0,1,0,0)
insert into #rep_ag_options values("rs username",1,1,0,0)
insert into #rep_ag_options values("rs password",2,1,1,0)
insert into #rep_ag_options values("scan batch size",3,2,0,0)
insert into #rep_ag_options values("scan timeout",4,2,0,0)
insert into #rep_ag_options values("retry timeout",5,2,0,0)
insert into #rep_ag_options values("fade timeout",6,2,1,0)
insert into #rep_ag_options values("skip ltl errors",7,3,0,0)
insert into #rep_ag_options values("batch ltl",8,3,0,0)
insert into #rep_ag_options values("send warm standby xacts",9,3,0,0)
insert into #rep_ag_options values("connect dataserver",10,1,0,0)
insert into #rep_ag_options values("connect database",11,1,0,0)
insert into #rep_ag_options values("send maint xacts to replicate",12,3,0,0)
insert into #rep_ag_options values("traceon",13,2,0,1)
insert into #rep_ag_options values("traceoff",13,2,0,1)
insert into #rep_ag_options values("trace log file",14,1,0,1)
insert into #rep_ag_options values("security mechanism",15,1,0,0)
insert into #rep_ag_options values("unified login",16,3,0,0)
insert into #rep_ag_options values("msg confidentiality",17,3,0,0)
insert into #rep_ag_options values("msg integrity",18,3,0,0)
insert into #rep_ag_options values("msg replay detection",19,3,0,0)
insert into #rep_ag_options values("msg origin check",20,3,0,0)
insert into #rep_ag_options values("msg out-of-sequence check",21,3,0,0)
insert into #rep_ag_options values("mutual authentication",22,3,0,0)
insert into #rep_ag_options values("net password encryption",31,3,0,0)
insert into #rep_ag_options values("skip unsupported features",23,3,0,0)
insert into #rep_ag_options values("ha failover",-1,3,0,1)
insert into #rep_ag_options values("short ltl keywords",24,3,0,0)
insert into #rep_ag_options values("send buffer size",25,1,0,0)
insert into #rep_ag_options values("priority",26,2,0,0)
insert into #rep_ag_options values("send structured oqids",27,3,0,0)
insert into #rep_ag_options values("schema cache growth factor",28,2,0,0)
insert into #rep_ag_options values("data limits filter mode",29,1,0,0)
insert into #rep_ag_options values("startup delay",30,2,0,0)
insert into #rep_ag_options values("bind to engine",32,2,0,0)
insert into #rep_ag_options values("ltl batch size",34,2,0,0)


if @configname is not NULL
begin
	/* Verify that the option is valid */

	select @configcount= count(*)
	from #rep_ag_options
	where optionname like "%" + @configname + "%"
	
	/* If more than one option, show duplicates */
	if @configcount > 1
	begin
		select "List of Matching Options" = optionname
		from #rep_ag_options 
		where optionname like "%" + @configname + "%" 
		/*
		** 17411, "Configuration option is not unique."
		*/
		raiserror 17411
		return (1)
	end

	/* Now we know that there is a unique option */
	select @type =-1

	select @realoption=optionname,@attrib_id = attrib_id,
	@type = optiontype, @hidden = hidden, @dynamic = dynamic 
	from #rep_ag_options
	where optionname like "%" + @configname + "%"

	/* if no match found */
	if @type =-1
	begin
		/* The option specified was incorrect */
		select "List of Options" = optionname
		from #rep_ag_options 
		where optionname != "fade timeout"
		/*
		** 17410, "Configuration option doesn't exist."
		*/
		raiserror 17410
		return (1)
	end
end

/* Get the name of the sysattributes entry */
if @realoption in ("traceon","traceoff")
begin
	select @attrname = "trace flags"
end
else
begin
	select @attrname = @realoption
end

/* Check if Rep Agent threads are enabled for everything except disable */
if (@realoption != "disable") and (is_rep_agent_enabled() =0)
begin
	/* 18373, "SQL Server is not currently configured to use Replication 
        ** Agent threads. Use sp_configure to set this property."
	*/
        raiserror 18373
        return (1)
end


/* If the database is not specified, then print out a list of databases
** that use the Rep Agent.
*/

if @dbname is NULL
begin

	select "Databases that use Rep Agent" = name
	from master.dbo.sysdatabases
	where 1 =  case when ((status3 & @tempdb_mask) = 0)
			then is_rep_agent_enabled(dbid)
			else 0
		   end
	and   ((status3 & 4096) = 0)
	and   ((status3 & 8) = 0)
	and   dbid != 2

	
	return (0)
end

/* If the database name is specified but no configuration parameter is 
** specified then print out the current settings for the database.
*/
if @realoption is NULL
begin
	if is_rep_agent_enabled(@dbid) = 0
	begin
	/* 18374, "Database '%1!' is not configured to use Replication Agent. 
        ** Run sp_config_rep_agent without parameters to see a list of 
        ** databases that use Replication Agent. Use the ENABLE option of 
        ** sp_config_rep_agent to configure a database to use this feature."
	*/
        raiserror 18374,@dbname
        return (1)
        end
        
	/* 'select into' the configuration information into a temp table. */		
	select	"Parameter_Name" = optionname,
		"Default_Value" = rep_agent_config(@dbid,"default config",optionname),
		"Config_Value" = rep_agent_config(@dbid,"current config",optionname),
		"Run_Value" = rep_agent_config(@dbid,"config",optionname)
	into #config_rep_agent_all
	from #rep_ag_options
	where hidden = 0
		and attrib_id !=  13
	
	/* Insert 'trace flags'	information into the temp table. */
	insert into #config_rep_agent_all values("trace flags", 
	rep_agent_config(@dbid,"default config","trace flags"),
	rep_agent_config(@dbid,"current config","trace flags"),
	rep_agent_config(@dbid,"config","trace flags"))
	
	/* Output and format the content of the	temp table. */
	exec sp_autoformat #config_rep_agent_all
	
	/* drop the temp table */
	drop table #config_rep_agent_all
	
	return (0)
end
/* If the option is specified, but no value is given, then we print out the
** value unless the option is hidden.
*/
else if (@configvalue is NULL) and (@rs_username is NULL) 
	and (@rs_password is NULL) and (@hidden =0)
begin
	/* If the config option was specified, but no value, then we will
	** print out the settings for the option.	
	*/
	
	/* 'select into' the configuration information into a temp table. */	
	select "Parameter_Name"	= @attrname,
		"Default_Value"	= rep_agent_config(@dbid,"default config",@attrname),
		"Config_Value" = rep_agent_config(@dbid,"current config",@attrname),
		"Run_Value" = rep_agent_config(@dbid,"config",@attrname)
	into #config_rep_agent_someone

	/* Output and format the content of the	temp table. */	
	exec sp_autoformat #config_rep_agent_someone
	
	/* drop the temp table */
	drop table #config_rep_agent_someone
	
	return (0)
end

/* Now, we are here to modify the current settings for the specified database.
** Enforce that the current database is the same as the one specified. 
*/

if @dbid != db_id()
begin
	/* 18381, "You must be in the specified database '%1!' to configure 
        ** its Replication Agent thread."
	*/
        raiserror 18381,@dbname
        return (1)
end


/* Else, it means that we have found a match with one of the options */

if @realoption ="enable"
begin
	/* Check if the database already has the Rep Agent enabled. */
	if is_rep_agent_enabled(@dbid) = 1
	begin
		/* 18382, "Database '%1!' is already configured to use 
		** Replication Agent. Request to enable Replication Agent has 
		** been ignored."
		*/
        	raiserror 18382,@dbname
        	return (1)
	end
	if (@configvalue is NULL
	or @rs_username is NULL) 
	begin
		/* 18423, "Incorrect syntax for sp_config_rep_agent. Usage: 
		** sp_config_rep_agent <dbname>, enable, <rs_servername>,
		** <rs_username>,<rs_password>. Replication Agent was not 
		** enabled for this database."
		*/
        	raiserror 18423
		return (1)	
	end	

	if (rep_agent_admin("enable",@dbid,@configvalue,@rs_username,
		@rs_password) = 0)
	begin
		/* 18424, "Failed to enable Replication Agent for database '%1!'." */
        	raiserror 18424,@dbname
		return (1)
	end

	/* 18383, "Replication Agent enabled for database '%1!'. The 
	** Replication Agent thread needs to be started using 
	** sp_start_rep_agent."
	*/
        exec sp_getmessage 18383, @msg output
	print @msg,@dbname
	return (0)
end

if is_rep_agent_enabled(@dbid) = 0
begin
	/* 18374, "Database '%1!' is not configured to use Replication Agent. 
        ** Run sp_config_rep_agent without parameters to see a list of 
        ** databases that use Replication Agent. Use the ENABLE option of 
        ** sp_config_rep_agent to configure a database to use this feature."
	*/
        raiserror 18374,@dbname
        return (1)
end

if @realoption ="disable"
begin
	if (@configvalue = "preserve secondary truncpt")
	begin
		select @preserve_trunc_pt =1
	end	
	else if (@configvalue is NULL)
	begin
		select @preserve_trunc_pt =0
	end	
	else
	begin
		/* 18426, "Incorrect syntax for sp_config_rep_agent. Usage: 
		** sp_config_rep_agent <dbname>, disable [,'preserve secondary
		**  truncpt']. Replication Agent was not disabled for database
		**  '%1!'."
		*/
        	raiserror 18426,@dbname

		return (1)	
	end	

	/* Now go ahead and call the builtin */
	if (rep_agent_admin("disable",@dbid, @preserve_trunc_pt) = 0)
	begin
		/* 18427, "Failed to disable Replication Agent for
		**         database '%1!'."
		*/
        	raiserror 18427,@dbname
		return (1)
	end

	if @preserve_trunc_pt =1
	begin
		/* 18384, "Replication Agent disabled for database '%1!'. The 
		** secondary truncation point in the database is preserved."
		*/
        	exec sp_getmessage 18384, @msg output
		print @msg,@dbname
		return (0)
	end
	else
	begin
		/* 18385, "Replication Agent disabled for database '%1!'. The 
		** secondary truncation point in the database is no longer 
		** active."
		*/
        	exec sp_getmessage 18385, @msg output
		print @msg,@dbname
		return (0)
	end

end

else if @realoption ="ha failover"
begin
	/*
	** HA failover takes a boolean arguement, but does not have a row in
	** sysattributes.
	*/
	select @intvalue = NULL

	/* Verify that value is passed in and other parameters are NULL */
	if (@configvalue is NULL
	 or @rs_username is not NULL
	 or @rs_password is not NULL)
	begin
		/* 
		** 18428, "Incorrect syntax for sp_config_rep_agent. Usage:
		** sp_config_rep_agent <dbname, '%1!',<value. Replication 
		** Agent configuration has not been changed."
		*/
		raiserror 18428,@realoption
		return (1)
	end
	if (lower(@configvalue) in ("true", @true ))
	begin
		select @intvalue = 1
	end
	else if (lower(@configvalue) in ("false",@false))
	begin
		select @intvalue = 0
	end
	else
	begin
		/* 18429, "Incorrect syntax for sp_config_rep_agent.
		** Usage: sp_config_rep_agent <dbname, '%1!', {true|
		** false}. Replication Agent configuration has not
		** been changed."
		*/
		raiserror 18429,@realoption
		return (1)
	end

	/* Now go ahead and call the builtin */
	if (rep_agent_admin("ha failover",@dbid, @intvalue) != 0)
	begin
		/* 'select into' the configuration information into a temp table. */
		select	"Parameter_Name" = @attrname,
			"Default_Value"	= rep_agent_config(@dbid,"default config",@attrname),
			"Config_Value" = rep_agent_config(@dbid,"current config",@attrname),
			"Run_Value" = rep_agent_config(@dbid,"config",@attrname)
		into #config_rep_agent_ha

		/* Output and format the content of the	temp table. */	
		exec sp_autoformat #config_rep_agent_ha
			
		/* drop the temp table */
		drop table #config_rep_agent_ha
	
	end
end

else
begin
	/* Instead of repeating code for ints and chars, use @charvalue
	** and @intvalue (only one of them will be non-NULL).
	*/
	select @charvalue = NULL
	select @intvalue = NULL
	/* Verify that value is passed in and other parameters are NULL */
	if (@configvalue is NULL 
	 or @rs_username is not NULL
         or @rs_password is not NULL)
	begin
		/* 18428, "Incorrect syntax for sp_config_rep_agent. Usage: 
		** sp_config_rep_agent <dbname>, '%1!',<value>. Replication 
		** Agent configuration has not been changed."
		*/
        	raiserror 18428,@realoption
		return (1)
	end

	/* For booleans */
	if @type =3
	begin
		if (lower(@configvalue) in ("true", @true ))
		begin
			select @intvalue = 1
		end
		else if (lower(@configvalue) in ("false",@false))
		begin
			select @intvalue = 0
		end
		else
		begin
			/* 18429, "Incorrect syntax for sp_config_rep_agent. 
			** Usage: sp_config_rep_agent <dbname>, '%1!', {true| 
			** false}. Replication Agent configuration has not 
			** been changed."
			*/
        		raiserror 18429,@realoption
			return (1)
		end
	end
	else if @type =2 /* integers */
	begin
		select @intvalue = convert(int,@configvalue)	
	end	
	else /* characters */
	begin
		select @charvalue = @configvalue
	end

	/*
	** Special case check for send buffer size, which only allows
	** 2k, 4k, 8k, and 16k as arguments.
	*/
	if @realoption = "send buffer size"
	begin
		/* Check for legal sizes. */
		select @charvalue = lower(@charvalue)
		if not ( @charvalue in ('2k', '4k', '8k', '16k') )
		begin
        		raiserror 18895, @charvalue
			return (1)
		end

		/*
		** Convert char value to integer.
		** Note that this attribute will have both a charvalue and
		** an intvalue.
		*/
		select @intvalue
			= convert(int, substring(@charvalue, 1,
						charindex('k', @charvalue) - 1))
	end

	/* Special case check for legal filter modes. */
	if @realoption = "data limits filter mode"
	begin
		select @charvalue = lower(@charvalue)
		if not ( @charvalue in ('off', 'stop', 'truncate', 'skip') )
		begin
			raiserror 18896, @charvalue
			return (1)
		end
	end

	if @realoption = "cluster instance name" and
		   lower(@charvalue) = 'coordinator'
	begin
		select @charvalue = lower(@charvalue)
	end

	/* Figure out whether or not we need to insert a row or update in
	** sysattributes.
	*/
	select @oldvalue = int_value
		from sysattributes where class=@class
		and attribute=@attrib_id
		and object_type = "RA"
		and object_cinfo = @attrname
	if @@rowcount != 0
	begin
		if ((@realoption = 'cluster instance name') and
                    (@charvalue = 'coordinator'))
		begin
			select @action = 3	/* ATTR_DROP */
		end
		else
		begin
			select @action = 2	/* ATTR_CHANGE */
		end
	end
	else 
        begin			
		select @action = 1    	/* ATTR_ADD */
		select @oldvalue = 0
        end
	/* If traceoff is the operation, then there should have been an
	** entry in sysattributes. 
	*/
	if (@realoption = "traceoff" and @action =1)
	begin
		/* 18430, "Replication Agent configuration changed for database '%1!'." */
        	exec sp_getmessage 18430, @msg output
		print @msg,@dbname
		return (0)
	end
	begin transaction rs_logexec

	if attrib_valid(@class, @attrib_id, 'RA', @dbid, NULL, NULL, NULL,
			@attrname,@intvalue, @charvalue, NULL, NULL, NULL, @action) =0
	begin
		rollback transaction rs_logexec

		/* 18431, "Failed to configure the 
		** Replication Agent for database '%1!'." 
		*/
        	raiserror 18431,@dbname
		return (1)
	end
	
	/* If this is for trace flags, figure out what to set */
	if @attrname = "trace flags"
	begin
		select @tracenum = @intvalue
		if @realoption= "traceon"
		begin
        		select @intvalue = @oldvalue | 
				(power(2,(@tracenum -9200)))
		end
		else
		begin
        		select @intvalue = @oldvalue & 
				(~power(2,(@tracenum -9200)))
		end
	end

	/* For the password, the insert/update in sysattributes
	** is done by attrib_notify.
	*/
	if @attrname != "rs password"
	begin
		if (@action = 2)	/* ATTR_CHANGE */
		begin
			update sysattributes 
				set char_value = @charvalue,
			    	int_value = @intvalue 
				where class =@class
				 and  attribute = @attrib_id
				 and  object_type = "RA"
				 and  object_cinfo = @attrname

			/*
			** If there was an error, @@error will be non-zero
			*/
			if @@error != 0
			begin
				if @@trancount != 0
					rollback transaction rs_logexec
				/* 18431, "Failed to configure the 
				** Replication Agent for database '%1!'." 
				*/
        			raiserror 18431,@dbname
				return (1)
			end
		end
		else
		if (@action = 3)	/* DROP attribute */
		begin
			delete from sysattributes
			where class = @class
			  and attribute = @attrib_id
			  and object_type = "RA"
			  and object_cinfo = @attrname
		end
		else			/* ADD attribute */
		begin
	
			insert into sysattributes(class,attribute,object_type,
				 object, object_cinfo, int_value, char_value)
		   	values(@class,@attrib_id,"RA",0, @attrname, 
				@intvalue, @charvalue)

			/*
			** If there was an error, @@error will be non-zero
			*/
			if @@error != 0
			begin
				if @@trancount != 0
					rollback transaction rs_logexec
				/* 18431, "Failed to configure the 
				** Replication Agent for database '%1!'." 
				*/
        			raiserror 18431,@dbname
				return (1)
			end
		end
					
	end

	/* Notify */
	if attrib_notify(@class,@attrib_id,"RA",@dbid, NULL, NULL, NULL, 
		@attrname,@intvalue, @charvalue, NULL, NULL, NULL, @action) = 0	
	/* Unable to notify ? */
	begin
		rollback transaction rs_logexec

		/* 18431, "Failed to configure the 
		** Replication Agent for database '%1!'." 
		*/
        	raiserror 18431,@dbname
		return (1)
	end

	/*
	** Write the log record to replicate this invocation 
	** of the stored procedure.
	*/
	if (logexec(@dbid) != 1)
	begin
		/*
		** 17756, "The execution of the stored procedure '%1!'
		** 	   in database '%2!' was aborted because there
		** 	   was an error in writing the replication log
		**	   record."
		*/
		select @curdbname = db_name()
		raiserror 17756, "sp_config_rep_agent", @curdbname
			
		rollback transaction rs_logexec
		return(1)
	end

	commit tran
	/* If the attribute is visible */
	if @hidden =0
	begin
		/* 'select into' the configuration information into a temp table. */
		select "Parameter_Name"	= @attrname,
			"Default_Value"	= rep_agent_config(@dbid,"default config",@attrname),
			"Config_Value" = rep_agent_config(@dbid,"current config",@attrname),
			"Run_Value" = rep_agent_config(@dbid,"config",@attrname)
		into #config_rep_agent_rs
		
		/* Output and format the content of the	temp table. */		
		exec sp_autoformat #config_rep_agent_rs
					
		/* drop the temp table */
		drop table #config_rep_agent_rs
	
	end	
	if @dynamic =0
	begin
	/* 18432, "Replication Agent configuration changed for database '%1!'.
	** The changes will take effect the next time the Replication Agent 
	** thread is started."
	*/
        exec sp_getmessage 18432, @msg output
	print @msg,@dbname
	end
	else
	begin
	/* 18430, "Replication Agent configuration changed for database '%1!'." */
        exec sp_getmessage 18430, @msg output
	print @msg,@dbname
	end
	return (0)
			
end

return (0)
go
exec sp_procxmode 'sp_config_rep_agent', 'anymode'
go
grant execute on sp_config_rep_agent to public
go
exec sp_procxmode 'sp_config_rep_agent', 'rep_current'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_help_rep_agent')
begin
	drop procedure sp_help_rep_agent
end
go
print "Installing sp_help_rep_agent"
go

/*
** Messages for "sp_help_rep_agent"	18425
**
** 17421, "No such database -- run sp_helpdb to list databases."
** 18374, "Database '%1!' is not configured to use Replication Agent. Run sp_config_rep_agent without parameters to see a list of databases that use Replication Agent. Use the ENABLE option of sp_config_rep_agent to configure a database to use this feature."
** 18375, "You are not authorized to execute this stored procedure. Only the System Administrator (SA), the Database Owner (DBO) or a user with replication_role authorization can execute this stored procedure."
** 18425, "Incorrect syntax for sp_help_rep_agent. Usage: sp_help_rep_agent [<dbname> [,{recovery | process | config | scan | security | all } ] ]."
*/
create procedure sp_help_rep_agent
@dbname 	varchar(30) = NULL,	        /* database name - optional */
@whattoprint 	varchar(30) = NULL 		/* what properties to print */
as

declare @dbid 			int	/* dbid of the database */
declare @dbuid 			int	/* id of the owner of the database */
declare @msg 			varchar(250)
declare @sptlang		int
declare @procval	 	int
declare @type		 	int	/* Type of the config. parameter */
declare	@has_sa_role		int	/* User has SA role. */
declare	@has_repl_role		int	/* User has REPLICATION role. */
declare	@dbstatus3		int	/* Database's status3		   */
declare @skip_status		int	/* Holds db status to be skipped
					** from the sysdatabases select    */
declare @tempdb_mask		int	/* Mask indicating this is a
					** temporary database 		   */

if @@trancount = 0
begin
        set chained off
end

set transaction isolation level 1

/* Turn rowcounting off. */
set nocount on
/*
** Initialize the variable with the status to be skipped from the
** select from sysdatabases:
**
**      status3 = 8    : Database is being shutdown
**      status3 = 4096 : Shutdown of the database is complete
*/
select @skip_status = 8 | 4096
select @tempdb_mask = number
from master.dbo.spt_values
where   type = "D3" and name = "TEMPDB STATUS MASK"

select @skip_status =  @skip_status |  @tempdb_mask

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

if (@dbname is not NULL)
begin
	/*
	**  Verify the database name and get the @dbid and @dbuid
	*/
	select @dbid = dbid, @dbuid = suid, @dbstatus3 = status3
		from master.dbo.sysdatabases
			where name = @dbname

	/*
	**  If @dbname not found, say so and list the databases.
	*/
	if @dbid is NULL
	begin
		/*
		** 17421, "No such database -- run sp_helpdb to list databases."
		*/
		raiserror 17421
		return (1)
	end

	/*
	** Verify that this database is not being shutdown, or the shutdown
	** is complete after a HA takeover.
	**	status3 = 8    : Database is being shutdown
	**	status3 = 4096 : Shutdown of the database is complete
	** or it is a temporary database.
	*/
	if (((@dbstatus3 & 8) = 8) or
	    ((@dbstatus3 & 4096) = 4096) or
	    ((@dbstatus3 & @tempdb_mask != 0)) or (@dbid = 2))
	begin
		raiserror 18374, @dbname
		return (1)
	end

	/* Verify that the database has the Rep Agent property enabled. */
	if is_rep_agent_enabled(@dbid) = 0
	begin
	/* 18374, "Database '%1!' is not configured to use Replication Agent.
        ** Run sp_config_rep_agent without parameters to see a list of
        ** databases that use Replication Agent. Use the ENABLE option of
        ** sp_config_rep_agent to configure a database to use this feature."
	*/
		raiserror 18374, @dbname
		return (1)
	end
end

/*
** Check SA and REPLICATION role.
** Keep their status in local variables for auditing later.
*/
select @has_sa_role = charindex ("sa_role", show_role())
select @has_repl_role = charindex ("replication_role", show_role())

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role or replication role can execute it.
**  First check if we are the DBO if the database name is specified.
*/
if (@dbname is NULL) or (suser_id() != @dbuid)
begin
       	/* Check if we have sa_role or replication_role. */
        if ( @has_sa_role = 0  and @has_repl_role = 0 )
        begin
		/*
		** Audit failure. This will result in three messages, but
		** we will live with that until there is a better 'proc_role()'
		** interface.
		*/
		select @procval = proc_role("sa_role")
		select @procval = proc_role("replication_role")

		/* 18375, "You are not authorized to execute this stored
		** procedure. Only the System Administrator (SA), the
 		** Database Owner (DBO) or a user with replication_role
                ** authorization can execute this stored procedure."
		*/
		raiserror 18375
		return (1)
        end
end

/* Audit success(es) */
if ( @has_sa_role > 0 )
	select @procval = proc_role("sa_role")
if ( @has_repl_role > 0 )
	select @procval = proc_role("replication_role")

/* Validate @whattoprint */

if @whattoprint is not NULL and
  not (@whattoprint in ("recovery","config","scan","process","security","all"))
begin
	/* 18425, "Incorrect syntax for sp_help_rep_agent. Usage:
	** sp_help_rep_agent [<dbname> [,{recovery | process | config |
	** scan | security | all } ] ]."
	*/
	raiserror 18425
	return (1)
end

/* If no category is specified, then print all categories */
if (@whattoprint is NULL)
begin
	select @whattoprint = "all"
end

if (@whattoprint in ("recovery","all"))
begin
	print "Replication Agent Recovery status"
	if @dbname is not NULL
	begin
	/* For a given database */

	/* 'select into' the recovery information into a temp table */
	select "dbname"	= @dbname,
		"connect_dataserver" = rep_agent_config(@dbid,"recovery","connect dataserver"),
		"connect_database" = rep_agent_config(@dbid,"recovery","connect database"),
		"status" = rep_agent_config(@dbid,"recovery","status"),
		"rs_servername"	= rep_agent_config(@dbid,"recovery","rs servername"),
		"rs_username" =	rep_agent_config(@dbid,"recovery","rs username")
	into #help_rep_agent_recovery1

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_recovery1

	/* drop the temp table */
	drop table #help_rep_agent_recovery1

	end
	else
	begin

	/* 'select into' the recovery information into a temp table */
	select "dbname"	= name,
		"connect_dataserver" = rep_agent_config(dbid,"recovery","connect dataserver"),
		"connect_database" = rep_agent_config(dbid,"recovery","connect database"),
		"status" = rep_agent_config(dbid,"recovery","status"),
		"rs_servername"	= rep_agent_config(dbid,"recovery","rs servername"),
		"rs_username" =	rep_agent_config(dbid,"recovery","rs username")
	into #help_rep_agent_recovery2
	from master.dbo.sysdatabases
	where 1 = (case when ((status3 & @skip_status) = 0)
			then is_rep_agent_enabled(dbid) else  0
		  end)

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_recovery2

	/* drop the temp table */
	drop table #help_rep_agent_recovery2

	end
end
if (@whattoprint in ("process","all"))
begin
	print "Replication Agent Process status"
	if @dbname is not NULL
	begin
	/* For a given database */

	/* 'select into' the process information into a	temp table */
	select "dbname"	= @dbname,
		"spid" = convert(varchar(11),rep_agent_config(@dbid,"process","spid")),
		"sleep_status" = rep_agent_config(@dbid,"process","sleep status"),
		"retry_count" =	convert(varchar(11),rep_agent_config(@dbid,"process","retry count")),
		"last_error" = convert(varchar(11),rep_agent_config(@dbid,"process","last error"))
	into #help_rep_agent_process1

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_process1

	/* drop the temp table */
	drop table #help_rep_agent_process1

	end
	else
	begin

	/* 'select into' the process information into a	temp table */
	select "dbname"	= name,
		"spid" = convert(varchar(11),rep_agent_config(dbid,"process","spid")),
		"sleep_status" = rep_agent_config(dbid,"process","sleep status"),
		"retry_count" =	convert(varchar(11),rep_agent_config(dbid,"process","retry count")),
		"last_error" = convert(varchar(11),rep_agent_config(dbid,"process","last error"))
	into #help_rep_agent_process2
	from master.dbo.sysdatabases
	where 1 = (case when ((status3 & @skip_status) = 0)
			then is_rep_agent_enabled(dbid) else  0
		  end)

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_process2

	/* drop the temp table */
	drop table #help_rep_agent_process2

	end
end
if (@whattoprint in ("scan","all"))
begin
	print "Replication Agent Scan status"
	if @dbname is not NULL
	begin
	/* For a given database	*/

	/* 'select into' the scan information into a temp table	*/
	select "dbname"	= @dbname,
		"start_marker" = rep_agent_config(@dbid,"scan","start marker"),
		"end_marker" = rep_agent_config(@dbid,"scan","end marker"),
		"current_marker" = rep_agent_config(@dbid,"scan","current marker"),
		"log_recs_scanned" = convert(varchar(11),rep_agent_config(@dbid,"scan","log recs scanned")),
		"oldest_transaction" = rep_agent_config(@dbid,"scan","oldest transaction")
	into #help_rep_agent_scan1

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_scan1

	/* drop the temp table */
	drop table #help_rep_agent_scan1

	end
	else
	begin

	/* 'select into' the scan information into a temp table	*/
	select	"dbname" = name,
		"start_marker" = rep_agent_config(dbid,"scan","start marker"),
		"end_marker" = rep_agent_config(dbid,"scan","end marker"),
		"current_marker" = rep_agent_config(dbid,"scan","current marker"),
		"log_recs_scanned" = convert(varchar(11),rep_agent_config(dbid,"scan","log recs scanned")),
		"oldest_transaction" = rep_agent_config(dbid,"scan","oldest transaction")
	into #help_rep_agent_scan2
	from master.dbo.sysdatabases
	where 1 = (case when ((status3 & @skip_status) = 0)
			then is_rep_agent_enabled(dbid) else  0
		  end)

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_scan2

	/* drop the temp table */
	drop table #help_rep_agent_scan2

	end
end
if (@whattoprint in ("config","all"))
begin
	print "Replication Agent Configuration"
	if @dbname is not NULL
	begin
	/* For a given database */

	/* 'select into' the config information	into a temp table */
	select "dbname"	= @dbname,
	       "auto_start" = rep_agent_config(@dbid,"config","auto start"),
	       "rs_servername" = rep_agent_config(@dbid,"config","rs servername"),
	       "rs_username" = rep_agent_config(@dbid,"config","rs username"),
	       "connect_dataserver" = rep_agent_config(@dbid,"recovery","connect dataserver"),
	       "connect_database" = rep_agent_config(@dbid,"recovery","connect database"),
	       "scan_batch_size" = convert(varchar(11),rep_agent_config(@dbid,"config","scan batch size")),
	       "scan_timeout" =	convert(varchar(11),rep_agent_config(@dbid,"config","scan timeout")),
	       "retry_timeout" = convert(varchar(11),rep_agent_config(@dbid,"config","retry timeout")),
	       "skip_ltl_errors" = rep_agent_config(@dbid,"config","skip ltl errors"),
	       "batch_ltl" = rep_agent_config(@dbid,"config","batch ltl"),
	       "send_warm_standby_xacts" = rep_agent_config(@dbid,"config","send warm standby xacts"),
	       "send_maint_xacts_to_replicate" = rep_agent_config(@dbid,"config","send maint xacts to replicate"),
	       "ha_failover" = rep_agent_config(@dbid,"config","ha failover"),
	       "skip_unsupported_features" = rep_agent_config(@dbid,"config","skip unsupported features"),
	       "short_ltl_keywords" = rep_agent_config(@dbid,"config","short ltl keywords"),
	       "send_buffer_size" = rep_agent_config(@dbid,"config","send buffer size"),
	       "priority" = rep_agent_config(@dbid,"config","priority"),
	       "send_structured_oqids" = rep_agent_config(@dbid,"config","send structured oqids"),
	       "data_limits_filter_mode" = rep_agent_config(@dbid,"config","data limits filter mode"),
	       "schema_cache_growth_factor" = rep_agent_config(@dbid,"config","schema cache growth factor"),
	       "startup_delay" = convert(varchar(11),rep_agent_config(@dbid,"config","startup delay")),
	       "bind_to_engine" = rep_agent_config(@dbid,"config","bind to engine"),
	       "ltl_batch_size" = rep_agent_config(@dbid,"config","ltl batch size")


	into #help_rep_agent_config1

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_config1

	/* drop the temp table */
	drop table #help_rep_agent_config1

	end
	else
	begin

	/* 'select into' the config information	into a temp table */
	select "dbname"	= name,
	       "auto_start" = rep_agent_config(dbid,"config","auto start"),
	       "rs_servername" = rep_agent_config(dbid,"config","rs servername"),
	       "rs_username" = rep_agent_config(dbid,"config","rs username"),
	       "connect_dataserver" = rep_agent_config(dbid,"recovery","connect dataserver"),
	       "connect_database" = rep_agent_config(dbid,"recovery","connect database"),
	       "scan_batch_size" = convert(varchar(11),rep_agent_config(dbid,"config","scan batch size")),
	       "scan_timeout" =	convert(varchar(11),rep_agent_config(dbid,"config","scan timeout")),
	       "retry_timeout" = convert(varchar(11),rep_agent_config(dbid,"config","retry timeout")),
	       "skip_ltl_errors" = rep_agent_config(dbid,"config","skip ltl errors"),
	       "batch_ltl" = rep_agent_config(dbid,"config","batch ltl"),
	       "send_warm_standby_xacts" = rep_agent_config(dbid,"config","send warm standby xacts"),
	       "send_maint_xacts_to_replicate" = rep_agent_config(dbid,"config","send maint xacts to replicate"),
	       "ha_failover" = rep_agent_config(dbid,"config","ha failover"),
	       "skip_unsupported_features" = rep_agent_config(dbid,"config","skip unsupported features"),
	       "short_ltl_keywords" = rep_agent_config(dbid,"config","short ltl keywords"),
	       "send_buffer_size" = rep_agent_config(dbid,"config","send buffer size"),
	       "priority" = rep_agent_config(dbid,"config","priority"),
	       "send_structured_oqids" = rep_agent_config(dbid,"config","send structured oqids"),
	       "data_limits_filter_mode" = rep_agent_config(dbid,"config","data limits filter mode"),
	       "schema_cache_growth_factor" = rep_agent_config(dbid,"config","schema cache growth factor"),
	       "startup_delay" = convert(varchar(11),rep_agent_config(dbid,"config","startup delay")),
	       "bind_to_engine" = rep_agent_config(dbid,"config","bind to engine"),
	       "ltl_batch_size" = rep_agent_config(dbid,"config","ltl batch size")

	into #help_rep_agent_config2
	from master.dbo.sysdatabases
	where 1 = (case when ((status3 & @skip_status) = 0)
			then is_rep_agent_enabled(dbid) else  0
		   end)

	/* Output and format the content of the	temp table */
	exec sp_autoformat #help_rep_agent_config2

	/* drop the temp table */
	drop table #help_rep_agent_config2

	end
end
/* If category is "security", or "all" */
if (@whattoprint in ("security","all"))
begin
	/* Print the title, and set the category. */
	print "Replication Agent Security Configuration"

	/* If dbname was specified, do specified database. */
	if @dbname is not NULL
	begin
		/* Retrieve the information requested. */
		select "dbname" = @dbname,
		       "security_mechanism" =
			    rep_agent_config(@dbid, "security",
							"security mechanism"),
		       "unified_login" =
			    rep_agent_config(@dbid, "security",
							"unified login"),
		       "msg_confidentiality" =
			    rep_agent_config(@dbid, "security",
							"msg confidentiality"),
		       "msg_integrity" =
			    rep_agent_config(@dbid, "security",
							"msg integrity"),
		       "msg_replay_detection" =
			    rep_agent_config(@dbid, "security",
							"msg replay detection"),
		       "msg_origin_check" =
			    rep_agent_config(@dbid, "security",
							"msg origin check"),
		       "msg_out_of_sequence_check" =
			    rep_agent_config(@dbid, "security",
						"msg out-of-sequence check"),
		       "mutual_authentication" =
			    rep_agent_config(@dbid, "security",
						"mutual authentication"),
		       "net_password_encryption" =
			    rep_agent_config(@dbid, "security",
						"net password encryption")
		into #help_rep_agent_security1

		/* Output and format the content of the	temp table. */
		/* And because the column name 'msg_out_of_sequence_check' should */
		/* be renamed as 'msg_out-of-sequence_check', the selectlist is	*/
		/* set for 'sp_autoformat' */
		exec sp_autoformat #help_rep_agent_security1,
			"'dbname' = dbname,
			'security_mechanism' = security_mechanism,
			'unified_login'	= unified_login,
			'msg_confidentiality' = msg_confidentiality,
			'msg_integrity'	= msg_integrity,
			'msg_replay_detection' = msg_replay_detection,
			'msg_origin_check' = msg_origin_check,
			'msg_out-of-sequence_check' = msg_out_of_sequence_check,
			'mutual_authentication'	= mutual_authentication,
			'net_password_encryption'= net_password_encryption"

		/* drop the temp table */
		drop table #help_rep_agent_security1

	end
	else
	/* If dbname was not specified, do all enabled databases. */
	begin
		/* Retrieve the information requested. */
		select "dbname" = name,
		       "security_mechanism" =
			    rep_agent_config(dbid, "security",
							"security mechanism"),
		       "unified_login" =
			    rep_agent_config(dbid, "security",
							"unified login"),
		       "msg_confidentiality" =
			    rep_agent_config(dbid, "security",
							"msg confidentiality"),
		       "msg_integrity" =
			    rep_agent_config(dbid, "security",
							"msg integrity"),
		       "msg_replay_detection" =
			    rep_agent_config(dbid, "security",
							"msg replay detection"),
		       "msg_origin_check" =
			    rep_agent_config(dbid, "security",
							"msg origin check"),
		       "msg_out_of_sequence_check" =
			    rep_agent_config(dbid, "security",
						"msg out-of-sequence check"),
		       "mutual_authentication" =
			    rep_agent_config(dbid, "security",
						"mutual authentication"),
		       "net_password_encryption" =
			    rep_agent_config(dbid, "security",
						"net password encryption")
		into #help_rep_agent_security2
		from master.dbo.sysdatabases
		where 1 = (case when ((status3 & @skip_status) = 0)
				then is_rep_agent_enabled(dbid) else  0
			   end)

		/* Output and format the content of the	temp table. */
		/* And because the column name 'msg_out_of_sequence_check' should */
		/* be renamed as 'msg_out-of-sequence_check', the selectlist is	*/
		/* set for 'sp_autoformat' */
		exec sp_autoformat #help_rep_agent_security2,
			"'dbname' = dbname,
			'security_mechanism' = security_mechanism,
			'unified_login'	= unified_login,
			'msg_confidentiality' = msg_confidentiality,
			'msg_integrity'	= msg_integrity,
			'msg_replay_detection' = msg_replay_detection,
			'msg_origin_check' = msg_origin_check,
			'msg_out-of-sequence_check' = msg_out_of_sequence_check,
			'mutual_authentication'	= mutual_authentication,
			'net_password_encryption'= net_password_encryption"

		/* drop the temp table */
		drop table #help_rep_agent_security2

	end
end

return (0)
go
exec sp_procxmode 'sp_help_rep_agent', 'anymode'
go
grant execute on sp_help_rep_agent to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_start_rep_agent')
begin
	drop procedure sp_start_rep_agent
end
go
print "Installing sp_start_rep_agent"
go

/*
** Messages for "sp_start_rep_agent"	18378
**
** 17421, "No such database -- run sp_helpdb to list databases."
** 18373, "SQL Server is not currently configured to use Replication Agent threads. Use sp_configure to set this property."
** 18374, "Database '%1!' is not configured to use Replication Agent. Run sp_config_rep_agent without parameters to see a list of databases that use Replication Agent. Use the ENABLE option of sp_config_rep_agent to configure a database to use this feature."
** 18375, "You are not authorized to execute this stored procedure. Only the System Administrator (SA), the Database Owner (DBO) or a user with replication_role authorization can execute this stored procedure."
** 18378, "Incorrect syntax for sp_start_rep_agent. Usage: sp_start_rep_agent <dbname> [, {recovery|recovery_foreground} [,<connect dataserver>, <connect database> [,<rs servername>, <rs username>, <rs password>]]]."
** 18379, "Parameters other than the database name can be specified only when starting the Replication Agent thread in recovery mode. The Replication Agent thread was not started."
** 18380, "Replication Agent thread is started for database '%1!'."
** 18421, "Failed to start the Replication Agent thread for database '%1!'."
*/
create procedure sp_start_rep_agent
@dbname varchar(255),		        /* database name - required */
@recovery_mode varchar(20) = NULL,
@connect_ds varchar(255) = NULL,
@connect_db varchar(255) = NULL,
@rs_servername varchar(255) = NULL,
@rs_username varchar(255) = NULL,
@rs_password varchar(255) = NULL
as

declare @dbid int			/* dbid of the database */
declare @dbuid int			/* id of the owner of the database */
declare @msg varchar(1024)
declare @sptlang	int
declare @name		varchar(30)
declare @procval	int
declare @recovery	int
declare	@has_sa_role	int		/* User has SA role. */
declare	@has_repl_role	int		/* User has REPLICATION role. */

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

/*
**  Verify the database name and get the @dbid and @dbuid
*/
select @dbid = dbid, @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so and list the databases.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

/*
** Check SA and REPLICATION role.
** Keep their status in local variables for auditing later.
*/
select @has_sa_role = charindex ("sa_role", show_role())
select @has_repl_role = charindex ("replication_role", show_role())

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role or replication role can execute it.
**  First check if we are the DBO.
*/
if (suser_id() != @dbuid) 
begin
       	/* Check if we have sa_role or replication_role. */
        if ( @has_sa_role = 0  and @has_repl_role = 0 )
        begin
		/*
		** Audit failure. This will result in three messages, but
		** we will live with that until there is a better 'proc_role()'
		** interface.
		*/
		select @procval = proc_role("sa_role")
		select @procval = proc_role("replication_role")

		/* 18375, "You are not authorized to execute this stored 
		** procedure. Only the System Administrator (SA), the 
 		** Database Owner (DBO) or a user with replication_role 
                ** authorization can execute this stored procedure."
		*/
		raiserror 18375
		return (1)
        end
end

/* Audit success(es) */
if ( @has_sa_role > 0 )
	select @procval = proc_role("sa_role")
if ( @has_repl_role > 0 )
	select @procval = proc_role("replication_role")

/* Check if Rep Agent threads are enabled. */
if is_rep_agent_enabled() =0
begin
	/* 18373, "SQL Server is not currently configured to use Replication 
        ** Agent threads. Use sp_configure to set this property."
	*/
	raiserror 18373
	return (1)
end

if is_rep_agent_enabled(@dbid) = 0
begin
	/* 18374, "Database '%1!' is not configured to use Replication Agent. 
        ** Run sp_config_rep_agent without parameters to see a list of 
        ** databases that use Replication Agent. Use the ENABLE option of 
        ** sp_config_rep_agent to configure a database to use this feature."
	*/
	raiserror 18374,@dbname
	return (1)
end

/*
** Validate the arguments.
*/
if @recovery_mode = "recovery" 
begin
	select @recovery=1
end
else if @recovery_mode = "recovery_foreground"
begin
	select @recovery=2
end
else if @recovery_mode is null
begin
	select @recovery=0
	/* If we are not in recovery mode, none of the other arguments
	** can be specified.
	*/
	if (@connect_ds is NULL
	    and @connect_db is NULL
	    and @rs_servername is NULL
	    and @rs_username is NULL
	    and @rs_password is NULL)
	begin
		select @recovery =0
	end
	else
	begin
		/* 18379, "Parameters other than the database name can be 
		** specified only when starting the Replication Agent thread 
		** in recovery mode. The Replication Agent thread was not 
		** started."
		*/
		raiserror 18379
		return (1)
	end
end
else
begin
	/* 18378, "Incorrect syntax for sp_start_rep_agent. Usage: 
	** sp_start_rep_agent <dbname> [, {recovery|recovery_foregournd} 
	** [,<connect dataserver>, <connect database> [,<rs servername>,
	** <rs username>, <rs password>]]]."
	*/
	raiserror 18378
	return (1)
end

if @recovery =0
begin
	if (rep_agent_admin("start thread",@dbid) =0) 
	begin
		/* 18421, "Failed to start the Replication Agent thread for 
		** database '%1!'."
		*/
		raiserror 18421,@dbname
		return (1)
	end
end
else
begin
	/* Need to start in recovery mode */
	if rep_agent_admin("start thread",@dbid,@recovery,@connect_ds,
			@connect_db,@rs_servername,@rs_username,@rs_password) =0
	begin
		/* 18421, "Failed to start the Replication Agent thread for 
		** database '%1!'."
		*/
		raiserror 18421,@dbname
 		return (1)
	end
end

/* Success message */
/* 18380, "Replication Agent thread is started for database '%1!'." */
exec sp_getmessage 18380, @msg output
print @msg,@dbname 

return (0)
go
exec sp_procxmode 'sp_start_rep_agent', 'anymode'
go
grant execute on sp_start_rep_agent to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_stop_rep_agent')
begin
	drop procedure sp_stop_rep_agent
end
go
print "Installing sp_stop_rep_agent"
go

/*
** Messages for "sp_stop_rep_agent"	18376
**
** 17421, "No such database -- run sp_helpdb to list databases."
** 18374, "Database '%1!' is not configured to use Replication Agent. Run sp_config_rep_agent without parameters to see a list of databases that use Replication Agent. Use the ENABLE option of sp_config_rep_agent to configure a database to use this feature."
** 18375, "You are not authorized to execute this stored procedure. Only the System Administrator (SA), the Database Owner (DBO) or a user with replication_role authorization can execute this stored procedure."
** 18376, "Incorrect syntax for sp_stop_rep_agent. Usage: sp_stop_rep_agent <dbname> [,nowait]."
** 18377, "The Replication Agent thread for database '%1!' is being stopped."
** 18422, "The Replication Agent thread for database '%1!' is not currently running.
*/

create procedure sp_stop_rep_agent
@dbname varchar(255),		        /* database name - required */
@optname varchar(20) = NULL		/* with nowait option */
as

declare @dbid 		int,		/* dbid of the database */
	@dbuid 		int,		/* id of the owner of the database */
	@msg varchar(1024),
	@sptlang	int,
	@name		varchar(30),
	@procval	int,
	@nowait		int,		/* is stop graceful ? */
	@has_sa_role	int,		/* User has SA role. */
	@has_repl_role	int,		/* User has REPLICATION role. */
	@builtin_retstat int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17050 and 17069
		and langid = @@langid)
	select @sptlang = 0
end

/*
**  Verify the database name and get the @dbid and @dbuid
*/
select @dbid = dbid, @dbuid = suid
	from master.dbo.sysdatabases
		where name = @dbname

/*
**  If @dbname not found, say so and list the databases.
*/
if @dbid is NULL
begin
	/*
	** 17421, "No such database -- run sp_helpdb to list databases."
	*/
	raiserror 17421
	return (1)
end

/*
** Check SA and REPLICATION role.
** Keep their status in local variables for auditing later.
*/
select @has_sa_role = charindex ("sa_role", show_role())
select @has_repl_role = charindex ("replication_role", show_role())

/*
**  Only the Database Owner (DBO) or
**  Accounts with SA role or replication role can execute it.
**  First check if we are the DBO.
*/
if (suser_id() != @dbuid) 
begin
       	/* Check if we have sa_role or replication_role. */
        if ( @has_sa_role = 0  and @has_repl_role = 0 )
        begin
		/*
		** Audit failure. This will result in three messages, but
		** we will live with that until there is a better 'proc_role()'
		** interface.
		*/
		select @procval = proc_role("sa_role")
		select @procval = proc_role("replication_role")

		/* 18375, "You are not authorized to execute this stored 
		** procedure. Only the System Administrator (SA), the 
 		** Database Owner (DBO) or a user with replication_role 
                ** authorization can execute this stored procedure."
		*/
		raiserror 18375
		return (1)
        end
        else
        begin
                /*
                ** Call proc_role() with each role that the user has
                ** in order to send the success audit records.
                ** Note that this could mean 1 or 2 audit records.
                */
                if (charindex("sa_role", show_role()) > 0)
                        select @procval = proc_role("sa_role")
                if (charindex("replication_role", show_role())> 0)
                        select @procval = proc_role("replication_role")
        end
end

/* Audit success(es) */
if ( @has_sa_role > 0 )
	select @procval = proc_role("sa_role")
if ( @has_repl_role > 0 )
	select @procval = proc_role("replication_role")

/* Verify that the database is using the Rep Agent. */
if is_rep_agent_enabled(@dbid) = 0
begin
	/* 18374, "Database '%1!' is not configured to use Replication Agent. 
        ** Run sp_config_rep_agent without parameters to see a list of 
        ** databases that use Replication Agent. Use the ENABLE option of 
        ** sp_config_rep_agent to configure a database to use this feature."
	*/
	raiserror 18374,@dbname
	return (1)
end

/*
**  Verify that if optvalue if specified is the correct value.
*/
if @optname = "nowait" 
begin
	select @nowait=1
end
else if @optname is null
begin
	select @nowait=0
end
else
begin
	/* 18376, "Incorrect syntax for sp_stop_rep_agent. Usage: 
	** sp_stop_rep_agent <dbname> [,nowait]."
	*/
	raiserror 18376
	return (1)
end

/* Call the builtin to do the work. If it encounters an error, it will
** raise an exception and output a message to the client.
*/
select @builtin_retstat = rep_agent_admin("stop thread",@dbid,@nowait)

if (@builtin_retstat = 1)
begin
	/* 18377, "The Replication Agent thread for database '%1!' is 
	** being stopped."
	*/
	exec sp_getmessage 18377, @msg output
	print @msg,@dbname
	return (0)
end
else if (@builtin_retstat = -1)
begin
	/* 
	** 18422, "The Replication Agent thread for database '%1!' is not 
	** currently running.
	*/
	raiserror 18422,@dbname
end
else if  (@builtin_retstat = 0)
begin
	/* 19653, "Failed to stop the Replication Agent thread for 
	** database '%1!'.
	*/
	raiserror 19653,@dbname
end
return (1)
go
exec sp_procxmode 'sp_stop_rep_agent', 'anymode'
go
grant execute on sp_stop_rep_agent to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_object_stats')
begin
	drop procedure sp_object_stats
end
go
print "Installing sp_object_stats"
go


if (exists (select * from tempdb.dbo.sysobjects where id =
                (select object_id("tempdb..syslkstats"))))
 begin
        drop table tempdb..syslkstats
 end
go

/* Messages for sp_object_stats
**
** 18617, "Usage: sp_object_stats 'hh:mm:ss', @top_n, @dbname, @objname, @rpt_option"
** 18618, "sp_object_stats: Invalid interval string passed '%1!'. It should be in the form 'hh:mm:ss'."
** 18619, "sp_object_stats: Failed to %1! temporary table %2!."
** 18620, "sp_object_stats: If @objname is specified, a valid @dbname must also be specified."
** 18127, "You must have System Administrator (SA) role to execute this
**         stored procedure."
** 17260, "Can't run %1! from within a transaction."
*/
create procedure sp_object_stats
	@interval 	char(12)="", 	/* Time interval string */
	@top_n 	int=10,		/* Top 'n' number of hot objects to report on */
	@dbname	char(255)="",	/* Database name */
	@objname	char(255)="",	/* Object name */
	@rpt_option	char(11)="rpt_locks"	/* Report option:
			rpt_locks (default) - reports on objects having non_zero
					 lock contention with detailed
					 lock statistics
			rpt_objlist	 - reports on most active objects
					 even if contention is zero with
					 no detailed lock statistics
					*/	
as

/*
** Local variables.
*/
declare 	@msg 			varchar(255)	/* message variable */
declare		@blankline		char(80)
declare		@rpt_line		char(530)
declare		@lock_scheme_str	char(10)
declare		@iter_count		int
declare		@ldspc			char(2)
declare		@tab			char(1)
declare		@tmp_dbid		int
declare		@tmp_objid		int
declare		@tmp_lkscheme		smallint
declare		@tmp_expg_cont		double precision
declare		@tmp_uppg_cont		double precision
declare		@tmp_shpg_cont		double precision
declare		@tmp_exad_cont		double precision
declare		@tmp_shad_cont		double precision
declare		@tmp_exrow_cont		double precision
declare		@tmp_uprow_cont		double precision
declare		@tmp_shrow_cont		double precision
declare		@AllPages		int
declare		@DataPages		int
declare		@DataRows		int
declare		@strlength		int

/*
** define some constants.
*/
select @AllPages = 1, @DataPages = 2, @DataRows = 3

select	@blankline	= " "
select	@rpt_line	= " "

select	@tab		= "	"
select	@ldspc		= space(1)

/* BEGIN: Validate input parameters
** ================================ */

/* If no interval or option was passed, display usage */
if (@interval = "")
begin
	raiserror 18617,@msg
	return 1
end

/*
** Validate that it is a proper time interval string.
** Eg of form "nn:mn:mn" with m between 0 - 5, n 0 - 9.
*/

if (patindex("[0-9][0-9]:[0-5][0-9]:[0-5][0-9]", @interval) = 0 or
		patindex("00:00:00",@interval) = 1)
begin
	raiserror 18618,@msg,@interval
 	return 1
end

/* END: Validate input parameters
** ============================== */

/* BEGIN: Validate permissions for proc
** ==================================== */

/*
** Check if OK to Run
*/
if proc_role("sa_role") < 1
begin
	/* 18127, "You must have System Administrator (SA) role to execute
	this stored procedure." */
	raiserror 18127 @msg, "sp_object_stats"
	return 1
end
 
/*
** In a transaction?, disallow since it might make recovery impossible
*/
if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260 @msg, "sp_object_stats"
	return 1
end

set chained off
set transaction isolation level 1

/* END: Validate permissions for proc
** ================================== */

/* BEGIN: Create repository for dbcc object_stats
** ============================================== */

/*
** Drop and create tempdb..syslkstats.
**
** This table will hold the outputs from system monitoring
** and will be analysed by this procedure.
*/
if (exists (select * from tempdb.dbo.sysobjects where id =
	(select object_id("tempdb..syslkstats"))))
begin
	drop table tempdb..syslkstats
end

/*
** tempdb..syslkstats is the repository for information from
** dbcc object_stats. So its format reflects the table
** defined in object_stats.
*/

create table tempdb..syslkstats
(
	dbid	 	smallint,
	objid 	 	int,
	lockscheme	smallint,
	page_type	smallint,
	stat_name	char(30),
	stat_value	double precision
)

/* bail out if we cannot create this table */
if (@@error != 0)
begin
	raiserror 18619,@msg,"create","tempdb..syslkstats"
	return 1
end

/* END: Create repository for dbcc object_stats
** ============================================ */

/* BEGIN: Enable object and user level lock statistics monitoring.
** ===============================================================
** NOTE: It is imperative that this be switched off before
** returning from this procedure, else system performance may
** be severely compromised.
*/

dbcc traceon(1213)

/*
** Determine which mode we are called in.
** If no database or object name is specified, default
** is to sample lock usage.
*/
if (@dbname = "" and @objname = "")
begin
	dbcc object_stats("init_locks")
end
else if (@dbname != "" and @objname = "")
begin
	select @tmp_dbid = db_id(rtrim(@dbname))
	dbcc object_stats("init_locks", @tmp_dbid)
end
else if (@dbname != "" and @objname != "")
begin
	select @tmp_dbid = db_id(rtrim(@dbname))
	select @tmp_objid = object_id(rtrim(@dbname)+".."+rtrim(@objname))
	dbcc object_stats("init_locks", @tmp_dbid, @tmp_objid)
end
else
begin
	raiserror 18620,@msg
	dbcc traceoff(1213)
/*	=================== */
	return 1
end

/*
** Leave dbcc to collect stats for the specified interval
*/
waitfor delay @interval

if (@dbname = "" and @objname = "")
	dbcc object_stats("insert_locks")
else if (@dbname != "" and @objname = "")
	dbcc object_stats("insert_locks", @tmp_dbid)
else
	dbcc object_stats("insert_locks", @tmp_dbid, @tmp_objid)

/*
** Now we have collected the statistics, switch the traceflag off.
*/
dbcc traceoff(1213)
/*=================*/

/* END: Enable object and user level lock statistics monitoring.
** =============================================================*/

/* BEGIN: Process data and look for contention.
** ============================================ */

/*
** Now create a temporary table to store analysis of results.
*/
if object_id("#syslkstats_cont") is not null
begin
	drop table #syslkstats_cont
end
create table #syslkstats_cont
(
	dbid			smallint,
	objid			int,
	lockscheme		smallint,
	expg_cont		double precision,
	uppg_cont		double precision,
	shpg_cont		double precision,
	exad_cont		double precision,
	shad_cont		double precision,
	exrow_cont		double precision,
	uprow_cont		double precision,
	shrow_cont		double precision
)
/*
** Did the create table work?
*/
if (@@error != 0)
begin
	raiserror 18619,@msg,"create","#syslkstats_cont"
	return 1
end

/*
** Contention Algorithm
** ====================
**
** For each of the distinct database, object, lockscheme's
** we look for the contention, which is measured as a
** percentage of the 'waiting' time to the total time.
** Total time is the sum of the waiting, granting and deadlock
** time for an object in a database, and will depend on
** the locking scheme used.
**
** The fields to be reported are
**
** dbid
** objid
** lockscheme	Allpages, Datapages, Datarow = 1, 2, 3
** expg_cont	Exclusive page contention (%)
** uppg_cont	Update page contention (%)
** shpg_cont	Shared page contention (%)
** exad_cont	Exclusive address contention (%)
** shad_cont	Shared address contention (%)
** exrow_cont	Exclusive row contention (%)
** uprow_cont	Update row contention (%)
** shrow_cont	Shared row contention (%)
**
** These calculations are coded using a case statement since this
** offers tremendous flexibility to define "functions" that can
** be applied to each column.
**
** Since we wish to avoid "division by zero" exceptions we use
** nullif function to return null if the denominator of the fraction is 0,
** and hence the division results in NULL. As we do not want the tuple to
** contain nulls, we use isnull to switch nulls to 0.
**
** We can classify the domain of the contention functions as follows:
**
**		    Locking Mode
** attribute	AP	DP	DR
**
** expg_cont	f1	f1	0
** uppg_cont	f1	f1	0
** shpg_cont	f1	f1	0
** exad_cont	f2	0	0
** shad_cont	f2	0	0
** exrow_cont	f2	0	0
** uprow_cont	0	0	f3
** shrow_cont	0	0	f3
**
** where
**
** f1(mode) = isnull{
**	100 * Sum(	stat_value	if stat_name = "mode_pg_wait"
**			0		otherwise)
**      -----------------------------------------------------------
**	nullif ( Sum(	stat_value	if stat_name = ("mode_pg_wait"
**						| "mode_pg_grants"
**						| "mode_pg_deadlocks")
**		 	0		otherwise
**		, 0)
**	, 0)
**
** and mode is {ex, up, sh}
**
** f2(mode) = isnull{
**	100 * Sum (	stat_value	if stat_name = "mode_addr_wait"
**					  and lockscheme = @AllPages
**					  and page_type = 1
**			0		otherwise)
**      -----------------------------------------------------------
**	nullif ( sum(	stat_value	if stat_name = ("mode_addr_wait"
**						| "mode_addr_grants"
**						| "mode_addr_deadlocks")
**					  and lockscheme = @AllPages
**					  and page_type = 1
**		 	0		otherwise)
**		, 0)
**	, 0)
**
** and mode is {ex, sh}
**
** f3(mode) = isnull{
**	100 * Sum (	stat_value	if stat_name = "mode_row_wait"
**					  and lockscheme = @DataRow
**					  and page_type = 0
**			0		otherwise)
**      -----------------------------------------------------------
**	nullif ( sum(	stat_value	if stat_name = ("mode_row_wait"
**						| "mode_row_grants"
**						| "mode_row_deadlocks")
**					  and lockscheme = @DataRow
**					  and page_type = 0
**		 	0		otherwise)
**		, 0)
**	, 0)
**
** and mode is {ex, up, sh}
**
*/

insert into #syslkstats_cont (dbid, objid, lockscheme, expg_cont,
	uppg_cont, shpg_cont, exad_cont, shad_cont,
	exrow_cont, uprow_cont, shrow_cont)
select distinct dbid, objid, lockscheme,

-- f1 --> AllPage and Data Page lock statistics

isnull( 100 * sum( case when stat_name = "ex_pg_waits" and lockscheme != @DataRows
	    	     then	stat_value
	    	     else 	0
	   	   end)
	/ nullif( sum( case when stat_name in ("ex_pg_grants", "ex_pg_waits",
						"ex_pg_deadlocks")
			 then 	stat_value
			 else	0
		       end)
	, 0)
, 0)		as expg_cont,

isnull( 100 * sum( case when stat_name = "up_pg_waits" and lockscheme != @DataRows
		     then 	stat_value
		     else 	0
		   end)
	/ nullif( sum( case when stat_name in ("up_pg_grants", "up_pg_waits",
						"up_pg_deadlocks")
			 then 		stat_value
			 else		0
		       end)
	, 0)
, 0)		as uppg_cont,

isnull( 100 * sum( case when stat_name = "sh_pg_waits" and lockscheme != @DataRows
		     then 		stat_value
		     else 		0
		   end)
	/ nullif( sum( case when stat_name in ("sh_pg_grants", "sh_pg_waits",
						"sh_pg_deadlocks")
			 then 		stat_value
			 else		0
		       end)
	, 0)
, 0)		as shpg_cont,

-- f2 --> AllPage specific lock Statistics

isnull(
100 * sum( case when stat_name = "ex_addr_waits" and lockscheme = @AllPages
			and page_type = 1
	  then 		stat_value
	  else 		0
	end)
	/ nullif( sum( case when stat_name in ("ex_addr_grants", 
				"ex_addr_waits", "ex_addr_deadlocks")
				and lockscheme = @AllPages and page_type = 1
			 then 		stat_value
			 else		0
		       end)
	, 0)
, 0)		as exad_cont,

isnull(
100 * sum( case when stat_name = "sh_addr_waits" and lockscheme = @AllPages
			and page_type = 1
	  then 		stat_value
	  else 		0
	end)
	/ nullif(
		sum( case when stat_name in ("sh_addr_grants", "sh_addr_waits",
						"sh_addr_deadlocks")
				and lockscheme = @AllPages and page_type = 1
		       then 		stat_value
		       else		0
		     end)
	, 0)
, 0)		as shad_cont,


-- DataRow locking statistics
isnull(
100 * ( case when stat_name = "ex_row_waits" and lockscheme = @DataRows
			and page_type = 0
	  then 		stat_value
	  else 		0
	end)
	/ nullif( sum( case when stat_name in ("ex_row_grants", 
				"ex_row_waits", "ex_row_deadlocks")
			and lockscheme = @DataRows
			and page_type = 0
			 then 		stat_value
			 else		0
		       end)
	, 0)
, 0)		as exrow_cont,

isnull(
100 * sum( case when stat_name = "up_row_waits" and lockscheme = @DataRows
			and page_type = 0
	     then 		stat_value
	     else 		0
	   end)
	/ nullif( sum( case when stat_name in ("up_row_grants", "up_row_waits",
				"up_row_deadlocks") and lockscheme = @DataRows
				and page_type = 0
		         then 		stat_value
			 else		0
		       end)
	, 0)
, 0)		as uprow_cont,

isnull(
100 * sum( case when stat_name = "sh_row_waits" and lockscheme = @DataRows
			and page_type = 0
	     then 		stat_value
	     else 		0
	   end)
	/ nullif( sum( case when stat_name in ("sh_row_grants", "sh_row_waits",
				"sh_row_deadlocks") and lockscheme = @DataRows
				and page_type = 0
			 then 		stat_value
			 else		0
		       end)
	, 0)
, 0)		as shrow_cont

from tempdb..syslkstats
group by dbid, objid

/* did this insert fail? */
if (@@error != 0)
begin
	raiserror 18619,@msg,"insert into","#syslkstats_cont"
	return 1
end          

/* Reporting phase
** =============== */

select @iter_count = 0

if (@rpt_option = "rpt_objlist")
begin
	declare obj_rpt_csr cursor for
	select dbid, objid
	from #syslkstats_cont
	order by 
	(expg_cont + uppg_cont + shpg_cont +
		exad_cont + shad_cont +
		exrow_cont + uprow_cont + shrow_cont) desc
	 for read only
	open obj_rpt_csr
	fetch obj_rpt_csr into @tmp_dbid,@tmp_objid
	while (@@sqlstatus = 0 and @iter_count < @top_n)
	begin
		if (@iter_count = 0)
		begin
			print @blankline
			select @rpt_line = "List of the top "+
					ltrim(str(@top_n))+
				" (or less) most frequently accessed objects:"
			print @rpt_line
			select @rpt_line = "----------------"+
				replicate('-',datalength(ltrim(str(@top_n))))+
				"-------------------------------------------"
			print @rpt_line
			print @blankline
		end

		select	@strlength = char_length(@ldspc+ltrim(str(@iter_count+1))+")")

		select  @rpt_line = @ldspc+ltrim(str(@iter_count+1))+")"+ " " +
			db_name(@tmp_dbid)+".."+ object_name(@tmp_objid, @tmp_dbid)
		print	@rpt_line
		select	@rpt_line = space(@strlength) + " " +
			"(dbid="+ltrim(str(@tmp_dbid))+", objid="+ltrim(str(@tmp_objid))+")"
		print	@rpt_line
		print	@blankline

		select @iter_count = @iter_count + 1

		fetch obj_rpt_csr into @tmp_dbid,@tmp_objid
	end
	close obj_rpt_csr
	deallocate cursor obj_rpt_csr
end
else
begin
	declare stats_rpt_csr cursor for
	select 	expg_cont, uppg_cont, shpg_cont,
		exad_cont, shad_cont,
		exrow_cont, uprow_cont, shrow_cont,
	 	dbid, objid, lockscheme
	from #syslkstats_cont
	where (expg_cont + uppg_cont + shpg_cont +
		exad_cont + shad_cont +
		exrow_cont + uprow_cont + shrow_cont) > 0
 	order by 
	 	(expg_cont + uppg_cont + shpg_cont +
		exad_cont + shad_cont +
		exrow_cont + uprow_cont + shrow_cont) desc
	for read only

	open stats_rpt_csr
	fetch stats_rpt_csr into @tmp_expg_cont, @tmp_uppg_cont, @tmp_shpg_cont, 
			@tmp_exad_cont, @tmp_shad_cont,
			@tmp_exrow_cont,@tmp_uprow_cont,@tmp_shrow_cont,
			@tmp_dbid,@tmp_objid, @tmp_lkscheme

	while (@@sqlstatus = 0 and @iter_count < @top_n)
	begin
	
		if (@iter_count = 0)
		begin
			print @blankline
			select @rpt_line = "Lock statistics for the top "+
				ltrim(str(@top_n))+
				" (or less) most contended objects:"
			print @rpt_line
			select @rpt_line = "----------------------------"+ 
				replicate('-',datalength(ltrim(str(@top_n))))+
				"---------------------------------"
			print @rpt_line
			print @blankline
		end

		if	(@tmp_lkscheme = @AllPages)
			select @lock_scheme_str = "Allpages"
		else if	(@tmp_lkscheme = @DataPages)
			select @lock_scheme_str = "Datapages"
		else if	(@tmp_lkscheme = @DataRows)
			select @lock_scheme_str = "Datarows"
	
		print @blankline
		select	@strlength = char_length("Object Name:")
		select	@rpt_line = "Object Name:" + " " + db_name(@tmp_dbid)+".." +
			object_name(@tmp_objid, @tmp_dbid)
		print	@rpt_line
		select	@rpt_line = space(@strlength) + " " +
			"(dbid="+ltrim(str(@tmp_dbid))+", objid="+
			ltrim(str(@tmp_objid))+", lockscheme="+
			rtrim(@lock_scheme_str)+")"
		print	@rpt_line
		print	@blankline

		if (@tmp_lkscheme != @DataRows)
		begin

			if (exists (select *
				from tempdb..syslkstats
				where stat_name like "%_pg_%"
				and dbid = @tmp_dbid
				and objid = @tmp_objid))
			begin
	
				print @blankline
	
				select @rpt_line = rtrim(@ldspc+"Page Locks"+
					@tab+" SH_PAGE "+@tab+@tab+
					" UP_PAGE "+@tab+@tab+" EX_PAGE ")
				print @rpt_line
				select @rpt_line = rtrim(@ldspc+"----------"+
					@tab+"----------"+@tab+@tab+"----------"+
					@tab+@tab+"----------")
				print @rpt_line
				select @rpt_line = rtrim(@ldspc+"Grants:"+@tab+
				/* the field is unsigned int32 that means we can only have
				** 10 characters in it
				*/
					str(sum(case when stat_name = "sh_pg_grants"
							then stat_value
							else 0
						end),10)+@tab+@tab+
					str(sum(case when stat_name = "up_pg_grants"
							then stat_value
							else 0
						end),10)+@tab+@tab+
					str(sum(case when stat_name = "ex_pg_grants"
							then stat_value
							else 0
						end),10))
				from tempdb..syslkstats
				where	dbid = @tmp_dbid
				and	objid = @tmp_objid
			
				print @rpt_line
	
				select @rpt_line = rtrim(@ldspc+"Waits:"+@tab+
					str(sum(case when stat_name = "sh_pg_waits"
							then stat_value
							else 0
						end),10)+@tab+@tab+
					str(sum(case when stat_name = "up_pg_waits"
							then stat_value
							else 0
						end),10)+@tab+@tab+
					str(sum(case when stat_name = "ex_pg_waits"
							then stat_value
							else 0
						end),10))
				from tempdb..syslkstats
				where	dbid = @tmp_dbid
				and	objid = @tmp_objid
			
				print @rpt_line
		
				select @rpt_line = rtrim(@ldspc+"Deadlocks:"+@tab+
					str(sum(case when stat_name = "sh_pg_deadlocks"
							then stat_value
							else 0
						end),10)+@tab+@tab+
					str(sum(case when stat_name = "up_pg_deadlocks"
							then stat_value
							else 0
						end),10)+@tab+@tab+
					str(sum(case when stat_name = "ex_pg_deadlocks"
							then stat_value
							else 0
						end),10))
				from tempdb..syslkstats
				where	dbid = @tmp_dbid
				and	objid = @tmp_objid
			
				print @rpt_line
		
				select @rpt_line = rtrim(@ldspc+"Wait-time:"+@tab+
					str(sum(case when stat_name = "sh_pg_waittime"
							then stat_value
							else 0
						end),10)+" ms"+@tab+@tab+
					str(sum(case when stat_name = "up_pg_waittime"
							then stat_value
							else 0
						end),10)+" ms"+@tab+@tab+
					str(sum(case when stat_name = "ex_pg_waittime"
							then stat_value
							else 0
						end),10)+" ms")
				from tempdb..syslkstats
				where	dbid = @tmp_dbid
				and	objid = @tmp_objid
			
				print @rpt_line
		
				select @rpt_line = rtrim(@ldspc+"Contention:"+
					+@tab+str(@tmp_shpg_cont,10,2)+"%%"+
					+@tab+@tab+str(@tmp_uppg_cont,10,2)+"%%"+@tab+@tab+
					str(@tmp_expg_cont,10,2))+"%%"
				
				print @rpt_line
				
				print @blankline
			end

			if ((@tmp_shpg_cont+@tmp_uppg_cont+@tmp_expg_cont) > 15.0)
			begin
				if (@tmp_lkscheme = @AllPages)
				begin
					select @rpt_line= " *** Consider altering "+
						db_name(@tmp_dbid)+".."+ 
						object_name(@tmp_objid, @tmp_dbid)+
						" to Datapages locking."
					print @rpt_line
				end
				else
				begin
					select @rpt_line= " *** Consider altering "+
						db_name(@tmp_dbid)+".."+ 
						object_name(@tmp_objid, @tmp_dbid)+
						" to Datarows locking."
					print @rpt_line
				end
			end
		end
		else
		begin
			print @blankline
		
			select @rpt_line = rtrim(@ldspc+"Row Locks"+@tab+" 
					SH_ROW "+@tab+@tab+
					" UP_ROW "+@tab+@tab+" EX_ROW ")
			print @rpt_line
			select @rpt_line = rtrim(@ldspc+"----------"+@tab+"----------"+
					@tab+@tab+"----------"+@tab+@tab+"----------")
			print @rpt_line
			select @rpt_line = rtrim(@ldspc+"Grants:"+
					@tab+str(s.stat_value,10)+@tab+@tab+
					str(u.stat_value,10)+@tab+@tab+str(e.stat_value,10))
			from tempdb..syslkstats s, tempdb..syslkstats u, tempdb..syslkstats e
			where 	s.stat_name = "sh_row_grants"
			and 	u.stat_name = "up_row_grants"
			and 	e.stat_name = "ex_row_grants"
			and	s.dbid = @tmp_dbid
			and	s.dbid = u.dbid
			and	u.dbid = e.dbid
			and	s.objid = @tmp_objid
			and	s.objid = u.objid
			and	u.objid = e.objid
			and	s.page_type = 0
			and	s.page_type = u.page_type
			and	u.page_type = e.page_type
			
			print @rpt_line
	
			select @rpt_line = rtrim(@ldspc+"Waits:"+@tab+
					str(s.stat_value,10)+@tab+@tab+
					str(u.stat_value,10)+@tab+@tab+str(e.stat_value,10))
			from tempdb..syslkstats s, tempdb..syslkstats u, tempdb..syslkstats e
			where 	s.stat_name = "sh_row_waits"
			and 	u.stat_name = "up_row_waits"
			and 	e.stat_name = "ex_row_waits"
			and	s.dbid = @tmp_dbid
			and	s.dbid = u.dbid
			and	u.dbid = e.dbid
			and	s.objid = @tmp_objid
			and	s.objid = u.objid
			and	u.objid = e.objid
			and	s.page_type = 0
			and	s.page_type = u.page_type
			and	u.page_type = e.page_type
			
			print @rpt_line
	
			select @rpt_line = rtrim(@ldspc+"Deadlocks:"+
					@tab+str(s.stat_value,10)+@tab+@tab+
					str(u.stat_value,10)+@tab+@tab+str(e.stat_value,10))
			from tempdb..syslkstats s, tempdb..syslkstats u, tempdb..syslkstats e
			where 	s.stat_name = "sh_row_deadlocks"
			and 	u.stat_name = "up_row_deadlocks"
			and 	e.stat_name = "ex_row_deadlocks"
			and	s.dbid = @tmp_dbid
			and	s.dbid = u.dbid
			and	u.dbid = e.dbid
			and	s.objid = @tmp_objid
			and	s.objid = u.objid
			and	u.objid = e.objid
			and	s.page_type = 0
			and	s.page_type = u.page_type
			and	u.page_type = e.page_type
			
			print @rpt_line
	
			select @rpt_line = rtrim(@ldspc+"Wait-time:"+
					@tab+str(s.stat_value,10)+" ms"+
					@tab+@tab+str(u.stat_value,10)+" ms"+
					@tab+@tab+str(e.stat_value,10)+" ms")
			from tempdb..syslkstats s, tempdb..syslkstats u, tempdb..syslkstats e
			where 	s.stat_name = "sh_row_waittime"
			and 	u.stat_name = "up_row_waittime"
			and 	e.stat_name = "ex_row_waittime"
			and	s.dbid = @tmp_dbid
			and	s.dbid = u.dbid
			and	u.dbid = e.dbid
			and	s.objid = @tmp_objid
			and	s.objid = u.objid
			and	u.objid = e.objid
			and	s.page_type = 0
			and	s.page_type = u.page_type
			and	u.page_type = e.page_type
			
			print @rpt_line
	
			select @rpt_line = rtrim(@ldspc+"Contention:"+
					@tab+str(@tmp_shrow_cont,10,2)+
					"%%"+@tab+@tab+
					str(@tmp_uprow_cont,10,2)+"%%"+
					@tab+@tab+str(@tmp_exrow_cont,10,2))+"%%"
			print @rpt_line

			print @blankline
		end

		fetch stats_rpt_csr into @tmp_expg_cont, @tmp_uppg_cont, @tmp_shpg_cont,
					@tmp_exad_cont, @tmp_shad_cont,
					@tmp_exrow_cont,@tmp_uprow_cont,@tmp_shrow_cont,
					@tmp_dbid,@tmp_objid, @tmp_lkscheme
		select @iter_count = @iter_count + 1

	end
	close stats_rpt_csr
	deallocate cursor stats_rpt_csr

	if (@iter_count = 0)
	begin
		print "----------------------------"
		print "No contention on any tables!"
		print "----------------------------"
	end
end
return 0
go
exec sp_procxmode 'sp_object_stats', 'anymode'
go
grant execute on sp_object_stats to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_modifystats')
begin
	drop procedure sp_modifystats
end
go
print "Installing sp_modifystats"
go


/*
** Messages for "sp_modifystats"
** 17460, "Object must be in the current database."
** 17563, "The table does not have a column named '%1!'."
** 18118, "Object '%1!' does not exist in this database."
** 18162, "'%1!' is a not a user table. '%2!' can be used only on user tables."
** 18884, "No statistics exist for column '%1!'."
** 18921, "Unable to execute stored procedure '%1!'.This version of the procedure is based on a '%2!' byte column ID and is incompatible with the server's column ID size.
** 18922, "Command failed. The 'value' argument for 'MODIFY_DENSITY' must be greater than or equal to 0.0 and not more than 1.0 when the 'absolute' method is specified.
** 18923, "The density value of column group '%1!' exceeded 1.0 and has been set to 1.0. Processing continues.
** 19569, "UPDATE STATISTICS permission denied on object '%1!'."
*/

/*
** IMPORTANT NOTE:
** This stored procedure uses the built-in function object_id() in the
** where clause of a select query. If you intend to change this query
** or use the object_id() or db_id() builtin in this procedure, please read the
** READ.ME file in the $DBMS/generic/sproc directory to ensure that the rules
** pertaining to object-id's and db-id's outlined there, are followed.
*/

create procedure sp_modifystats
	@objname	varchar(767) = null,	/* user table name */
	@column_group	varchar(1200) = null,	/* column name */
	@option		varchar(60) = null,	/* statistic to be modified */
	@opt_param1	varchar(255) = null,	/* optional param */
	@opt_param2	varchar(255) = null,	/* optional param */
	@opt_param3	varchar(255) = null	/* optional param */
as
	/*
	**
	**	Description: Allow sa to modify statistics stored
	**				in sysstatistics.
	**
	**	Argument:	all uses of sp_modifystats require at least
	**			three arguments: the table in question;
	**			the column or column group (note that this
	**			can be null); and the option.  Since different
	**			options may require different arguments,several
	**			@opt_param varchar(255) args are provided.
	**			Please do not modify the datatype of these
	**			params,	rather use the convert function within
	**			your option.
	**			Additional @opt_param parameters may be added
	**			as they are needed.
	**
	**	Options:	"REMOVE_SKEW_FROM_DENSITY"  -
	**				This option allows sa to change the
	**				total density of a column to be equal
	**				to the range density which is useful
	**				when data skew is present.
	**				This will also update the total density of
	**				any composite column statistics for which
	**				this column is the leading attribute.
	**				Most commonly, a composite index for which
	**				this column is the leading attribute would
	**				produce such composite column statistics,
	**				but they can also be produced by a
	**				composite update column statistics such as
	**				update statistics t1(a,b,c) 
	**				REQUIRES @objname, @column_group, @option.
	**
	**			"MODIFY_DENSITY" -
	**				This option provides a very granular
	**				mechanism to modify either the range or
	**				total density for a column or column
	**				group.
	**				Explanation of syntax:
	**				"[database].[owner].table" -
	**					object name you wish to modify
	**				{ "column_group" | "all" } - the column
	**					or groups of columns to modify.
	**				Rules: "all" will modify all columns
	**						for this table
	**					"a1" will modify column a1
	**					"a1,a2,a3" will
	**						modify the group a1,a2,a3
	**					"a1,%,a3" will modify
	**						the groups a1,a2,a3 and 
	**						a1,a5,a3, etc.
	**					"a1,%" will modify
	**						the groups a1,a2
	**						and a1,a2,a3, etc. but
	**						not a1.
	**					"a1%" will modify
	**						the groups a1,a2 and
	**						a1,a2,a3 AS WELL AS a1.
	**				{ range | total } - modify either
	**					range cell or total cell density
	**				{ absolute | factor } - type of
	**					modification to do. If absolute,
	**					then the value argument is the
	**					value you want.  If factor, then
	**					multiply existing value by the
	**					value argument
	**				value - the target value.  Must be >= 0
	**					and <= 1.0 if absolute is
	**					specified
	**				REQUIRES @objname,@column_group, @option,
	**					@opt_param1, @opt_param2,
	**					@opt_param3
	**
	**
	**	Future Info:	Other options can be added in the future
	**				using the @option parameter.
	**
	**	Dependencies:	This proc relies on the object_id built-in,
	**			and the db_name() built-in. Additionally,
	**			it must be created with updates to system
	**			tables enabled.
	**
	**	Errors:		This proc relies on the following errors:
	**				17460, 17563, 18118, 18162
	**			Errors 18884, 18921, 18922, 18923
	**				are installed for this proc.
	**
	**	Version:	This proc is for ASE 11.9.x and beyond
	**
	**	Usage:		sp_modifystats tabname, column_group, opt
	**
	**	History:	9/16/99	(mciccone)
	**			2/1/01	(dwein - changed structure of proc
	**					to improve modularization)
	**			2/1/01	(dwein - added MODIFY_DENSITY)
	*/

/*
** Note that any local variables needed for your module
** should be declared within that module only.  @rows,
** @err, and @colid are retained here to encourage their use.
*/

declare @rows int   /* Variable to check @@rowcount */
declare @err int    /* Variable to check @@error */
declare @colid int  /* Variable to hold colid from syscolumns */
declare @colidsize int  /* Variable to hold colid size for the server */
declare @role_name varchar(30) /* Stores role name */
declare @user_role_per int /* Variable to indicate whether user has
                           ** permission to execute the procedure
                           ** through any role
                           */

set nocount on

/*
** Check colid size to avoid executing this proc
** on a server with different colid size.
*/
select @colidsize = length from syscolumns
where id=object_id("syscolumns") and name="colid"

if (@colidsize != 2)
begin
	/*
	** 18921, "Unable to execute stored procedure '%1!'.This version of the
	** procedure is based on a '%2!' byte column ID and is incompatible 
	** with the server's column ID size."
	*/ 
	raiserror 18921, "sp_modifystats","2"
	return(1)
end

/* Check Usage */

/*
** Note that when adding modules to this procedure they must
** be added to this check.
*/

if (@objname is null) or (@option not in (
		"REMOVE_SKEW_FROM_DENSITY",
		"MODIFY_DENSITY"))
begin
	/*
	** When adding an option, be sure to add it to this usage
	** output.
	*/
	print "Usage: sp_modifystats objname, column_group, option"
	print "Valid Options:"
	print "REMOVE_SKEW_FROM_DENSITY,"
	print "MODIFY_DENSITY"
	return(1)
end

/* Only operate on tables in current database */
if @objname like "%.%.%" and
	substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
	/* 17460, "Object must be in the current database." */
	raiserror 17460
	return(1)
end

/* Check to see if the @objname is in sysobjects. */
if not exists (select * from sysobjects
	where id = object_id(@objname))
begin
	/* 18118, "Object '%1!' does not exist in this database." */
	raiserror 18118, @objname
	return(1)
end

/*
** Make sure @objname in NOT a system table.
** Check status bit within sysobjects.systats. This is same
** method the server uses internally to determine if an object
** is a system table.
*/
if ((select (sysstat & 15) from sysobjects where
	id = object_id(@objname)) = 1)
begin
	/*
	** 18162: '%1!' is a not a user table.
	** '%2!' can be used only on user tables.
	*/
	raiserror 18162, @objname, "sp_modifystats"
	return (1)
end

/*
** Check for UPDATE STATISTICS permission on object.
** Will have to check for groups and roles that the user belongs to.
*/
        
/*
** Initialise @user_role_per to 0, indicating user does not have permission
** for UPDATE STATISTICS through any user defined roles or contained roles
*/
select @user_role_per = 0

declare role_name cursor for
select srvro.name from sysprotects p1,
	master.dbo.syssrvroles srvro,
        sysroles ro
        where p1.id = object_id(@objname)
        and p1.uid = ro.lrid
        and ro.id = srvro.srid
        and p1.action = 326
for read only

open role_name

fetch role_name into @role_name
while (@@sqlstatus = 0 and @user_role_per != 1)
begin
        if @role_name is not null
        begin
                if (has_role(@role_name, 1) > 0)
                begin
                        /*
                        ** User has role which has
                        ** permission for UPDATE STATISTICS
                        */
                        select @user_role_per = 1
                end
        end
        fetch role_name into @role_name
end
close role_name
deallocate cursor role_name

/* 
** If user has sa_role, then has UPDATE STATISTICS 
** permission on the object 
*/
if ((charindex("sa_role", show_role()) = 0)                        

/*
** If user is the owner of the object, then has UPDATE STATISTICS permission
** on the object
*/
and not exists (select id from sysobjects
	where id = object_id(@objname)
        and uid = user_id())

and ((select max((abs(p.uid-u2.gid)*2) +
	((p.protecttype/2)^1))
        from sysprotects p, sysusers u2
        where p.id = object_id(@objname)
        and u2.uid = user_id()

        /* get rows for public, current users, user's groups */
        and (p.uid = 0           /* get rows for public */
        or p.uid = user_id()     /* current user */
        or p.uid = u2.gid)       /* users group */
        and (p.action in (326))  /* check for UPDATE STATISTICS privilege */
     )&1 ) is NULL

/*
** If @user_role_per = 0, then user doesnot have permission through any 
** user defined roles or contained roles 
*/
and @user_role_per = 0)
begin
	/* 19569, "UPDATE STATISTICS permission denied on object '%1!'." */
        raiserror 19569, @objname
        return(1)
end
								
if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
if @option = "REMOVE_SKEW_FROM_DENSITY"
/**Update total density for specified column**/
begin

	/*
	** The first action of any module is to setup
	** module specific variables and validate
	** any module-specific usage.
	*/

	/* Validate @columngroup value, as it is required by this module */
	/* Step 1 : make sure it isn't null */
	if (@column_group is null)
	begin
		print "Usage for REMOVE_SKEW_FROM_DENSITY option:"
		print "sp_modifystats table_name, column_name, REMOVE_SKEW_FROM_DENSITY"
		return(1)
	end
	/* Step 2: Check to see if the @column_group is in syscolumns */
	if not exists (select * from syscolumns
		where id = object_id(@objname) and name = @column_group)
	begin
		/* 17563: "The table does not have a column named '%1!'." */
		raiserror 17563, @column_group
		return(1)
	end

	/* We are ready to proceed with the actual work. */
	select @colid = (select colid from syscolumns
		where id = object_id(@objname) and name = @column_group)
	begin tran
		/*
		** Change the total density & update STATISTICS_EDITED flag
		*/ 
		update sysstatistics set c3 = c2,
			c1 = convert (varbinary,(convert(int, c1) |  2))
			where convert(smallint, substring(colidarray, 1, 2)) =  @colid
				and id = object_id(@objname)
				and formatid=100

		select @rows = @@rowcount, @err=@@error
		if @err != 0
		begin
			select @err
			rollback tran
			return(1)
		end
	if @rows >= 1
	begin
		/* Successful update */	
		commit tran
		return(0)
	end
	else
	begin
		/* 18884: No statistics exist for column '%1!'. */
		raiserror 18884, @column_group
		rollback tran
		return(1)
	end
end
/* end of REMOVE_SKEW_FROM_DATA module */

else if (@option = "MODIFY_DENSITY")
/* granular modification of density values */
begin

	/*
	** The first action of any module is to setup
	** module specific variables and to validate
	** any module-specific usage.
	*/

	/* declare values local to this module */
	declare @density_type varchar(5)	/* @opt_param1 */
	declare @method varchar(8)	/* @opt_param2 */
	declare @target_value double precision	/* @opt_param3 */
	declare @col_count int, @col_length int
	declare @col_position int, @position int
	declare @colidarray varbinary(100)
	declare @indid smallint
	declare @partitionid int
	declare @column_name varchar(255)
	declare @column_string varchar(1200)

	/* assign @opt_param values to semantically approriate values */
	select @density_type = @opt_param1, @method = @opt_param2,
		@target_value = convert(double precision, @opt_param3)

	/* Validate arguments*/
	if (@column_group is null) or (@density_type not in ("range", "total"))
		or (@method not in ("absolute", "factor"))
		or (@target_value is null)
	begin
		print "Usage for MODIFY_DENSITY option:"
		print "sp_modifystats ""[database].[owner].table"", { ""column_group"" | ""all"" },"
		print "  MODIFY_DENSITY, { range | total }, {absolute | factor}, ""value"" "
		return(1)
	end

	/* Make sure our value isn't bogus */
	if (@target_value < 0) or (@target_value > 1.0 and @method = "absolute")
	begin
		/*
		** 18922, "Command failed. The 'value' argument for 
		** 'MODIFY_DENSITY' must be greater than or equal to 0.0 and
		** not more than 1.0 when the 'absolute' method is specified."
		*/ 
		raiserror 18922
		return(1)
	end

	/* Go through the column list looking for valid columns */
	if @column_group != "all"
	begin
		select @col_length = char_length(@column_group)
		select @position = 1
		select @col_count = 0

		/* Eliminate possible white spaces introduced by user */
		select @position = charindex(" ",@column_group)
		while (@position != 0)
		begin
			select @column_group =
				stuff(@column_group,@position,1,null)
			select @position = charindex(" ",@column_group)
		end

		/* Eliminate possible tab chars introduced by user */
		select @position = charindex(char(9),@column_group)
		while (@position != 0)
		begin
			select @column_group =
				stuff(@column_group,@position,1,null)
			select @position = charindex(char(9),@column_group)
		end

		select @position = 1
		select @col_length = char_length(@column_group)

		/*
		** We must loop through @column_group to find the column names.
		** @position is used in the outer loop, and marks the character
		** position within @column_group.  @col_position is used in
		** the inner loop and marks the number of characters FROM @position
		** until we hit either the end of the string or a comma.
		*/
		while (@position <= @col_length)
		begin
			select @col_position = 0
			while ((substring(@column_group,
				(@position + @col_position),1) != ",") and
				((@position + @col_position) <= @col_length))
			begin
				select @col_position = @col_position  + 1
			end

			/* Check for wildcards */
			if (substring(@column_group, @position, @col_position) != "%")
			begin
				/* 
				** Our column is not a wildcard, so make sure 
				** it exits
				*/
				if not exists (select colid from syscolumns
					where id = object_id(@objname)
					and name like substring(@column_group,
							@position, @col_position))
				begin
					select @column_name = substring(@column_group,
						@position, @col_position)
					/*
					** 17563: "The table does not have a
					** column named '%1!'."
					*/
					raiserror 17563, @column_name
					return(1)
				end
			end
			select @position = @position + @col_position + 1
			select @col_count = @col_count + 1
		end
	end /* column validation end */

	/* Create a #table to hold the old and new values */
	create table #densities (indid smallint, partitionid int,
			colidarray varbinary(100),
			column_string varchar(1200) null,
			density_type char(5),
			old_value double precision,
			new_value double precision null)

	/* Create an index to aid in cursor processing */
	create unique clustered index densities_CI on
	#densities(indid, partitionid, colidarray)

	/*
	** Insert into #densities all formatid 100 rows for the object
	** we note the old value and set the new value to @target_value
	*/
	insert #densities select indid, partitionid, colidarray, null, 
		@density_type,
	case
		when @density_type = "range" then convert(double precision,c2)
		when @density_type = "total" then convert(double precision,c3)
	end
	, @target_value
	from sysstatistics where formatid = 100 and id = object_id(@objname)

	/* If we are using factoring, correct the new value */
	if @method = "factor"
		update #densities set new_value = (old_value * @target_value)

	/* We now need to cursor through #densities and rebuild  column string */
	declare new_densities cursor for
		select indid, partitionid, colidarray 
		from #densities for update

	open new_densities
	fetch new_densities into @indid, @partitionid, @colidarray
	select @column_string = ""
	while (@@sqlstatus = 0)
	begin
		select @position = 1
		select @col_length = char_length(@colidarray)
		/* Build the column list string */
		while (convert(smallint,substring(@colidarray,@position,2)) != 0)
			and (@position <= @col_length)
		begin
			select @colid = convert(smallint,
					substring(@colidarray,@position,2))
			if @position != 1
				select @column_string = @column_string + ","
			select @column_string = @column_string +
				(select name from syscolumns where
				id = object_id(@objname) and
				colid = @colid)
			select @position = @position + 2
		end

		/* Now update the #table with the string */
		update #densities set column_string =
			ltrim(rtrim(@column_string))
			where colidarray = @colidarray
			and indid = @indid
			and partitionid = @partitionid

		/* Get rid of the row if we don't want it */
		if @column_group != "all"
			delete #densities
				where column_string not like @column_group
				and colidarray = @colidarray
				and indid = @indid
				and partitionid = @partitionid

		/* Check to see it our row stills exists */
		if exists (select * from #densities
				where colidarray = @colidarray
				and indid = @indid
				and partitionid = @partitionid)
		begin
			/*
			** Now check to see if we have gone over 1.0 for
			** a density
			*/
			if (select new_value from #densities
				where colidarray = @colidarray
				and indid = @indid
				and partitionid = @partitionid) > 1.0
			begin
				/* 
				** 18923, "The density value of column group 
				** '%1!' exceeded 1.0 and has been set to 1.0.
				** Processing continues."
				*/
				raiserror 18923, @column_string

				update #densities
					set new_value = 1.0
					where colidarray = @colidarray
					and indid = @indid
					and partitionid = @partitionid
			end
		end
		select @column_string = ""
		fetch new_densities into @indid, @partitionid, @colidarray
	end

	close new_densities
	deallocate cursor new_densities

	/*
	** We can now set sysstatistics appropriately
	** Notice that c1 is or'd with 2, as this sets the stats edited flag
	*/
	begin transaction

	if (@density_type = "range")
	begin
		update sysstatistics set c2 = convert(varbinary(255),new_value),
			c1 = convert (varbinary,(convert(int, c1) |  2))
			from #densities where
			sysstatistics.colidarray = #densities.colidarray
			and formatid = 100 and id = object_id(@objname)
			and sysstatistics.indid = #densities.indid
			and sysstatistics.partitionid = sysstatistics.partitionid
	end
	else
	begin	/* Setting total density in this case */
		update sysstatistics set c3 = convert(varbinary(255),new_value),
			c1 = convert (varbinary,(convert(int, c1) |  2))
			from #densities where
			sysstatistics.colidarray = #densities.colidarray
			and formatid = 100 and id = object_id(@objname)
			and sysstatistics.indid = #densities.indid
			and sysstatistics.partitionid = sysstatistics.partitionid
	end

	/* Do some error checking */
	select @rows = @@rowcount, @err=@@error
	if @err != 0
	begin
		select @err
		rollback tran
		return(1)
	end
	if @rows >= 1
	begin
		/* Successful update */
		commit tran
	end
	else
	begin
		/* 18884: No statistics exist for column '%1!'. */
		raiserror 18884, @column_group
		rollback tran
		return(1)
	end

	/*
	** Now display the output.  Pull new values from
	** sysstatistics for accuracy purposes
	*/

	select "Densities updated for table " + @objname +" by SP_MODIFYSTATS"

	select d.column_string "Column Group",
			d.density_type "Density Type",
			convert(decimal(9,8), d.old_value) "Original Value",
			case
				when @density_type = "range" then
					convert(decimal(9,8),
					convert(double precision,s.c2))
				when @density_type = "total" then
					convert(decimal(9,8),
					convert(double precision,s.c3))
			end "New Value"
			from sysstatistics s, #densities d where
			s.formatid = 100 and s.id = object_id(@objname) and
			s.colidarray = d.colidarray

	/* We are all done! */
	return(0)

end
go

exec sp_procxmode 'sp_modifystats', 'anymode'
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_maplogin')
begin
	drop procedure sp_maplogin
end
go
print "Installing sp_maplogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Messages for "sp_maplogin"    
**
** 17260, "Can't run '%1!' from within a transaction."
** 18294, "User '%1!' is not a local user -- request denied."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
** 19257, "The authentication mechanism '%1!' is not valid."
** 19256, "Client authentication mapping updated."
** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
** 19445, "External name '%1!' is already a local login -- map request denied."
** 19447, "User '%1!' allows only '%2!' authentication mechanism to be used -- request denied."
** 19450, "A mapping with authentication mechanism '%1!' is not allowed, only action 'drop' is permitted."
** 19453, "Cannot define a mapping for ALL authentications and ALL logins -- map request denied.
** 19940, "Client authentication mapping overwritten. Previous values were @authentication_mech='%1!', @client_name='%2!' and @login_name='%3!'.
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_maplogin
	@authmethod	varchar(30) = NULL,	/* Authentication mechanism */
	@externname	varchar(255) = NULL,	/* client user name */
	@loginame	varchar(255) = NULL	/* user's local name */
AS
BEGIN

DECLARE	@msg		varchar(1024),
	@authid		int,
	@any_authid	int,			/* LOGIN_ANY auth id */
	@syslog_authid	int,			/* syslogin auth id */
	@syslog_authmch	varchar(30),		/* syslogin auth mech name */
	@suid		int,
	@login_class	smallint,		/* omni's attribute  class */
	@attrib		smallint,		/* attr. id for ext. login */
	@action		smallint,
	@dummy		int,
	@HA_CERTIFIED	tinyint,   /* Is the SP HA certified ? */
	@retstat	int,
	@config		int,
	@del		int,
	@auth_mech      varchar(30),
	@client_name    varchar(255),
	@login_name     varchar(255)
	
/*
** Only a user with sso_role can add extern login mappings
*/
	if (proc_role("sso_role") < 1)
		return 1

	select @HA_CERTIFIED = 0
	select @retstat = 0



/* check to see if we are using HA specific SP for a HA enabled server */
	exec @retstat = sp_ha_check_certified 'sp_maplogin', @HA_CERTIFIED
	if (@retstat != 0)
        	return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
	if @@trancount > 0
	BEGIN
		/*		
		** 17260 Can't run '%1!' from within a transaction.
		*/
		raiserror 17260, "sp_maplogin"
		return 1
	END

/* 
** We cannot define any mapping for all authentications
** and all logins
*/
	if ((@authmethod is null or upper(@authmethod) = 'ANY') 
		and (@externname is null or upper(@externname) = 'ANY'))
	BEGIN
		/*		
		** 19453  "Cannot define a mapping for ALL authentications 
		** and ALL logins -- map request denied.
		*/
		raiserror 19453
		return 1
	END

/*
** Check that the auth method is valid. NULL means ALL.
*/
	if (@authmethod is null)
		select @authmethod = 'ANY'

        /*
        ** Check whether authentication mechanism specified is valid or not.
        ** 'AUTH_DEFAULT' and 'AUTH_MASK' are new values added in spt_values
        ** used to obtain value of default ('ANY') authmech or authentication
        ** mask respectively. They are not valid names that the user can
        ** specify as authentication mechanism.
        */
	select	@authid = low, @config = number
		from master.dbo.spt_values
		where type = 'ua' and upper(name) = upper(@authmethod)
		and upper(name) not in ('AUTH_DEFAULT', 'AUTH_MASK')

	if @@rowcount = 0 
	BEGIN
		/*		
		** 19257  "The authentication mechanism '%1!' is not valid .
		*/
		raiserror 19257, @authmethod
		return (1)
	END

/*
** Check that the authentication method is enabled. The configuration option
** is in spt_values.number.
** For SMP or SDC, look up syscurconfigs for local instance.
*/
	if (@config != 0) and not exists(select 1
		from master.dbo.syscurconfigs a

		where a.config = @config and a.value != 0)

	BEGIN
		/*
		** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
		*/
		exec sp_getmessage 19259, @msg output
		print @msg, @authmethod
	END

	select @del = 0
	
/*
** Check the login name/action
*/
	if upper(@loginame) = "CREATE LOGIN"
		select @suid = -3
	else if (upper(@loginame) = 'DROP')
		select @del = 1
	else
	BEGIN
/*
** Check that the @loginame is valid.
*/
		/*
		**  Set a mask with all the authentication bits using
		** 'AUTH_MASK'
		*/
		select	@any_authid = low
			from master.dbo.spt_values
			where type = 'ua' and upper(name) = 'AUTH_MASK'

		select @suid = suid, @syslog_authid = (status & @any_authid)
			from master.dbo.syslogins
			where name = @loginame
		if @@rowcount = 0  
		BEGIN
			/*		
			** 18294 "User '%1!' is not a local user -- 
			** request denied."
			*/
			raiserror 18294, @loginame
			return (1)
		END

		/* authid of 0 means ANY, set it the local var to this value. */
		if @syslog_authid = 0
			select @syslog_authid = @any_authid

/*
**  Check the authentication mechanism for a login and authentication
**  mechanism parameter to sp_maplogin do not conflict.  There should
**  be at least one bit matching in the two masks representing the
**  authentication mechanism.
**
**  The bitmask for auth mech NONE/NULL has already been mapped to ANY.
*/

		if (@syslog_authid & @authid) = 0
		BEGIN
			select	@syslog_authmch = name
				from master.dbo.spt_values
				where type = 'ua' and low = @syslog_authid
				and upper(name) not in ('AUTH_DEFAULT',
				'AUTH_MASK')
			/*		
			** 19447 "User '%1!' allows only '%2!' authentication 
			** mechanism to be used -- request denied."
			*/
			raiserror 19447, @loginame, @syslog_authmch
			return (1)
		END
	END

	if (@externname is null or upper(@externname) = 'ANY')
	BEGIN
		select @externname = '*'
	END

	if (@externname != '*' and @del = 0)
	BEGIN
/*
**  Check that an explicit value of @externname is not already a local login
*/
		if exists (select 1 
			from master.dbo.syslogins 
			where name = @externname)
		BEGIN
			/*		
			** 19445 "External name '%1!' is already a local 
			** login -- map request denied."
			*/
			raiserror 19445, @externname
			return (1)
		END
	END
/*
** Check if the ASE authentication mechanism is used for the mapping.
** New behavior in ASE 12.5.4 prevents local logins from being mapped
** to other local logins, making most actions with ASE auth mech invalid.
** The only allowed action allowed for ASE is 'drop', to aid in removing any
** mappings that may have been added in earlier releases.
*/
	if (upper(@authmethod) = "ASE") and (@del = 0)
	BEGIN
		/*		
		** 19450  "A mapping with authentication mechanism '%1!' is
		** not allowed, only action 'drop' is permitted."
		*/
		raiserror 19450, @authmethod
		return (1)
	END
/*
** The mapping is stored in sysattributes. The entries for external
** authentication mechanisms are as follows:
**
**	- class:	20
**	- attribute:	0
**	- object:	mapped suid
**			- It may have a real suid or,
**			- INVALID_SUID (-2), to map using the external name.
**			- CRTLOGIN_SUID (-3), to create login if it does not
**			  exist.
**	- object_cinfo:	external name, or '*' for all external names.
**	- object_info1: authentication mechanism. If we map any authentication
**			it will contain LOGIN_ALL, that is an OR of all the
**			existing authentication mechinsms.
**
** If there is already an entry for that external user, we'll update
** it, else we'll insert a new row.
** For each user only one authentication mechanism is allowed. However,
** when setting a generic map (extern user name is null), there can
** be multiple entries for it. We can specify that all the users using
** PAM will be mapped as u1, all users using LDAP will be mapped
** u2, etc.
*/
	select @login_class = 20, @attrib = 0

/*
** Check whether a mapping already exists. If it does, update it
** or delete it, depending on the parameter @delete.
** If the client user name is null, we will look for a mapping for
** all users with the authentication method specified.
** If the client user name is not null, we will look for a mapping
** for this user.
*/
	if ((@externname = '*' and 
		exists(select * from master.dbo.sysattributes where
			class = @login_class and attribute = @attrib and
			object_cinfo = '*' and
			object_info1 = @authid))
	   or (@externname != '*' and
		exists(select * from master.dbo.sysattributes where
			class = @login_class and attribute = @attrib and 
			object_cinfo = @externname)))
	BEGIN	
		if (@del = 0)
			select @action = 2	/* update attribute */
		else
			select @action = 3      /* delete attribute */
	END
	else 
	BEGIN
		if (@del = 0)
			select @action = 1 	/* insert attribute */	
		else
			/* Nothing to delete. */
			return (0)
	END

/*
** First validate the row. 
*/
	if attrib_valid(@login_class, @attrib, "LM", @suid, @authid, NULL, NULL,
		@externname, NULL, NULL, NULL, NULL, NULL, @action) = 0         
	BEGIN
		return(1)
	END



/*
** Now insert/update/delete the row
*/
	if @action = 1
	BEGIN
		insert into master.dbo.sysattributes (class, attribute, 
			object_type, object_info1, object, object_cinfo,
			image_value, object_info2)
		values (@login_class, @attrib, "LM", @authid, @suid, 
			@externname, null, null)

		if (@@error != 0)
			goto clean_all

                /*
                ** 19256 "Client authentication mapping updated."
                */
                exec sp_getmessage 19256, @msg output
                print @msg
	END
	else if @action = 2 
	BEGIN
	        if (@externname = '*') 
                BEGIN
			/* 
			** Select the previous mapping information to be 
			** displayed in the message before updating the row.
			*/
                        select  @auth_mech = isnull(s.name, "ANY"),
                                @client_name =
                                case object_cinfo
                                        when '*' then "ANY"
                                        else object_cinfo
                                end,
                                @login_name =
                                case object
                                        when -2 then "ANY"
                                        when -3 then "CREATE LOGIN"
                                        else isnull(suser_name(object), "NO MAP")
                                end
                        from master.dbo.sysattributes, master.dbo.spt_values s
                        where class = @login_class and attribute = @attrib and
                                (object_info1 = s.low) and
                                (s.name not in ('AUTH_MASK')) and
                                (s.type = 'ua') and
                                object_cinfo = '*' and object_info1 = @authid

			update master.dbo.sysattributes
			set     object = @suid
			where class = @login_class and attribute = @attrib and
                        	object_cinfo = '*' and
                        	object_info1 = @authid
		END
		else
                BEGIN
                        /*
                        ** Select the previous mapping information to be
                        ** displayed in the message before updating the row.
                        */
                        select  @auth_mech = isnull(s.name, "ANY"),
                                @client_name =
                                case object_cinfo
                                        when '*' then "ANY"
                                        else object_cinfo
                                end,
                                @login_name =
                                case object
                                        when -2 then "ANY"
                                        when -3 then "CREATE LOGIN"
                                        else isnull(suser_name(object), "NO MAP")
                                end
                        from master.dbo.sysattributes, master.dbo.spt_values s
                        where class = @login_class and attribute = @attrib and
                                (object_info1 = s.low) and
                                (s.name not in ('AUTH_MASK')) and
                                object_cinfo = @externname
	
			update master.dbo.sysattributes
			set	object = @suid, object_info1 = @authid
			where	class = @login_class and 
				attribute = @attrib and
				object_cinfo = @externname 
		END

		if (@@error != 0)
			goto clean_all

                /*
                ** 19940 "Client authentication mapping overwritten.
                ** Previous values were @authentication_mech='%1!',
                ** @client_name='%2!' and @login_name='%3!'."
                */
                exec sp_getmessage 19940, @msg output
                print @msg, @auth_mech, @client_name, @login_name
	END 
	else if @action = 3
	BEGIN
		delete master.dbo.sysattributes
		where   class = @login_class and 
			attribute = @attrib and
			object_cinfo = @externname and
			object_info1 = @authid
		if (@@error != 0)
			goto clean_all

                /*
                ** 19256 "Client authentication mapping updated."
                */
                exec sp_getmessage 19256, @msg output
                print @msg
	END



	/*
	** Sync the in-memory RDES with the new values
	** in sysattributes.
	*/
	if attrib_notify(@login_class, @attrib, "LM", @suid, @authid, NULL,
			NULL, NULL, NULL, NULL, NULL, NULL, NULL,
			@action) = 0
		return (1)
	else
		return (@retstat)
END

clean_all:

	return (1)
go
exec sp_procxmode 'sp_maplogin', 'anymode'
go
grant execute on sp_maplogin to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpmaplogin')
begin
	drop procedure sp_helpmaplogin
end
go
print "Installing sp_helpmaplogin"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_helpmaplogin"    
**
** 19257  "The authentication mechanism '%1!' is not valid." 
*/
create procedure sp_helpmaplogin
	@authmethod	varchar(255) = null,	/* Authentication mechanism */
	@externname	varchar(255) = null	/* user's remote name */
as
begin

declare	@authid		int,
	@suid		int,
	@login_class	smallint,
	@attrib		smallint

/*
** Only a user with sso_role can see external login mappings
*/
if (proc_role("sso_role") < 1)
	return 1

/*
** Check that the auth method is valid. NULL means ANY.
** Avoid selecting 'AUTH_MASK' for the value of 'ANY'.
*/
if (@authmethod is null)
	select @authmethod = 'ANY'

if ((@externname is null) or (@externname = 'ANY'))
	select @externname = '*'

select	@authid = low
from master.dbo.spt_values
where type = 'ua' and name = upper(@authmethod)

if @@rowcount = 0 
begin
	/*		
	** 19257  "The authentication mechanism '%1!' is not valid." 
	*/
	raiserror  19257, @authmethod
	return (1)
end

select @login_class = 20, @attrib = 0

select	isnull(s.name, "ANY") as authentication,
	case object_cinfo
		when '*' then "ANY"
		else object_cinfo
	end as clientname,
	case object 
		when -2 then "ANY"
		when -3 then "CREATE LOGIN"
		else isnull(suser_name(object), "NO MAP")
	end loginame
into #sphelpmap1rs
from master.dbo.sysattributes, master.dbo.spt_values s
where 	class = @login_class and attribute = @attrib and
	(object_info1 = s.low) and (s.name not in ('AUTH_MASK')) and
	(s.type = 'ua') and
	(object_cinfo = @externname or @externname = '*' ) and 
	(object_info1 & @authid) != 0
exec sp_autoformat @fulltabname = #sphelpmap1rs,
	@selectlist = "authentication, 'client name' = clientname, 'login name' = loginame",
	@orderby = "order by 1,2"
drop table #sphelpmap1rs 
return (0)
end
go
exec sp_procxmode 'sp_helpmaplogin', 'anymode'
go
grant execute on sp_helpmaplogin to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpjava')
begin
	drop procedure sp_helpjava
end
go
print "Installing sp_helpjava"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_helpjava"
**
** 18697, "Usage: sp_helpjava ['class' [, name [, 'detail' |, 'depends']]
**                            | 'jar' [, name [, 'depends']]]"
** 18698, "Class '%1!' is not a system class and is not installed in the
**	   current database."
** 18699, "Jar '%1!' does not exist in this database."
** 18817, "Cannot run this command because Java services are not enabled.
**	   A user with System Administrator (SA) role must reconfigure the
**	   system to enable Java."
** 18901, "Objects that depend on this class: " 
** 18902, "Class name: '%1!'"
*/

create procedure sp_helpjava
@help_option varchar(8) = NULL,   /* The option can be 'class' or 'jar' */
@object_name varchar(767) = NULL,  /* jar name or class name */
@detail_option varchar(8) = NULL  /* Show detailed information of a class */
as

declare @sptlang int
declare @method_variable varchar(92)
declare @val char(10)
declare @maxlen int
declare @msg varchar(1024)
declare @class_name varchar(255)
declare @sqlj_proc int 		  /* indicates a sqlj proc */

if exists (select s.value from master..sysconfigures s
	where s.name = "enable java"
	and s.value = 0) 
begin
	/* 
	** 18817, "Cannot run this command because Java services are not 
	** enabled. A user with System Administrator (SA) role must 
	** reconfigure the system to enable Java."
	*/
	raiserror 18817
	return  (1)
end

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

select @sptlang = @@langid

if @@langid != 0
begin
	if not exists (
		select * from master.dbo.sysmessages where error
		between 17100 and 17109
		and langid = @@langid)
	    select @sptlang = 0
end

select  @sqlj_proc = hextoint("0x2000000")    /* value of O2_JPROC */

set nocount on

/*
**  If no @help_option given AND no @object_name given, give a little 
**  info about all classes and jars.
*/
if @help_option is NULL and @object_name is NULL and @detail_option is NULL
begin

	print ""

	/* Display a list of all Java classes installed in this database */
	/* and the jars they belong to.					 */
	select classes = x.xtname, 
		j  = isnull(j.jname, '')
	into #sphelpjava1rs
		from sysxtypes x, sysjars j
		where x.xtcontainer *= j.jid

	exec sp_autoformat @fulltabname = #sphelpjava1rs,
		@selectlist = "'Classes installed' = classes,'Jar' = j",
		@orderby = "order by 1"
	drop table #sphelpjava1rs

	print ""

	/* Display a list of all jars installed in this database */
	exec sp_autoformat @fulltabname = sysjars,
		@selectlist = "'Jars installed' = jname",
		@orderby = "order by jname"

	print ""
	return (0)
end

else
/*
** If @help_option is "jar" and @object_name is NULL, list all of the 
** jars in the database.
*/
if @help_option = "jar" and @object_name is NULL and @detail_option is NULL
begin
	/* Display a list of all jars installed in this database. */

	exec sp_autoformat @fulltabname = sysjars,
	@selectlist = "'Jars installed' = jname",
	@orderby = "order by jname"

	return (0)
end

else
/*
** If @help_option is "class" and @object_name is NULL, list all of 
** the classes in the database.
*/
if @help_option = "class" and @object_name is NULL and @detail_option is NULL
begin
	/* Display list of all Java classes installed in this database. */

	exec sp_autoformat @fulltabname = sysxtypes,
		@selectlist = "'Classes installed' = xtname",
		@orderby = "order by xtname"

	return(0)
end
else
/* 
** If @help_option is "jar" and an @object_name is specified, list all of
** the classes belonging to that jar.
*/
if @help_option = "jar" and @object_name is not NULL and @detail_option is NULL
begin
	if exists ( select *
		from sysjars j
		where j.jname = @object_name )
	begin
		
		select  jname
		into #sphelpjava2rs
			from sysjars
			where jname = @object_name
		exec sp_autoformat @fulltabname = #sphelpjava2rs,
		@selectlist = "'Jars' = jname"
		drop table #sphelpjava2rs

		select x.xtname
		into #sphelpjava3rs
			from sysxtypes x, sysjars j
			where x.xtcontainer = j.jid
			and j.jname = @object_name
		exec sp_autoformat @fulltabname = #sphelpjava3rs,
			@selectlist = "'Classes' = xtname",
			@orderby = "order by xtname"
		drop table #sphelpjava3rs
		return (0)
	end
	else 
	begin
		/* 18699, "Jar '%1!' does not exist in this database." */ 
		raiserror 18699, @object_name
		return  (1)
	end
end
/*
** If @help_option is "jar", an @object_name is specified, and the detail
** option is "depends" then list the classes that belong to that jar
** and those classes dependencies.
*/

if @help_option = "jar" and @object_name is not NULL
                                and @detail_option = "depends"
begin
        if exists ( select *
                from sysjars j
                        where j.jname = @object_name )
        begin
                declare help_cur cursor
                for select x.xtname
                        from sysxtypes x, sysjars j
                        where x.xtcontainer = j.jid
                        and j.jname = @object_name
                        order by x.xtname
                        for read only
                open help_cur
                fetch help_cur into @class_name
                while(@@sqlstatus = 0)
                begin
                        if exists (select * from sysdepends d, sysxtypes x,
                                        syscolumns c
                                where x.xtname = @class_name and
                                        (d.depid = x.xtid or
                                        c.xtype = x.xtid))
                        begin
				/* 
				** 18902, "Class name: '%1!'"
				*/
				exec sp_getmessage 18902, @msg output
				print @msg, @class_name
                                select  distinct id = d.id,
                                        name = o.name,
                                        type = m.description,
                                        owner = user_name(o.uid)
				into #sphelpjava4rs
                                from sysobjects o, sysxtypes x, sysdepends d,
                                        sysusers u, master.dbo.spt_values v,
                                        master.dbo.sysmessages m
                                where   @class_name = x.xtname and
                                        x.xtid = d.depid and
                                        d.id = o.id  and
                                        o.sysstat & 2063 = v.number and
                             		((v.type = "O" and 
					    (o.sysstat2 & @sqlj_proc) = 0) or
                                  	    (v.type = "O2" and 
					    (o.sysstat2 & @sqlj_proc) != 0)) and
                                        v.msgnum = m.error
                                union
                                select distinct id = c.id,
                                        name = o.name,
                                        type = convert(char(15), m.description),
                                        owner = user_name(o.uid)
                                        from sysobjects o, sysxtypes x,
                                        syscolumns c, sysusers u,
                                        master.dbo.spt_values v,
                                        master.dbo.sysmessages m
                                where   @class_name = x.xtname and
                                        x.xtid = c.xtype and
                                        c.id = o.id  and
                                        o.sysstat & 2063 = v.number and
					((v.type = "O" and 
                                            (o.sysstat2 & @sqlj_proc) = 0) or
                                            (v.type = "O2" and 
                                            (o.sysstat2 & @sqlj_proc) != 0)) and
                                        v.msgnum = m.error
			exec sp_autoformat @fulltabname = #sphelpjava4rs,
                                @orderby = "order by 3 desc, 2 asc"
			drop table #sphelpjava4rs
                        end
                fetch help_cur into @class_name
                end
                close help_cur
                deallocate cursor help_cur
                return (0)
        end
	else
	begin
		/* 18699, "Jar '%1!' does not exist in this database." */
		raiserror 18699, @object_name
		return  (1)
	end
end

else
/* If @help_option is "class", an @object_name is specified, and 
** the @detail_option is "depends" then list the java objects that 
** depend on this class.
*/
if (@help_option = "class" and @object_name is not NULL
				and @detail_option = "depends")
begin
        /*
	** 18901, "Objects that depends on this class: "
	*/
		exec sp_getmessage 18901, @msg output
		print @msg

	select 	distinct id = d.id,
		name = o.name,
		type = m.description,
		owner = user_name(o.uid)
	into #sphelpjava5rs
	from sysobjects o, sysxtypes x, sysdepends d, sysusers u, 
		master.dbo.spt_values v, master.dbo.sysmessages m
	where 	@object_name = x.xtname and
		x.xtid = d.depid and
		d.id = o.id  and
		o.sysstat & 2063 = v.number and
		((v.type = "O" and
                     (o.sysstat2 & @sqlj_proc) = 0) or
                     (v.type = "O2" and
                     (o.sysstat2 & @sqlj_proc) != 0)) and
		v.msgnum = m.error
        union
	select distinct id = c.id,
		name = o.name,
		type = m.description,
		owner = user_name(o.uid)
	from sysobjects o, sysxtypes x, syscolumns c, sysusers u,
		master.dbo.spt_values v, master.dbo.sysmessages m
	where   @object_name = x.xtname and
		x.xtid = c.xtype and
		c.id = o.id  and
		o.sysstat & 2063 = v.number and
                ((v.type = "O" and
                     (o.sysstat2 & @sqlj_proc) = 0) or
                     (v.type = "O2" and
                     (o.sysstat2 & @sqlj_proc) != 0)) and
		v.msgnum = m.error
	exec sp_autoformat @fulltabname = #sphelpjava5rs,
		@orderby = "order by 3 desc, 2 asc"
	drop table #sphelpjava5rs
	return (0)
end
else
/* 
** If @help_option is "class" and an @object_name is specified, there
** exist two cases. 1) If the option 'detail' is specified, detailed 
** information of the class will be printed. 2) If the option 
** 'detail' is not specified, except for the class name, interfaces, 
** class constructors etc, only declared methods and declared fields
** in the class will be printed.
*/
if ((@help_option = "class" and @object_name is not NULL
			   and @detail_option is NULL) or 
    (@help_option = "class" and @object_name is not NULL
			   and @detail_option = "detail"))
begin
	declare @show_detail varchar(8)
	declare @vstr varchar(80)
	if @detail_option = "detail"
		select @show_detail = "detail" 
	else
		select @show_detail = "null" 

	create table #InterfaceTable(interface varchar(255))
	create table #ConstructorTable(constructor varchar(255))
	create table #MethodTable(method varchar(255))
	create table #FieldTable(field varchar(255))

	/*
	** The following statements that reference java class
	** sybase.aseutils.ClassInformation are contained in 
	** a string. The statements are executed at run time
	** only. They are not compiled when system procedure 
	** sp_helpjava is installed by the tool installmaster.
	** The purpose is to avoid errors of installmaster when 
	** "enable java" is 0 in master..sysconfigures.  
	** Use double quotes to delimit the concatenated execute immediate
	** string and single quotes around the arguments to the ClassInformation
	** method.  In this way, if the set quoted_identifier option is on
	** when the user invokes sp_helpjava, the arguments to ClassInformation
	** are treated as strings and not as identifiers, which is syntactically
	** what the parser requires.
	** Note that the double quoted concatenated string argument to execute
	** immediate will not itself be treated as an delimited identifier when
	** the procedure sp_helpjava is created because (it is assumed) set
	** quoted_identifier is NEVER on when installmaster is run.
        **
	** Note that there is now special handling for a new method added to
	** the ClassInformation class to extract the version number of a class
	** to enable admins to determine which classes would need to be removed
	** or recompiled in the event that the PCA/JVM is downgraded to a prior JVM.
 	*/

        /*
        ** if this is the PCA/JVM the getClassVersion method exists in the 
	** ClassInformation class, construct the call accordingly (for Kona
	** we just make @vstr an empty string)
        */
        if (select value from master..sysconfigures where name = 'enable pci') = 1
        begin
                set @vstr = "select 'Class Version' = @class_details>>getClassVersion()  print '' "
        end
        else
        begin
                set @vstr = " "
        end

	exec(
        "declare @class_details sybase.aseutils.ClassInformation " +
        "select @class_details = " +
        "new sybase.aseutils.ClassInformation('"+ @object_name +"', '" + @show_detail + "') " +

        "if (select @class_details>>getClassName()) is NULL " +
        "begin " +
                "/* 18698, 'Class %1! is not a system class and is not " +
                    "installed in the current database.' */ " +
                "raiserror 18698,'" + @object_name +"' " +
        "end " +

        "else " +
        "begin " +
                "/* Print out the name of the class */ " +
                "select 'Class Name' = @class_details>>getClassName() " +

                "print '' " +

		@vstr +

                "/* Print out the class modifiers */ " +
                "select 'Class Modifiers' = @class_details>>getClassModifiers() " +

                "print '' " +

                "/* Print out the SerialVersionUID of the class */ " +
                "if (select @class_details>>getSerialVersionUid()) is not NULL " +
                "begin " +
                "select 'Class SerialVersionUID' = @class_details>>getSerialVersionUid() " +
                "print '' " +
                "end " +

                "/* Print out the interfaces that this class implements */ " +
                "if (select @class_details>>getFirstInterface()) is not NULL " +
                "begin " +
                "insert into #InterfaceTable(interface) " +
                        "select interface = convert(varchar(255), " +
                        "@class_details>>getFirstInterface()) " +
                "while (select @class_details>>hasMoreInterfaces()) = 1" +
                "begin " +
                        "insert into #InterfaceTable (interface) " +
                        "(select interface = " +
                        "@class_details>>getNextInterface()) " +
                "end " +
                "end " +

                "/* Print out any superclasses this class extends */ " +
                "select 'Extended Superclass' = " +
                        "@class_details>>getSuperclass() " +

                "print '' " +

                "/* Print out the class constructors */ " +
                "if (select @class_details>>getFirstConstructor()) is not NULL "+
                "begin " +
                "insert into #ConstructorTable(constructor) " +
                        "select constructor = convert(varchar(255), " +
                        "@class_details>>getFirstConstructor()) " +
                "while (select @class_details>>hasMoreConstructors()) = 1 " +
                "begin " +
                        "insert into #ConstructorTable (constructor) " +
                                "(select constructor = " +
                                "@class_details>>getNextConstructor()) " +
                "end " +
                "end " +

                "/* Print out the method signatures */ " +
                "if (select @class_details>>getFirstMethodSignature()) is not NULL " +
                "begin " +
                "insert into #MethodTable (method) " +
                        "select method = convert(varchar(255), " +
                        "@class_details>>getFirstMethodSignature()) " +
                "while (select @class_details>>hasMoreMethodSignatures()) = 1 "+
                "begin " +
                        "insert into #MethodTable (method) " +
                                "(select method = convert(varchar(255), " +
                                "@class_details>>getNextMethodSignature())) " +
                "end " +
                "end " +

                "/* Print out the fields */ " +
                "if (select @class_details>>getFirstField()) is not NULL " +
                "begin " +
                "insert into #FieldTable (field) " +
                        "select field = convert(varchar(255), " +
                        "@class_details>>getFirstField()) " +
                "while (select @class_details>>hasMoreFields()) = 1 " +
                "begin " +
                        "insert into #FieldTable (field) " +
                                "(select field = convert(varchar(255), " +
                                "@class_details>>getNextField())) " +
                "end " +
                "end " +
        "end"
        )

	select @maxlen = max(char_length(interface)) from #InterfaceTable
	if @maxlen is not NULL
	begin
		select @val = convert(char(10), @maxlen)
		exec('select "Implemented Interfaces" = convert(varchar('
			+ @val +'), interface) from #InterfaceTable')
		print ""
	end

	select @maxlen = max(char_length(constructor)) from #ConstructorTable
	if @maxlen is not NULL
	begin
		select @val = convert(char(10), @maxlen)
		exec('select "Constructors" = convert(varchar('+ @val +'), 
		constructor) from #ConstructorTable')
		print ""
	end

	select @maxlen = max(char_length(method)) from #MethodTable
	if @maxlen is not NULL
	begin
		select @val = convert(char(10), @maxlen)
		exec('select "Methods" = convert(varchar('+ @val +'), 
		method) from #MethodTable')
		print ""
	end

	select @maxlen = max(char_length(field)) from #FieldTable
	if @maxlen is not NULL
	begin
		select @val = convert(char(10), @maxlen)
		exec('select "Fields" = convert(varchar('+ @val +'), 
		field) from #FieldTable')
		print ""
	end

	return(0)

end
else
begin
	/* 
	**18697, "Usage: sp_helpjava ['class' [, name [, 'detail' |, 'depends']]
	**                            | 'jar' [, name [, 'depends']]]"
	*/
	raiserror 18697  
	return  (1)
end

go
exec sp_procxmode 'sp_helpjava', 'anymode'
go
grant execute on sp_helpjava to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_rebuild_text')
begin
	drop procedure sp_rebuild_text
end
go
print "Installing sp_rebuild_text"
go


/* 
** Messages for "sp_rebuild_text"	18925
**
** 17260, "Can't run %1! from within a transaction." 
** 17590, "The specified database does not exist."
** 18301, "Database name '%1!' is not the current database."
** 18925  "sp_rebuild_text failed. Check the SQL Server error log file."
*/

create procedure sp_rebuild_text
@dbname		varchar(255)	/* database name */
as

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction." 
        */
	raiserror 17260, "sp_rebuild_text"
	return(1)
end

set chained off

set transaction isolation level 1

/*
**  Make sure the database exists.
*/
if not exists ( select * from master.dbo.sysdatabases
		where name = @dbname )
begin
	/* 17590, "The specified database does not exist." */
	raiserror 17590
	return (1)
end

/*
**  Make sure that we are in the database specified
**  by @dbname.
*/
if @dbname != db_name()
begin
	/*
	** 18301, "Database name '%1!' is not the current database."
	*/
	raiserror 18301, @dbname
	return (1)
end

/*
**  Check if user has sa role, proc_role will also do auditing
**  if required. proc_role will also print error message if required.
*/
if (proc_role("sa_role") = 0)
        return(1) 

/* Uses internal sql to rebuild_text */

dbcc rebuild_text("all")

if (@@error != 0)
begin
	/*
	** 18925, "sp_rebuild_text failed. Check the SQL Server error log file."
	*/
	raiserror 18925
	return (1)
end

return(0)

go
exec sp_procxmode 'sp_rebuild_text', 'anymode'
go
grant execute on sp_rebuild_text to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_extengine')
begin
	drop procedure sp_extengine
end
go
print "Installing sp_extengine"
go

/* Sccsid = "@(#) generic/sproc/src/%M% %I% %G%" */
/*      5.0     14.2    11/12/91        sproc/src/extengine */

/*
** Messages for "sp_extengine"      
**
** 18888, "The server name specified does not exist."
** 18889, "The specified command '%1!' does not exist."
** 18892, "Unable to start the EJB Server. Check server errorlog for any additional 
** information."
** 18893, "Unable to stop the EJB Server. Check server errorlog for any additional 
** information."
** 18894, "Unable to determine the status of the EJB Server. Check server errorlog for 
** any additional information."
**
*/
create procedure sp_extengine
@servername 	varchar(30),	
@command	varchar(30)
as
declare		@srvclass	smallint
declare		@upper_command	varchar(30)
declare		@physname	varchar(32)
declare		@msg		varchar(250)

select @upper_command = upper(@command)

/*
**  if we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_extengine"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Dont do "Dirty Reads" */
set transaction isolation level 1

if (proc_role("sa_role") < 1)
begin
	return(1)
end

/* Get the class id corresponding to the server name being passed */
select @srvclass = srvclass from master.dbo.sysservers
where srvname = @servername


/*
** Make sure that the class being passed, the server being passed and the
** command being passed are valid commands
*/
select @physname = srvnetname from master.dbo.sysservers 
		where srvclass = @srvclass and srvname = @servername

if @@rowcount = 0
begin
	/* 
	** 18888, "The server name specified does not exist."
	*/
	raiserror 18888
	return (1)
end
/* EJB Resolve : Put these commands into spt_values */

if (@upper_command != "START" AND @upper_command != "STOP" AND @upper_command != "STATUS")
begin
	/*
	** 18889, "The specified command '%1!' does not exist."
	*/
	raiserror 18889, @command
	return (1)
end

/* Commands associate with the EJB Class of Server */
if (@srvclass = 10)
begin
	if (@upper_command = "START")
	begin
		/* Server entry exists, start the server */
		dbcc extengine(@physname, @srvclass, @command)
		if (@@error != 0)
		begin
			raiserror 18892
			return (1)
		end
	end
	if (@upper_command = "STOP")
	begin
		/* Server entry exists, start the server */
		dbcc extengine(@physname, @srvclass, @command)
		if (@@error != 0)
		begin
			raiserror 18893
			return (1)
		end
	end
	if (@upper_command = "STATUS")
	begin
		/* Server entry exists, start the server */
		dbcc extengine(@physname, @srvclass, @command)
		if (@@error != 0)
		begin
			raiserror 18894
			return (1)
		end
	end
end
go
exec sp_procxmode 'sp_extengine', 'anymode'
go
grant execute on sp_extengine to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_engine')
begin
	drop procedure sp_engine
end
go
print "Installing sp_engine"
go


/*
** Messages for "sp_engine"
**
** 17260, "Can't run %1! from within a transaction."
** 18899, "Invalid value supplied to parameter %1!."
** 19461, "You can take this engine offline."
*/

/*
** Syntax:
**	sp_engine "online | offline | can_offline | shutdown
**		| q_online | q_offline | q_can_offline | q_shutdown " [,<engid>]
**
**	online		- online an engine
**	offline		- offline an engine with engid being passed in.
**	can_offline	- checks to see if the engine can be offlined.
**	shutdown	- shutdown the engine
**	q_online	- online a Q engine
**	q_offline	- offline a Q engine with engid being passed in.
**	q_can_offline	- checks to see if the Q engine can be offlined.
**	q_shutdown	- shutdown the Q engine
**
**	Onlines or offlines an engine. This stored procedure can be 
**	used to online an additional engine if the number of engines 
**	currently in the server is less than 'max online engines' 
**	config parameter value. This stored procedure can also be used
**	to offline an engine, if the number of engines active is more
**	than one.
**
** Returns:
**	1 - if error.
**	0 - if no error.
*/
create procedure sp_engine
@option	varchar(30),
@engid	int = -1
as

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_engine"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1
set nocount on

/* Must have sa_role as this stored procedure is related to config */
if (proc_role("sa_role") < 1)
	return (1)

if (@option = "offline") 
begin
	/* Offline an engine */
	if (@engid = -1)
	begin
		dbcc engine(@option)
	end
	else
	begin
		dbcc engine(@option, @engid)
	end
end
else if (@option = "can_offline")
begin
	/* Can the engine be offlined? */
	if (@engid = -1)
	begin
		dbcc engine(@option)
	end
	else
	begin
		dbcc engine(@option, @engid)
	end
        if(@@error = 0)
        begin
                raiserror 19461
                return (0)
        end
        else
        begin
                return (1)
        end
end
else if (@option = "online")
begin
	/* Online an engine */
	dbcc engine(@option)
end
else if (@option = "shutdown")
begin
	/* Can the engine be shutdown? */
	if (@engid = -1)
	begin
		/* Shutdown always expects engid to be supplied */
		raiserror 18899, "engid"
		return (1)
	end
	else
	begin
		dbcc engine(@option, @engid)
	end
end
else if (@option = "q_offline") 
begin
	/* engid is required. */
	if (@engid = -1)
	begin
		raiserror 18899, "engid"
		return (1)
	end

	dbcc engine(@option, @engid)
end
else if (@option = "q_can_offline")
begin
	/* engid is required. */
	if (@engid = -1)
	begin
		raiserror 18899, "engid"
		return (1)
	end

	dbcc engine(@option, @engid)
end
else if (@option = "q_online")
begin
	dbcc engine(@option)
end
else if (@option = "q_shutdown")
begin
	/* engid is required. */
	if (@engid = -1)
	begin
		raiserror 18899, "engid"
		return (1)
	end

	dbcc engine(@option, @engid)
end
else
begin
	/* 18899, Invalid value supplied to parameter %1!. */
	raiserror 18899, "option"
	return (1)
end

if (@@error != 0)
	return (1)
else
	return (0)
go
exec sp_procxmode 'sp_engine', 'anymode'
go
grant execute on sp_engine to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_errorlog_showhelp')
begin
	drop procedure sp_errorlog_showhelp
end
go
print "Installing sp_errorlog_showhelp"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_errorlog')
begin
	drop procedure sp_errorlog
end
go
print "Installing sp_errorlog"
go


/*
** raiserror Messages for sp_errorlog
**
** 17260, "Can't run %1! from within a transaction."
** 17925, "You entered an invalid option name. No change was made."
** 17932, "You entered an invalid value. No change was made."
** 19213, "Invalid argument or unsupported command: %1!."
** 19847, "File '%1!' did not open for writing."
** 19848, "Command already in use by another user or session."
** 19850  "Internal error encountered in opening a new ASE error log. Check 
**	   current ASE error log for details." 
*/

/*
** sp_getmessage Messages for sp_errorlog
** 
** 18954, "Usage:"
** 19541, "Examples:"
** 19539, "For more information, use:"
** 19845, "Change in error log path complete. New file: '%1!'." 
** 19846, "Update the -e argument in the runserver file with the new ASE error log 
**	   path to reflect the error log change."
** 19849, "Command is used to dynamically switch to a new ASE error log at 
** 	   location <new_path>." 
** 19851, "Warning : Previous ASE error log file could not be closed." 
** 19852, "Attempting to change the Job Scheduler Agent log from its current 
**         directory to the directory where new ASE error log is residing. 
**	   Check the JS Agent log and/or the new ASE error log for details."
** 19853, "The Job Scheduler log is not running; therefore, no attempt made 
**         to change the location of JS Agent log"
** 19854, "If 'jslog true' - ASE will attempt to change JS Agent error log 
** 	   to the same directory where the new ASE error log is residing 
**	   provided that the JS Agent is running. Success or failure of 
**	   command is reported in the JS Agent log and/or the new ASE error log."
** 19855, "If 'jslog false' - ASE will not attempt to change the log location of
**	   the Job Scheduler. Note that 'jslog true' is the deault option."
** 19856, "Error encountered when moving the Job Scheduler Agent log from its
**	   current directory to the directory where the new ASE error log is
**	   residing.Check the previous JS Agent log and/or ASE error log for details."
*/

/*
** SP_ERRORLOG_SHOWHELP
**
** The sub-procedure to print help/usage information for the sp_errorlog
** procedure. Called by sp_errorlog
**
** Parameters
**	@cmd          -	This is set to either null or 'help'.
**			If @cmd is null   - General help/usage information is printed
**			If @cmd is 'help' - Specific help/usage information is printed
**		        depending on command and subcommand 
**      @command      -	Command for which help information is to be provided
**			Currently valid command is only 'change log'
**	@subcommand   - Sub-command for which help information is to be provided 
**		 	Is either 'jslog true' or 'jslog false' or null
**
** Returns 
**      0	      - success
**      1             - unsupported or invalid command
*/

create procedure sp_errorlog_showhelp
(
        @cmd            varchar(30)     =NULL,
        @command	varchar(30)     =NULL,
        @subcommand     varchar(30)     =NULL
)
as
begin    
declare @retval         int,
        @msg            varchar(256)

        if ((@command is null) and (@subcommand is null))
        begin
                /* give generic help */
                exec    sp_getmessage 18954, @msg output
                print   @msg
                print "sp_errorlog 'help','change log'"
                print ""
		
                exec    sp_getmessage 18954, @msg output
                print   @msg
                print "sp_errorlog 'change log', '<new_path>'[,{'jslog true'|'jslog false'}]"
		print ""

                return (0)
        end
        else if ((@command = 'change log') and (@subcommand in ('jslog true','jslog false',null)))
        begin
		/*
		** 19849, "Command is used to dynamically switch to a new errorlog 
		**  	   at ocation <new_path>." 
		*/
		exec    sp_getmessage 19849, @msg output
		print   @msg
                /* 
		** 19846, Update the -e argument in the Runserver file with the
		** new errorlog path to reflect the errorlog change." 
		*/
                exec    sp_getmessage 19846, @msg output
                print   @msg		
                print   ""

                exec    sp_getmessage 18954, @msg output
                print   @msg
		
		print "sp_errorlog 'change log','<new_path>' [,{'jslog true'|'jslog false'}]" 
		print ""

		/* 
		** 19854, "If 'jslog true' - ASE will attempt to change JS Agent
		** 	   error log to the same directory where the new ASE 
		**	   error log is residing provided that the JS Agent is
		**	   running. Success or failure of command is reported in 
		**	   the JS Agent log and/or the new ASE error log. 
		*/
		exec    sp_getmessage 19854, @msg output
                print   @msg

		/*
		** 19855, "If 'jslog false' - ASE will not attempt to change the   
		**	   log location of the Job Scheduler. Note that 'jslog true' 
		**	   is the default option."
		*/
		exec    sp_getmessage 19855, @msg output
                print   @msg		 
		
        end
        else
        begin
                /* 19213, "Invalid argument or unsupported command: %1!." */
                raiserror 19213, @cmd
                return 1
        end
end     
go


/*
** SP_ERRORLOG
**
** Driver interface to error logging functionality.
** For each feature the underlying driver function/built-in/sub-ordinate stored 
** procedure is called.
**
** Syntax
**      sp_errorlog ["command" [,"parameter"]]
**
** Parameters
**	@cmd         - This is the command or action to be performed.
**      @subcommand  - This is the parameter supplied for executing the comman
**	@param_value - This is the require parameter to be passed for subcommand.
**
** Returns
**	0       - success
**      other   - errors while execution
*/

create procedure sp_errorlog
(
        @cmd            varchar(30)     =NULL,
        @subcommand     varchar(1024)   =NULL,
	@param_value	varchar(30)	=NULL
)
as
begin    
declare @retval         	int,
        @msg            	varchar(256),
	@flag			int,
	@retstatus		int
	
	
/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        /*  17260, "Can't run %1! from within a transaction."  */
        raiserror 17260, "sp_errorlog"
        return (1)
end
else
begin
        set chained off
end

set transaction isolation level 1
set nocount on

/*  Begin command processing. */

select @cmd = lower(@cmd)
select @param_value = lower(@param_value)
 
If (@cmd is null or @cmd = 'help' )
begin
   	exec sp_errorlog_showhelp @cmd, @subcommand, @param_value
   	return (0)
end

if (@cmd = 'change log')
begin
        /* Must have sa_role for this command */
        if (proc_role("sa_role") < 1)
        begin
                return (1)
        end

        /* Check if subcommand or param_value entered is valid */
        if (@subcommand is null or 
	   (@param_value not in ('jslog true','jslog false', null)))
        begin
		/* 17932, "You entered an invalid value. No change was made." */
                raiserror 17932
                return (1)
        end

	select @flag = 1
	if (@param_value = 'jslog false')
	begin
		select @flag = 0
	end	
		
        select @retval = errorlog_admin(@cmd,@subcommand)
        if (@retval = 0)
        begin
		/* 19845, "Change in errorlog path complete. New file: '%1!'" */
                exec    sp_getmessage 19845, @msg output
              	print   @msg, @subcommand
		/* 
		** 19846, "Update the -e argument in the Runserver file with 
		**	   the new errorlog path to reflect the errorlog change.
		*/
		exec    sp_getmessage 19846, @msg output
                print   @msg
        end
        else if (@retval = 2)
        begin
                /* 19848,"Command already in use by another user or session." */
                raiserror 19848
        end
        else if (@retval = 4)
        begin
                /* 19847, "File '%1!' did not open for writing." */
                raiserror 19847, @subcommand
        end
	else if (@retval = 8)
	begin
                /* 19845, "Change in errorlog path complete. New file: '%1!'" */
                exec    sp_getmessage 19845, @msg output
                print   @msg, @subcommand
                /*
                ** 19846, "Update the -e argument in the Runserver file with
                **         the new errorlog path to reflect the errorlog change.
                */
                exec    sp_getmessage 19846, @msg output
                print   @msg
						 
		/* 19851, "Warning:Previous errorlog file could not be closed."*/
		exec    sp_getmessage 19851, @msg output
		print   @msg
	end
	else
	begin
                /* 
		** 19850, "Internal error encountered in opening new errorlog. 
		** 	   Check current ASE errorlog for details." 
		*/
                raiserror 19850

	end

	if ((@retval = 0 or @retval = 8) and @flag = 1 )
	begin
		/* 
		** Errorlog change was successful. Now change the Job Scheduler 
		** errorlog directory from its current directory to the 
		** directory where new errorlog resides.
		*/
		
		select  @retstatus = js_wakeup('jsagent_log', @flag)

		if (@retstatus = 1)
		begin
			/* 
			** 19852, "Attempting to change the Job Scheduler Agent 
			**	   log from its current directory to the directory 
			**	   where new ASE errorlog is residing. Check the 
			** 	   JS Agent log and/or ASE errorlog for details." 
			*/ 
			exec    sp_getmessage 19852,@msg output
			print 	@msg
		end
		else
		begin
			select  @retstatus = js_wakeup('start_js', 0)
			if (@retstatus = 1 and @param_value = 'jslog true') 
			begin
				/* 
				** 19853, "The Job Scheduler is not running; 
				**	   therefore, no attempt amde to change
				**	   location of JS Agent log.
				*/
				raiserror 19853
			end
			else
			begin
				 if (@retstatus = 0) /* Indicates JS is running */
				 begin
				 	/* print error when moving to JS agent log */
					/*
					** 19856, "Error encountered when moving the
					**	   Job Scheduler Agent log from its
					** 	   current directory to the directory
					**	   where new errorlog is residing.
					**	   Check the previous JS Agent log and/or
					**	   ASE errorlog for details."
					*/
					raiserror 19856
				 end
			end
		end
	end
	return (@retval)
end
else
begin

        /* 19213, "Invalid argument or unsupported command: %1!." */
        raiserror 19213, @cmd
        return (1)
end
end 	
go
go
exec sp_procxmode 'sp_errorlog_showhelp', 'anymode'
go
grant execute on sp_errorlog_showhelp to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_errorlog', 'anymode'
go
grant execute on sp_errorlog to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_creategroup')
begin
	drop procedure sp_multdb_creategroup
end
go
print "Installing sp_multdb_creategroup"
go


/*
** Messages for "sp_multdb_creategroup"
** 
** 17260, "Can't run %1! from within a transaction."
** 17240, "'%1!' is not a valid name."
** 18610, "%1!: Insert row to master.dbo.sysattributes failed. Command aborted."
** 18941, "Currently only 'default' group is supported."
** 18967, "Group '%1!' already exists."
** 18942, "Internal Error: failed to create group."
*/

/*
** Procedure sp_multdb_creategroup
**
** This procedure adds a new group in SYSATTRIBUTES
** for the MULTEMPDB_CLASS (class 16)
**      
*/
create procedure sp_multdb_creategroup
	@tdbgroup varchar(255)		/* temp db group */
as

declare @class_id       smallint,       /* class in SYSATTRIBUTES */
        @attrib_id      smallint,       /* attribute in SYSATTRIBUTES */
        @object_type    char(2),        /* object type in SYSATTRIBUTES */
        @object_cinfo   varchar(255),    /* object_cinfo in SYSATTRIBUTES */
        @int_val        int,            /* int_value in SYSATTRIBUTES */
        @group_id       int,            /* group id database being added to */
        @action         int,            /* action for built in */
        @upcase_str     varchar(30),
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@action_code	int,		/* Indication action code for the op. */
	@MULTDB_ACTION_DO	int,	/* Action code that operation
					** completed successfully
					*/
	@MULTDB_ACTION_UNDO	int	/* Action code to indicate that 
					** operation did not complete
					*/

select @SMP = 0, 
	@SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP
end
else
begin
	select @svrmode = @SDC

	/* 
	** These values must be kept in sync with their definitions in
	** multempdb.h.
	*/

	select @MULTDB_ACTION_DO = 2
	select @MULTDB_ACTION_UNDO = 3
end

/*
**  if we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_multdb_creategroup"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Dont do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 0		/* attribute is MULTEMPDB_GROUP */
select @object_type = 'GR'	/* Object type if 'GR' for temp. db group */
select @action	= 1		/* add new group */

/*
** Make sure group name is valid.
*/
if (@tdbgroup != "default")
begin
	if valid_name(@tdbgroup) = 0
	begin
		raiserror 17240, @tdbgroup
		return (1)
	end
end

/*
** Check if group already exists. It shouldn't.
*/
if exists (select * from master..sysattributes 
             where class = @class_id 
               AND attribute = @attrib_id 
	       AND object_type = @object_type 
	       AND object_cinfo = @tdbgroup)
begin
	raiserror 18967, @tdbgroup
	return (1)
end

/*
** The "default" group id is fixed at 0.
** For a different group, find the next available id to use.
*/
if (@tdbgroup = "default")
begin
	select @group_id = 0
end
else
begin
	select @group_id = (select MAX(int_value)
			    from master..sysattributes 
                              where class = @class_id 
				AND attribute = @attrib_id 
				AND object_type = @object_type)

	select @group_id = @group_id + 1
end

/*
** Insert the group entry into the sysattributes.
*/
begin tran crt_tdbgrp

/*
** Send the notification to indicate the beginning of the transaction
** to allow cluster synchronization mechanism to be deployed.
*/
if (@svrmode = @SDC)
begin
	select @action = 5 	/* ATTR_BEGIN */
	if (attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
		NULL, "", @action)) = 0
	begin
		raiserror 18942
		goto error_exit
	end
end

insert into master..sysattributes 
  (class, attribute, object_type, object_cinfo, int_value)
  values
  (@class_id, @attrib_id, @object_type, @tdbgroup, @group_id)

if (@@error != 0)
begin
	raiserror 18610, "sp_multdb_creategroup"
	goto error_exit
end

/*
** Notify the addition of the new group.
*/
select @action = 1	/* ATTR_ADD */
if (attrib_notify (@class_id, @attrib_id, @object_type, NULL, NULL, NULL,
		NULL, @tdbgroup, @group_id, NULL, NULL, NULL, "", 
		@action)) = 0
begin
	raiserror 18942
	goto error_exit
end

commit tran
/*
** Send notification to communicate that transaction is committed and
** in-memory changes be made final.
*/
if (@svrmode = @SDC)
begin
	select @action = 6 	/* ATTR_END */
	select @action_code = @MULTDB_ACTION_DO	
	select attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, @action_code, NULL, NULL, 
		NULL, "", @action)
end
return (0)

error_exit:
	/*
	** In SDC, the in-memory changes are undone as part of the 
	** abort transaction processing. So, there is no need to send
	** end notification with @MULTDB_ACTION_UNDO action.
	*/
	rollback tran crt_tdbgrp
	return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_dropgroup')
begin
	drop procedure sp_multdb_dropgroup
end
go
print "Installing sp_multdb_dropgroup"
go


/*
** Messages for "sp_multdb_dropgroup"
**
** 17260, "Can't run %1! from within a transaction."
** 17240, "'%1!' is not a valid name."
** 18943, "Can not drop '%1!' group."
** 18944, "Internal Error: failed to drop group."
** 18947, "Group '%1!' does not exist."
** 18608, "%1!: Delete row from master.dbo.sysattributes failed. 
**	   Command aborted."
*/


/*
** Procedure sp_multdb_dropgroup
**
** This procedure drops a group from SYSATTRIBUTES
** for the MULTEMPDB_CLASS (class 16)
**      
*/
create procedure sp_multdb_dropgroup
	@tdbgroup varchar(255)		/* temp db group */
as

declare @class_id       smallint,       /* class in SYSATTRIBUTES */
        @attrib_id      smallint,       /* attribute in SYSATTRIBUTES */
        @object_type    char(2),        /* object type in SYSATTRIBUTES */
        @object_cinfo   varchar(255),    /* object_cinfo in SYSATTRIBUTES */
        @int_val        int,            /* int_value in SYSATTRIBUTES */
        @group_id       int,            /* group id database being added to */
        @action         int,            /* action for built in */
        @upcase_str     varchar(30),
	@errnum		int,		/* error during sysattribute update*/
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@action_code	int,		/* Indication action code for the op. */
	@MULTDB_ACTION_DO	int,	/* Action code that operation
					** completed successfully
					*/
	@MULTDB_ACTION_UNDO	int	/* Action code to indicate that 
					** operation did not complete
					*/

select @SMP = 0, 
	@SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP
end
else
begin
	select @svrmode = @SDC

	/* 
	** These values must be kept in sync with their definitions in
	** multempdb.h.
	*/
	select @MULTDB_ACTION_DO = 2
	select @MULTDB_ACTION_UNDO = 3
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	 raiserror 17260, "sp_multdb_dropgroup"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Dont do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */

/*
** We don't allow dropping the default group.
*/
if (@tdbgroup = "default")
begin
	raiserror 18943, @tdbgroup
	return (1)
end

/*
** Make sure group name is valid.
*/
if (@tdbgroup != "default")
begin
	if valid_name(@tdbgroup) = 0
	begin
		raiserror 17240, @tdbgroup
		return (1)
	end
end

/*
** Check if group exists.
*/
select @attrib_id = 0		/* attribute is MULTEMPDB_GROUP */
select @object_type = 'GR'	/* Object type if 'GR' for temp. db group */

select @group_id = (select int_value from master..sysattributes 
		      where class = @class_id 
			AND attribute = @attrib_id 
			AND object_type = @object_type 
			AND object_cinfo = @tdbgroup)

/*
** Group does not exist. Report error.
*/
if @group_id is NULL
begin
	raiserror 18947, @tdbgroup
	return (1)
end

select @attrib_id = 1 		/* attribute is MULTEMPDB_BIND */

select @errnum = 0

begin tran drop_tdbgrp

/*
** Send the notification to indicate the beginning of the transaction
** to allow cluster synchronization mechanism to be deployed.
*/
if (@svrmode = @SDC)
begin
	select @action = 5 	/* ATTR_BEGIN */
	select @attrib_id = 0	/* attribute is MULTEMPDB_GROUP */
	if (attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
		NULL, "", @action)) = 0
	begin
		raiserror 18944
		goto error_exit
	end
end

/*
** Drop all bindings of type 'AP' and 'LG' (application
** and login bindings) where the binding is to the group being dropped
**
** The int_value of 1 indicates that the name stored in char_value is a
** group name.
*/
select @attrib_id = 1 		/* attribute is MULTEMPDB_BIND */

delete from master..sysattributes 
  where class = @class_id 
    AND attribute = @attrib_id 
    AND (object_type = 'LG' OR object_type = 'AP') 
    AND char_value = @tdbgroup 
    AND int_value = 1

select @errnum = @@error
if (@errnum != 0)
 	goto error_exit

/*
** Drop all entres from the sysattributes where
** databases are bound to the group that is being dropped.
*/
select @object_type = 'D '	/* Object type if 'GR' for temp. db group */

delete from master..sysattributes
  where class = @class_id 
    AND attribute = @attrib_id 
    AND object_type = @object_type 
    AND object = @group_id

select @errnum = @@error
if (@errnum != 0)
	goto error_exit

/*
** Drop the group entry
*/
select @attrib_id = 0           /* attribute is MULTEMPDB_GROUP */
select @object_type = 'GR'      /* Object type if 'GR' for temp. db group */

delete from master..sysattributes 
  where class = @class_id 
    AND attribute = @attrib_id 
    AND object_type = @object_type 
    AND object_cinfo = @tdbgroup

select @errnum = @@error
if (@errnum != 0)
	goto error_exit

/*
** Notify the deletion of the new group.
** If this return failure, then it's an internal error.
** There is no reason to undo the work we have just done.
*/
select @action = 3		/* ATTR_DROP - Drop a group */
if (attrib_notify (@class_id, @attrib_id, @object_type, NULL, NULL, NULL,
		NULL, @tdbgroup, @group_id, NULL, NULL, NULL, "", 
		@action)) = 0
begin
	raiserror 18944
	goto error_exit
end

commit tran drop_tdbgrp
/*
** Send notification to communicate that transaction is committed and
** in-memory changes be made final.
*/
if (@svrmode = @SDC)
begin
	select @action = 6 	/* ATTR_END */
	select @action_code = @MULTDB_ACTION_DO	
	select attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, @action_code, NULL, NULL, 
		NULL, "", @action)
end
return (0)

error_exit:
	if @errnum != 0
		raiserror 18608, 'sp_multdb_dropgroup'
	/*
	** In SDC, the in-memory changes are undone as part of the 
	** abort transaction processing. So, there is no need to send
	** end notification with @MULTDB_ACTION_UNDO action.
	*/
	rollback tran drop_tdbgrp
	return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_addtogroup')
begin
	drop procedure sp_multdb_addtogroup
end
go
print "Installing sp_multdb_addtogroup"
go

/*
** Messages for "sp_multdb_addtogroup"
**
** 17260, "Can't run %1! from within a transaction."
** 17240, "'%1!' is not a valid name."
** 18610, "%1!: Insert row to master.dbo.sysattributes failed. Command aborted."
** 18945, "'tempdb' is implicitly a member of 'default' group and
**        can not be part of another group."
** 18946, "Either the database '%1!' does not exist or is not a 
**         user created temporary database."
** 18947, "Group '%1!' does not exist."
** 18948, "Database '%1!' is already a group member."
** 18949, "Internal Error: failed to add database to group."
** 19580, "Either the database '%1!' does not exist or is not a
**	   local user temporary database."
*/


/*
** Procedure sp_multdb_addtogroup
**
** This procedure adds a temporary database to a temporary database group
**	
*/
create procedure sp_multdb_addtogroup
@tdb	  varchar(255),		/* temporary database to be bound */
@tdbgroup varchar(255)		/* temp db group */
as

declare @class_id	smallint,	/* class in SYSATTRIBUTES */
	@attrib_id	smallint,	/* attribute in SYSATTRIBUTES */
	@object_type 	char(2),	/* object type in SYSATTRIBUTES */
	@object_cinfo	varchar(255),	/* object_cinfo in SYSATTRIBUTES */
	@int_val	int,		/* int_value in SYSATTRIBUTES */
	@group_id	int,		/* group id database being added to */
	@action		int,		/* action for build in */
	@upcase_str	varchar(30),
	@bindabletdb_stat	int,	/* dbstatus for database can be added
					** to a tdb group */
	@instanceid	int,
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@action_code	int,		/* Indicates action code for the op. */
	@MULTDB_ACTION_DO	int,	/* Action code that operation
					** completed successfully
					*/
	@MULTDB_ACTION_UNDO	int	/* Action code to indicate that 
					** operation did not complete
					*/

select @SMP = 0, 
	@SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP
end
else
begin
	select @svrmode = @SDC

	/* 
	** These values must be kept in sync with their definitions in
	** multempdb.h.
	*/
	select @MULTDB_ACTION_DO = 2
	select @MULTDB_ACTION_UNDO = 3
end

/*
**  if we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_multdb_addtogroup"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Dont do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */
select @object_type = 'D '	/* Object type if 'D ' for temp. db */
select @action	= 1		/* New Binding */

/*
** The system "tempdb" can not be added to a group. It is implicitly
** part of the default group.
** For a tempdb to be bound to a group:
** In SMP, the tempdb has to be a user create tempdb
** In SDC, the tempdb has to be a local user tempdb
*/
if (@svrmode = @SMP)
begin
	if @tdb = "tempdb"
	begin
		raiserror 18945
		return (1)
	end
	select @bindabletdb_stat = number
		from master.dbo.spt_values
		where   type = "D3" and name = "user created temp db"
end
else /* @SDC */
	select @bindabletdb_stat = number
		from master.dbo.spt_values
		where   type = "D3" and name = "local user temp db"

/*
**
** Check to see that the database being added is indeed
** right type of temporary database. We do not allow the
** addition of a non temporary database to a group.
*/
if not exists (select * 
	       from master..sysdatabases 
	       where name = @tdb 
	         AND (status3 & @bindabletdb_stat) = @bindabletdb_stat)
begin
	if @@clustermode != "shared disk cluster" 
		raiserror 18946, @tdb
	else
		raiserror 19580, @tdb 
	return (1)
end



/*
** Make sure group name is valid.
*/
if (@tdbgroup != "default")
begin
	if valid_name(@tdbgroup) = 0
	begin
		raiserror 17240, @tdbgroup
		return (1)
	end
end

/*
** Check if group exists and get group id
*/
select @attrib_id = 0           /* attribute is MULTEMPDB_GROUP */
select @object_type = 'GR'      /* Object type if 'GR' for temp. db group */

select @group_id = (select int_value from master..sysattributes 
		      where class = @class_id 
			AND attribute = @attrib_id 
			AND object_type = @object_type 
			AND object_cinfo = @tdbgroup)

/*
** Group must exist in order for us to add a database to it.
*/
if @group_id is NULL
begin
	raiserror 18947, @tdbgroup
	return (1)
end

select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */
select @object_type = 'D '	/* Object type if 'D ' for temp db */

/*
** If this entry doesn't already exist in sysattributes then
** add the new member into sysattributes.
** Note in SDC, object_info2 will hold the instance id of the tempdb;
** while in SMP, this field is filled with null.
*/
begin tran bind_tdbtogroup



if not exists (select * from master..sysattributes
		 where class = @class_id 
		   AND attribute = @attrib_id 
		   AND object_type = @object_type 
		   AND object_cinfo = @tdb 
		   AND object = @group_id)
begin
	insert into master..sysattributes

	(class, attribute, object_type, object_cinfo, object)
                values
                (@class_id, @attrib_id, @object_type, @tdb, @group_id)

	if (@@error != 0)
	begin
		raiserror 18610, "sp_multdb_addtogroup"
		goto error_exit
	end
end
else
begin
	raiserror 18948, @tdb
	goto error_exit
end

/*
** Notify the addition of the new database to the group.
** If this returns failure, then delete the just inserted entry.
*/
select @action = 1	/* ATTR_ADD */

if (attrib_notify(@class_id, @attrib_id, @object_type, @group_id, NULL, NULL,
                NULL, @tdb, NULL, NULL, NULL, NULL, "",
                @action)) = 0
	
begin
	raiserror 18949
	goto error_exit
end

commit tran bind_tdbtogroup
/*
** Send notification to communicate that transaction is committed and
** in-memory changes be made final.
*/
if (@svrmode = @SDC)
begin
	select @action = 6 	/* ATTR_END */
	select @action_code = @MULTDB_ACTION_DO	
	select attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, @action_code, NULL, NULL, 
		NULL, "", @action)
end
return (0)

error_exit:
	/*
	** In SDC, the in-memory changes are undone as part of the 
	** abort transaction processing. So, there is no need to send
	** end notification with @MULTDB_ACTION_UNDO action.
	*/
	rollback tran bind_tdbtogroup
	return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_removefromgroup')
begin
	drop procedure sp_multdb_removefromgroup
end
go
print "Installing sp_multdb_removefromgroup"
go


/*
** Messages for "sp_multdb_removefromgroup"
** 
** 17260, "Can't run %1! from within a transaction."
** 17240, "'%1!' is not a valid name."
** 18946, "Either the database '%1!' does not exist or is not a user 
**         created temporary database."
** 18947, "Group '%1!' does not exist."
** 18950, "Internal Error: failed to remove database from group."
** 18975, "Database '%1!' is not a member of the '%2!' group."
** 18608, "%1!: Delete row from master.dbo.sysattributes failed. 
**	   Command aborted."
** 19580, "Either the database '%1!' does not exist or is not a
**	   local user temporary database."
*/


/*
** Procedure sp_multdb_removefromgroup
**
** This procedure removes a database from a group in SYSATTRIBUTES
** for the MULTEMPDB_CLASS (class 16)
**      
*/
create procedure sp_multdb_removefromgroup
	@tdb	  varchar(255),		/* temporary database to be bound */
	@tdbgroup varchar(255)		/* temp db group */
as

declare @class_id       smallint,       /* class in SYSATTRIBUTES */
        @attrib_id      smallint,       /* attribute in SYSATTRIBUTES */
        @object_type    char(2),        /* object type in SYSATTRIBUTES */
        @object_cinfo   varchar(255),    /* object_cinfo in SYSATTRIBUTES */
        @int_val        int,            /* int_value in SYSATTRIBUTES */
        @group_id       int,            /* group id database being added to */
        @action         int,            /* action for built in */
        @upcase_str     varchar(30),
	@instanceid	int,	
	@bindabletdb_stat	int,	/* dbstatus for database can be added
					**  to a tdb group */
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@action_code	int,		/* Indicates action code for the op. */
	@MULTDB_ACTION_DO	int,	/* Action code that operation
					** completed successfully
					*/
	@MULTDB_ACTION_UNDO	int	/* Action code to indicate that 
					** operation did not complete
					*/

select @SMP = 0, 
	@SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP
end
else
begin
	select @svrmode = @SDC

	/* 
	** These values must be kept in sync with their definitions in
	** multempdb.h.
	*/
	select @MULTDB_ACTION_DO = 2
	select @MULTDB_ACTION_UNDO = 3
end

/*
**  if we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_multdb_removefromgroup"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Dont do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */
select @object_type = 'D '	/* Object type if 'D ' for temp. db */
select @action	= 3		/* Drop Binding */

/*
** Make sure group name is valid.
*/
if (@tdbgroup != "default")
begin
	if valid_name(@tdbgroup) = 0
	begin
		raiserror 17240, @tdbgroup
		return (1)
	end
end

/*
** tempdb is a special case since its binding to the default group
** is implicit and is not stored in sysattributes. So we cannot rely
** on the lookup in sysattributes as we do for other databases to determine
** if such a binding exists or not. 
** In addition, we want to catch the type of database that can not be
** specificly bind to a group and give proper msg here. Even though tempdb
** in SMP is implicitly part of the default group, it can not be specificly
** bind or unbind from any group.
*/
if (@svrmode = @SMP)
	select @bindabletdb_stat = number
		from master.dbo.spt_values
		where   type = "D3" and name = "user created temp db"
else
	select @bindabletdb_stat = number
		from master.dbo.spt_values
		where   type = "D3" and name = "local user temp db"

if not exists (select *
		from master..sysdatabases
		where name = @tdb
		AND (status3 & @bindabletdb_stat) = @bindabletdb_stat)
begin
	if (@svrmode = @SMP)
		raiserror 18946, @tdb
	else
		raiserror 19580, @tdb
	return (1)
end


/*
** Check if group exists and get group id
*/
select @attrib_id = 0           /* attribute is MULTEMPDB_GROUP */
select @object_type = 'GR'      /* Object type if 'GR' for temp. db group */

select @group_id = (select int_value from master..sysattributes 
		      where class = @class_id 
			AND attribute = @attrib_id 
			AND object_type = @object_type 
			AND object_cinfo = @tdbgroup)

/*
** Group not found
*/
if @group_id is NULL
begin
	raiserror 18947, @tdbgroup
	return (1)
end

select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */
select @object_type = 'D '	/* Object type if 'D ' for temp db */

begin tran unbind_tdbtogrp

/*
** Send the notification to indicate the beginning of the transaction
** to allow cluster synchronization mechanisms to be deployed.
*/
if (@svrmode = @SDC)
begin
	select @action = 5 	/* ATTR_BEGIN */
	if (attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
		NULL, "", @action)) = 0
	begin
		raiserror 18950
		goto error_exit
	end
end

/*
** Delete the binding from sysattributes.
*/
if exists (select * from master..sysattributes 
	     where class = @class_id 
	     AND attribute = @attrib_id 
	     AND object_type = @object_type 
	     AND object_cinfo = @tdb 
	     AND object = @group_id)
begin
	delete from master..sysattributes 
	  where class = @class_id 
	    AND attribute = @attrib_id 
	    AND object_type = @object_type 
	    AND object_cinfo = @tdb 
	    AND object = @group_id

	if @@error != 0
	begin
		raiserror 18608, 'sp_multdb_removefromgroup'
		goto error_exit
	end
end
else
begin
	raiserror 18975, @tdb, @tdbgroup
	goto error_exit
end

/*
** Notify the unbinding of the database 
** If this returns failure, then abort the transaction.
**
** Note in SDC, object_info2 will hold the instance id of the tempdb;
** while in SMP, this field is filled with null.
*/
select @action = 3		/* ATTR_DROP */

if (attrib_notify (@class_id, @attrib_id, @object_type, @group_id, NULL, NULL,
                NULL, @tdb, NULL, NULL, NULL, NULL, "",
                @action)) = 0	
	
begin
	raiserror 18950
	goto error_exit
end

commit tran unbind_tdbgrp
/*
** Send notification to communicate that transaction is committed and
** in-memory changes be made final.
*/
if (@svrmode = @SDC)
begin
	select @action = 6 	/* ATTR_END */
	select @action_code = @MULTDB_ACTION_DO	
	select attrib_notify(@class_id, @attrib_id, @object_type, 
		NULL, NULL, NULL, NULL, NULL, @action_code, NULL, NULL, 
		NULL, "", @action)
end
return (0)

error_exit:
	/*
	** In SDC, the in-memory changes are undone as part of the 
	** abort transaction processing. So, there is no need to send
	** end notification with @MULTDB_ACTION_UNDO action.
	*/
	rollback tran unbind_tdbtogrp
	return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_bind')
begin
	drop procedure sp_multdb_bind
end
go
print "Installing sp_multdb_bind"
go


/*
** Messages for "sp_multdb_bind"
**
** 17260, "Can't run %1! from within a transaction."
** 18252, "%1!' value '%2!' is not valid."
** 18255, "%1! cannot be NULL."
** 18276, "%1! is not a valid object type."
** 18314, "Login '%1!' does not exist in syslogins table."
** 18609, "%1!: Update row of master.dbo.sysattributes failed. Command aborted."
** 18610, "%1!: Insert row to master.dbo.sysattributes failed. Command aborted."
** 18946, "Either the database '%1!' does not exist or is not a user 
**         created temporary database."
** 18947, "Group '%1!' does not exist."
** 18951, "'%1!' is not currently supported."
** 18953, "Internal Error: failed to add binding."
** 18976, "The '%1!' login can not have a hard binding."
** 19580, "Either the database '%1!' does not exist or is not a local 
**	   user temporary database." 
** 19581, "The %1! '%2!' is already bound to a group. To bind it to a 
**	   database, first remove existing group binding to it."
** 19582, "The %1! '%2!' already has one or more database bindings. To 
**	   bind it to a group, first remove existing database bindings to it."
** 19594, "Unable to determine owner instance of the database '%1!'. An 
**	   internal inconsistency is encountered in row for the database '%1!' 
**	   in master..sysdatabases. Please contact Sybase Technical Support."
*/

/*
** Procedure sp_multdb_bind
**
** This procedure adds a new multiple tempdb related binding 
** in SYSATTRIBUTES
**      
** SMP
**      Triplet <objtype, objname, scope> could be either bound to a
**      temporary database group or to a temporary database i.e. there
**      could be only one binding entry for the given triplet.
**
** SDC
**      Triplet <objtype, objname, scope> could be either bound to a
**      temporary database group or to local temporary databases. If the
**      binding is to a temporary database group, then there could be
**      only one binding entry. However, if binding is to local temporary
**      databases then there could be multiple binding entries, one for
**      each cluster instance.
*/
create procedure sp_multdb_bind
	@obj_name	varchar(255),	/* object to be bound  */
	@obj_type	varchar(30),	/* Type of object 'AP' or 'LG' */
	@scope		varchar(255),	/* Application name or login name */
	@tdb_type	varchar(30),	/* 'DB' for db or "GR" for group */
	@tdb	  	varchar(255),	/* temporary db/group to be bound to*/
	@hardness	varchar(30)	/* hard of soft binding */
as

declare @class_id	smallint, 	/* class in SYSATTRIBUTES */
	@attrib_id	smallint,	/* attribute in SYSATTRIBUTES */
	@object_cinfo	varchar(255),	/* object_cinfo in SYSATTRIBUTES */
	@new_bind_type	int,		/* New binding type. Corresponds to 
					** int_value in SYSATTRIBUTES 
					*/
	@existing_bind_type	int,	/* Existing binding type. Corresponds
					** to int_value in SYSATTRIBUTES
					*/	
	@group_id	int,		/* group id */
	@action		int,		/* action for built in */
	@upcase_str	varchar(30),
	@app_name	varchar(255),	/* application name */
	@user_id	int,		/* user id of login */
	@hardorsoft	int,		/* hard or soft */
	@instanceid	int,		/* (SDC only) instance id of the owner 
					** of local user tempdb. 
					*/
	@obj_type_str	varchar(30),	/* To hold object type "login" or
					** "application" string constants 
					** for message printing.
					*/
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@notify_status	int,		/* return value from attrib_notify() */
	@MULTDB_HARDBINDING	int,	/* hard binding */
	@MULTDB_SOFTBINDING	int,	/* soft binding */
	@MULTDB_BINDGRP	int,		/* binding is to a group */
	@MULTDB_BINDDB	int,		/* binding is to a temporary database */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@DBT3_USER_TEMPDB	int,	/* (SMP only) Bit value corresponding 
					** to DBT3_USER_TEMPDB 
					*/
	@DBT3_LOCAL_USER_TEMPDB	int,	/* (SDC only) Bit value corresponding to
					** DBT3_LOCAL_USER_TEMPDB 
					*/
	@ATTR_ADD	int,		/* indicates a new binding */
	@ATTR_CHANGE	int		/* indicates a binding update */

select @SMP = 0, 
	@SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP

	select @DBT3_USER_TEMPDB = number
		from master.dbo.spt_values
		where type = "D3" and name = "user created temp db"

	/* instanceid is not relevant in SMP, set it to NULL */
	select @instanceid = NULL
end


/*
**  if we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_multdb_bind"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Don't do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */

/* 
** Following constants must be consistent with their definition in
** multempdb.c 
*/
select @MULTDB_HARDBINDING = 1,
	@MULTDB_SOFTBINDING = 0,
	@MULTDB_BINDGRP = 1,
	@MULTDB_BINDDB = 0

/* keep in sync with sysattr.h */
select @ATTR_ADD = 1,
	@ATTR_CHANGE = 2

/* 
** Make sure that object type is valid
** Can only be 'AP' or 'LG' or 'APPLICATION_NAME' or 'LOGIN_NAME'
*/
select @upcase_str = upper(@obj_type)
if (@upcase_str = "LG") OR (@upcase_str = "AP")
	OR (@upcase_str = "APPLICATION_NAME") OR (@upcase_str = "LOGIN_NAME")
begin
	if (@upcase_str = "APPLICATION_NAME") OR (@upcase_str = "AP")
	begin
		select @obj_type = "AP"
		select @obj_type_str = "application"
	end
	else
	begin
		select @obj_type = "LG"
		select @obj_type_str = "login"
	end
end
else
begin
	/*
	** 18276, "%1! is not a valid object type."
	*/
	raiserror 18276, @obj_type
	return (1)
end

/*
** Make sure that tdb type is valid
** Can only be 'GR' (binding to a group) or 'GROUP'
** 'DB' (binding to specific database) or 'DATABASE'
*/
select @upcase_str = upper(@tdb_type)
if (@upcase_str = "DB") OR (@upcase_str = "GR")
	OR (@upcase_str = "DATABASE") OR (@upcase_str = "GROUP")
begin
	if (@upcase_str = "DATABASE") OR (@upcase_str = "DB")
	begin
		select @tdb_type = "DB"
	end
	else
	begin
		select @tdb_type = "GR"
	end
end
else
begin
	/*
	** 18252, "%1!' value '%2!' is not valid."
	*/
	raiserror 18252, "Bindtype", @tdb_type
	return (1)
end

/*
** Object name can't be null
*/
if (@obj_name is NULL)
begin
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "Object name"
	return (1)
end

/*
** Check to see that the hardness is valid.
** Either "hard" or "soft" or null (in which case
** we use the default of "soft"
*/
select @upcase_str = upper(@hardness)
if (@upcase_str = "HARD")
begin
	select @hardorsoft = @MULTDB_HARDBINDING 
end
else if (@upcase_str = "SOFT") OR (@upcase_str is NULL)
begin
	select @hardorsoft = @MULTDB_SOFTBINDING 
end
else
begin
	/*
	** 18252, "%1!' value '%2!' is not valid."
	*/
	raiserror 18252, "Hardness", @hardness
	return (1)
end


/*
** Temp db or group name can't be null
*/
if (@tdb is NULL)
begin
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "bindobj"
	return (1)
end

select @action	= @ATTR_ADD	/* new binding */
select @user_id = NULL          /* id of user from syslogins */
select @app_name = NULL		/* application name */

/*
** We don't currently support a non null scope.
*/
if (@scope is not NULL)
begin
	/*
	** 18951, "'%1!' is not currently supported."
	*/
	raiserror 18951, "Scope"
	return (1)
end

/*
** If binding to temporary database then 
** check to see that the database being bound to
** is indeed a temporary database. We do not allow the
** binding to a non temporary database.
**
** For SDC, check to see if the database being bound is a local user 
** temporary database. Bindings to non temporary databases, global 
** temporary databases and local system temporary databases are not allowed.
*/
if (@tdb_type = "DB")
begin

		if not exists (select * from master..sysdatabases 
			   where name = @tdb 
			     AND ((status3 & @DBT3_USER_TEMPDB) = 
							@DBT3_USER_TEMPDB))
		begin
			/*
			** 18946, "Either the database '%1!' does not exist 
			**	   or is not a user created temporary database."
			*/
			raiserror 18946, @tdb
			return (1)
		end

	/* 
	** Specified (local) temporary database exists. Indicate that
	** binding is to a temporary database.
	*/
	select @new_bind_type = @MULTDB_BINDDB 

end
else 
/*
** Binding is to a group. 
** Check to see if the group name exists.
*/
begin
	select @attrib_id = 0       /* attribute is MULTEMPDB_GROUP */
	if not exists (select * from master..sysattributes 
			 where class = @class_id 
			   AND attribute = @attrib_id 
			   AND object_type = 'GR' 
			   AND object_cinfo = @tdb)
	begin
		/*
		** 18947, "Group '%1!' does not exist."
		*/
		raiserror 18947, @tdb
		return (1)
	end
	else
	begin
		select @new_bind_type = @MULTDB_BINDGRP  /* indicates group */

 	end
end
	
/* 
** convert user name to user id after checking its existence 
*/
if (@obj_type = "LG")
begin
	/* 'sa' cannot have a hard binding */
	if ((@hardorsoft = @MULTDB_HARDBINDING) and (@obj_name = "sa"))
	begin
		/*
		** 18976, "The '%1!' login can not have a hard binding."
		*/
		raiserror 18976, @obj_name
		return (1)
	end

        if not exists (select suid from master..syslogins 
                         where (name = @obj_name))
        begin
		/*
		** 18314, "Login '%1!' does not exist in syslogins table."
		*/
		raiserror 18314, @obj_name
                return(1)
        end

        select @user_id = (select suid from master..syslogins 
                             where (name = @obj_name))

	if (@scope is not NULL)
	begin
		select @app_name = @scope
	end
end

/*
** For "AP" type bindings, obj_name is an application name.
*/
else if (@obj_type = "AP")
begin
	select @app_name = @obj_name

	/*
	** if obj_type is "AP", then a non null scope
	** would have the login name. If user name is specified
	** then convert user name to user id after checking its existence
	*/
	if (@scope is not NULL)
	begin
		if not exists (select suid from master..syslogins 
			 where (name = @scope))
        	begin
			/*
			** 18314, "Login '%1!' does not exist in syslogins 
			**	   table."
			*/
			raiserror 18314, @scope
                	return(1)
        	end

        	select @user_id = (select suid from master..syslogins 
                             where (name = @scope))
	end
end

/* Attribute if for binding */
select @attrib_id = 1

begin transaction tempdb_bind

/*
** If binding already exists then update it,
** else insert the new binding
*/
if exists (select * from master..sysattributes 
	     where class = @class_id 
	       AND attribute = @attrib_id 
	       AND object_type = @obj_type 
	       AND object_cinfo = @app_name 
	       AND object = @user_id)
begin


		select @action = @ATTR_CHANGE

		/* Update the existing binding */
		update master..sysattributes
			set char_value = @tdb, int_value = @new_bind_type,
			object_info1 = @hardorsoft
			where class = @class_id 
				AND attribute = @attrib_id 
				AND object_type = @obj_type 
				AND object_cinfo = @app_name 
				AND object = @user_id

		if (@@error != 0)
		begin
			/*
			** 18609, "%1!: Update row of master.dbo.sysattributes 
			**	   failed. Command aborted."
			*/
			raiserror 18609, "sp_multdb_bind"
			goto error_exit
		end

end
else
begin

		select @action = @ATTR_ADD
		
		/* Insert the new binding */
		insert into master..sysattributes
			(class, attribute, object_type, object_cinfo, object,
			 object_info1, int_value, char_value)
		values
			(@class_id, @attrib_id, @obj_type, @app_name, @user_id,
			 @hardorsoft, @new_bind_type, @tdb)

		if (@@error != 0)
		begin
			/*
			** 18610, "%1!: Insert row to master.dbo.sysattributes 
			**	   failed. Command aborted."
			*/
			raiserror 18610, "sp_multdb_bind"
			goto error_exit
		end

end

/*
** Notify the server about the new/updated binding.
** Note that for SMP, @instanceid is always NULL and should be ignored
** by the notification handler routine.
**
** Currently, no action is taken upon notification of a new binding.
** Uncomment the following notification when some action needs to be
** implemented.
*/
--select @notify_status =  
--	attrib_notify (@class_id, @attrib_id, @obj_type, @user_id,
--		@hardorsoft, @instanceid, NULL, @app_name, 
--		@new_bind_type, @tdb, NULL, NULL, "", @action)
--
--if (@notify_status = 0)
--begin
--	/*
--	** Server responded with failure, rollback the transaction.
--	**
--	** 18953, "Internal Error: failed to add binding."
--	*/
--      raiserror 18953
--	goto error_exit
--end

/* Commit the transaction */
commit transaction tempdb_bind
return (0)

error_exit:
	rollback transaction tempdb_bind
	return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_unbind')
begin
	drop procedure sp_multdb_unbind
end
go
print "Installing sp_multdb_unbind"
go


/*
** Messages for "sp_multdb_unbind"
**
** 17260, "Can't run %1! from within a transaction."
** 18608, "%1!: Delete row from master.dbo.sysattributes failed. Command 
**	   aborted."
** 18276, "%1! is not a valid object type."
** 18255, "%1! cannot be NULL."
** 18314, "Login '%1!' does not exist in syslogins table."
** 18951, "'%1!' is not currently supported."
** 19595, "Instance '%1!' does not exist."
*/

/*
** Procedure sp_multdb_unbind
**
** This procedure removes a binding from SYSATTRIBUTES
** for the MULTEMPDB_CLASS (class 16)
**      
** SMP
**	Triplet <objtype, objname, scope> could be either bound to a 
**	temporary database group or to a temporary database i.e. there
**	could be only one binding entry for the given triplet.
**	For SMP, @instance_name argument must be NULL.
**
** SDC
**	Triplet <objtype, objname, scope> could be either bound to a 
**	temporary database group or to local temporary databases. If the
**	binding is to a temporary database group, then there could be 
**	only one binding entry. However, if binding is to local temporary
**	databases then there could be multiple binding entries, one for
**	each cluster instance.
**	To unbind the given triplet from a temporary database group, 
**	instance_name is not required (it is ignored, if specified).
**	To unbind the given triplet from DB bindings, if instance_name
**	is given, then only the DB binding entry for the given instance
**	is removed. If no instance_name is provided, then all the 
**	DB binding entries for the given triplet are removed.
*/
create procedure sp_multdb_unbind
@obj_name	varchar(255),	/* object to be bound  */
@obj_type	varchar(30),	/* Type of object 'AP' or 'LG' */
@scope		varchar(255) = NULL,	/* Application name or login name */
@instance_name	varchar(255) = NULL	/* Cluster instance name (optional 
					** and valid only in SDC).
					*/
as
declare @class_id       smallint,       /* class in SYSATTRIBUTES */
        @attrib_id      smallint,       /* attribute in SYSATTRIBUTES */
        @object_cinfo   varchar(255),    /* object_cinfo in SYSATTRIBUTES */
        @int_val        int,            /* int_value in SYSATTRIBUTES */
        @group_id       int,            /* group id database being added to */
        @action         int,            /* action for built in */
        @upcase_str     varchar(30),	
	@app_name	varchar(255),	/* application name */
	@user_id	int,		/* user id */
	@instanceid     int,            /* (SDC only) instance id of the owner
					** of local user tempdb.
					*/
	@existing_bind_type int,	/* Existing binding type. Corresponds
                                        ** to int_value in SYSATTRIBUTES
                                        */
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@MULTDB_BINDDB	int,		/* binding is to a temporary database */
	@MULTDB_BINDGRP	int,		/* binding is to a group */
	@ATTR_DROP	int		/* indicates a binding update */

select @SMP = 0,
	@SDC = 1


	select @svrmode = @SMP

        /* Instance related information is not relevant in SMP. */
        select @instance_name = NULL
        select @instanceid = NULL



/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_multdb_unbind"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Don't do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */

/*
** Following constants must be consistent with their definition in
** multempdb.c
*/
select	@MULTDB_BINDGRP = 1,
	@MULTDB_BINDDB = 0


/* keep in sync with sysattr.h */
select @ATTR_DROP = 3

/* 
** Make sure that object type is valid.
** Can only be 'AP' or 'LG' or 'APPLICATION_NAME' or 'LOGIN_NAME'.
*/
select @upcase_str = upper(@obj_type)
if (@upcase_str = "LG") OR (@upcase_str = "AP")
	OR (@upcase_str = "APPLICATION_NAME") OR (@upcase_str = "LOGIN_NAME")
begin
	if (@upcase_str = "APPLICATION_NAME") OR (@upcase_str = "AP")
	begin
		select @obj_type = "AP"
	end
	else
	begin
		select @obj_type = "LG"
	end
end
else
begin
	/*
	** 18276, "%1! is not a valid object type."
	*/
	raiserror 18276, @obj_type
	return (1)
end

/*
** Object name can't be null
*/
if (@obj_name is NULL)
begin
	/*
	** 18255, "%1! cannot be NULL."
	*/
	raiserror 18255, "Object name"
	return (1)
end

select @action	= @ATTR_DROP		/* unbind */
select @user_id = NULL          /* id of user from syslogins */

/*
** We don't currently support a non null scope.
*/
if (@scope is not NULL)
begin
	/*
	** 18951, "'%1!' is not currently supported."
	*/
	raiserror 18951, "Scope"
	return (1)
end





/* 
** convert user name to user id after checking its existence 
*/
if (@obj_type = "LG")
begin
        if not exists (select suid from master..syslogins 
                        where (name = @obj_name))
        begin
		/*
		** 18314, "Login '%1!' does not exist in syslogins table."
		*/
		raiserror 18314, @obj_name
                return(1)
        end

        select @user_id = (select suid from master..syslogins 
                             where (name = @obj_name))

	if (@scope is not NULL)
	begin
		select @app_name = @scope
	end
end
/*
** if obj_type is "AP", then a non null scope
** would have the login name. If user name is specified
** then convert user name to user id after checking its existence
*/
else if (@obj_type = "AP")
begin
	select @app_name = @obj_name

	/*
	** if obj_type is "AP", then a non null scope
	** would have the login name. If user name is specified
	** then convert user name to user id after checking its existence
	*/
	if (@scope is not NULL)
	begin
		if not exists (select suid from master..syslogins 
					where (name = @scope))
        	begin
			/*
			** 18314, "Login '%1!' does not exist in syslogins 
			**         table."
			*/
			raiserror 18314, @scope
                	return(1)
        	end

 		select @user_id = (select suid from master..syslogins 
					where (name = @scope))
	end
end

/* Attribute is for binding */
select @attrib_id = 1

begin transaction multdb_unbind


begin
	/*
	** SMP
	**	There could be only one binding for a given triplet. Delete it.
	**
	** SDC and @instance_name is NULL
	**	If group binding, delete it.
	**	If database bindings, delete all bindings. 
	**	If the request was to remove a database binding for a spefific 
	**	instance, then it must be already handled above.
	*/
	delete from master..sysattributes 
		where class = @class_id 
			AND attribute = @attrib_id 
			AND object_type = @obj_type 
			AND object_cinfo = @app_name 
			AND object = @user_id

	if (@@error != 0)
	begin
		/*
		** 18608, "%1!: Delete row from master.dbo.sysattributes failed.
		**	   Command aborted."
		*/
		raiserror 18608, "sp_multdb_unbind"
		goto error_exit
	end
end

/*
** Currently, no action is required upon notification of an unbind event.
** Uncomment the notification below when some action needs to be implemented.
** SMP
**	Note that @instanceid is set as NULL as it is not relevant in SMP.
**
** SDC
**	If group binding is removed, @instanceid is set to NULL even if 
**	a valid instance name was specified in the procedure arguments.
**	For other cases, @instanceid value is passed.
**	Notified routine will make use of instanceid to take the appropriate
**	action such as to remove all db bindings vs db binding for a 
**	particular cluster instance.
*/
-- select @notify_status = 
--	attrib_notify (@class_id, @attrib_id, @obj_type, @user_id,
--		NULL, @instanceid, NULL, @app_name,
--		@MULTDB_BINDDB, @tempdb_name, NULL, NULL, "", @action)
--
--if (@notify_status = 0)
--begin
--	print "Internal error: Failed to remove binding."
--	goto error_exit
--end


/* 
** Commit the transaction 
*/
commit transaction multdb_unbind
return (0)

error_exit:
	rollback transaction multdb_unbind
	return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_unbindall_db')
begin
	drop procedure sp_multdb_unbindall_db
end
go
print "Installing sp_multdb_unbindall_db"
go


/*
** Messages for "sp_multdb_unbindall_db"
**
** 17260, "Can't run %1! from within a transaction."
** 18946, "Either the database '%1!' does not exist or is not a user 
**         created temporary database."
** 19580, "Either the database '%1!' does not exist or is not a local 
**	   user temporary database." 
*/

/*
** Procedure sp_multdb_unbindall_db
**
** This procedure removes all login/application bindings from SYSATTRIBUTES for
** a given database.
*/
create procedure sp_multdb_unbindall_db
@tempdb_name	varchar(255)	/* temporary database  */
as

declare @class_id	smallint,       /* class in SYSATTRIBUTES */
        @attrib_id	smallint,       /* attribute in SYSATTRIBUTES */
        @int_val        int,            /* int_value in SYSATTRIBUTES */
	@MULTDB_BINDDB	int,		/* binding is to a temporary database */
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@DBT3_USER_TEMPDB	int,	/* (SMP only) Bit value corresponding 
					** to DBT3_USER_TEMPDB 
					*/
	@DBT3_LOCAL_USER_TEMPDB	int,	/* (SDC only) Bit value corresponding to
					** DBT3_LOCAL_USER_TEMPDB 
					*/
	@action		int,		/* action for built in */
	@ATTR_DROP	int		/* indicates a binding deletion */

select @SMP = 0,
        @SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP

	select @DBT3_USER_TEMPDB = number
		from master.dbo.spt_values
		where type = "D3" and name = "user created temp db"
end
else
begin
	select @svrmode = @SDC

	select @DBT3_LOCAL_USER_TEMPDB = number
		from master.dbo.spt_values
		where type = "D3" and name = "local user temp db"
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_multdb_unbindall_db"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Don't do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */

/*
** Following constants must be consistent with their definition in
** multempdb.c
*/
select @MULTDB_BINDDB = 0

/* keep in sync with sysattr.h */
select @ATTR_DROP = 3

/*
** In SMP, verify that specified dbname is a user created temporary database.
** Database bindings for a login/application could be created with user 
** create temporary databases only. Note that login/application binding 
** cannot be created with system tempdb.
**
** In SDC, verify that specified dbname is a local user temporary database.
** Database bindings for a login/application could be created with local 
** user temporary databases only.
*/
if (@svrmode = @SDC)
begin
	if not exists (select * from master..sysdatabases
		where name = @tempdb_name
			AND ((status3 & @DBT3_LOCAL_USER_TEMPDB) = 
					@DBT3_LOCAL_USER_TEMPDB))
	begin
		/*
		** 19580, "Either the database '%1!' does not exist 
		**         or is not a local user temporary database." 
		*/
		raiserror 19580, @tempdb_name
		return (1)
	end
end
else 	/* @SMP */
begin
	if not exists (select * from master..sysdatabases 
		   where name = @tempdb_name
		     AND ((status3 & @DBT3_USER_TEMPDB) = 
						@DBT3_USER_TEMPDB))
	begin
		/*
		** 18946, "Either the database '%1!' does not exist 
		**	   or is not a user created temporary database."
		*/
		raiserror 18946, @tempdb_name
		return (1)
	end
end

/*
** Delete all login and application bindings 
*/
select @attrib_id = 1 			/* Attribute is for binding */
select @int_val = @MULTDB_BINDDB	/* Binding is to a database as 
					** opposed to a group 
					*/
select @action = @ATTR_DROP

begin transaction multdb_unbindall_db

/*
** Delete the entry representing login/application bindings to the
** given database.
*/
delete from master..sysattributes 
	where class = @class_id 
		AND attribute = @attrib_id 
		AND char_value = @tempdb_name
		AND int_value = @int_val

if (@@error != 0)
begin
	/*
	** 18608, "%1!: Delete row from master.dbo.sysattributes failed.
	**	   Command aborted."
	*/
	raiserror 18608, "sp_multdb_unbindall_db"
	goto error_exit
end

/*
** Currently, no action is required upon notification of an unbindall event.
** Uncomment the notification below when some action needs to be implemented.
** Send only one notification for this operation. The notified routine needs
** to decode the operation code as 'unbindall_db' by examining the received
** arguments.
*/
-- select @notify_status = 
--	attrib_notify (@class_id, @attrib_id, NULL, NULL,
--		NULL, NULL, NULL, NULL,
--		@MULTDB_BINDDB, @tempdb_name, NULL, NULL, "", @action)
--
--if (@notify_status = 0)
--begin
--	print "Internal error: Failed to remove binding."
--	goto error_exit
--end
	
commit transaction multdb_unbindall_db
return (0)

error_exit:
rollback transaction multdb_unbindall_db
return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_unbindall_gr')
begin
	drop procedure sp_multdb_unbindall_gr
end
go
print "Installing sp_multdb_unbindall_gr"
go


/*
** Messages for "sp_multdb_unbindall_gr"
**
** 17240, "'%1!' is not a valid name."
** 17260, "Can't run %1! from within a transaction."
** 18608, "%1!: Delete row from master.dbo.sysattributes failed. 
** 	   Command aborted."
** 18947, "Group '%1!' does not exist."
*/

/*
** Procedure sp_multdb_unbindall_gr
**
** This procedure removes all login/application bindings from SYSATTRIBUTES for
** a given temporary database group.
*/
create procedure sp_multdb_unbindall_gr
@group_name	varchar(255)	/* temporary database group name */
as

declare @class_id	smallint,       /* class in SYSATTRIBUTES */
        @attrib_id	smallint,       /* attribute in SYSATTRIBUTES */
        @int_val        int,            /* int_value in SYSATTRIBUTES */
	@MULTDB_BINDGRP	int,		/* binding is to a tempdb group */
	@svrmode	int,		/* Indicates the SMP or SDC mode */
	@SMP		int,		/* Indicates SMP Server */
	@SDC		int,		/* Indicates SDC Server */
	@action		int,		/* action for built in */
	@ATTR_DROP	int		/* indicates a binding deletion */

select @SMP = 0,
        @SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP
end
else
begin
	select @svrmode = @SDC
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_multdb_unbindall_gr"
	return (1)
end
else
begin
	/* Use TSQL mode of unchained transactions */
	set chained off
end

/* Don't do "Dirty Reads" */
set transaction isolation level 1

select @class_id = 16		/* class is MULTEMPDB_CLASS */
select @attrib_id = 1		/* attribute is MULTEMPDB_BIND */

/*
** Following constants must be consistent with their definition in
** multempdb.c
*/
select @MULTDB_BINDGRP = 1

/* keep in sync with sysattr.h */
select @ATTR_DROP = 3

/*
** Make sure group name is valid. Since 'default' is a reserved keyword
** it will fail the valid name test, so handle it separately.
*/
if ((@group_name != "default") AND (valid_name(@group_name) = 0))
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @group_name
	return (1)
end


/*
** Make sure that the specified group exists.
*/
select @attrib_id = 0		/* attribute is MULTEMPDB_GROUP */
if not exists (select * from master..sysattributes
		where class = @class_id
		AND attribute = @attrib_id
		AND object_type = 'GR'
		AND object_cinfo = @group_name)
begin

	/*
	** 18947, "Group '%1!' does not exist."
	*/
	raiserror 18947, @group_name
	return (1)
end


/*
** Delete all login and application bindings to the specified group.
*/
select @attrib_id = 1 			/* Attribute is for binding */
select @int_val = @MULTDB_BINDGRP	/* Binding is to a group */ 

select @action = @ATTR_DROP

begin transaction multdb_unbindall_gr

/*
** Delete the entry representing login/application bindings to the
** given temporary database group.
*/
delete from master..sysattributes 
	where class = @class_id 
		AND attribute = @attrib_id 
		AND char_value = @group_name
		AND int_value = @int_val

if (@@error != 0)
begin
	/*
	** 18608, "%1!: Delete row from master.dbo.sysattributes failed.
	**	   Command aborted."
	*/
	raiserror 18608, "sp_multdb_unbindall_gr"
	goto error_exit
end

/*
** Currently, no action is required upon notification of an unbindall event.
** Uncomment the notification below when some action needs to be implemented.
** Send only one notification for this operation. The notified routine needs
** to decode the operation code as 'unbindall_gr' by examining the received
** arguments.
*/
-- select @notify_status = 
--	attrib_notify (@class_id, @attrib_id, NULL, NULL,
--		NULL, NULL, NULL, NULL,
--		@MULTDB_BINDGRP, @group_name, NULL, NULL, "", @action)
--
--if (@notify_status = 0)
--begin
--	print "Internal error: Failed to remove binding."
--	goto error_exit
--end
	
commit transaction multdb_unbindall_gr
return (0)

error_exit:
rollback transaction multdb_unbindall_gr
return (1)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_multdb_show')
begin
	drop procedure sp_multdb_show
end
go
print "Installing sp_multdb_show"
go


/*
** Messages for "sp_multdb_show"
**
** 17260, "Can't run %1! from within a transaction."
*/

/*
** Procedure sp_multdb_show
**
** This procedure displays information stored in SYSATTRIBUTES
** for the MULTEMPDB_CLASS (class 16)
**      
*/
create procedure sp_multdb_show
	@option	varchar(10) = NULL,
	@name   varchar(255) = NULL

as

declare
	@loginname	varchar(255),	/* login name */
	@appname	varchar(255),	/* application name */
	@type		int,   		/* binding type 'GR' or 'DB' */
	@groupid	int,   		/* tempdb group id */
	@groupname	varchar(255),	/* tempdb group name */
	@dbname		varchar(255),	/* database name */
	@creategroups   int,		/* need the groups table */
	@createdbs	int,		/* need the dbs table */
	@createbind	int,		/* need the bindings table */
	@membership_list varchar(255),
	@groupmember_list varchar(255),
	@login_binding_list varchar(255),
	@app_binding_list varchar(255),
	@isSDC		int,
	@instanceid	int,
	@instancename	varchar(255),	
	@sqlbuf		varchar(255),
	@retstat	int,
	@grptdb_stat	int		/* status for temp db that could be
					** added to a group, in smp, this is
					** user create temp db, in sdc, this
					** means local user temp db.
					*/
/*
**  if we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
        raiserror 17260, "sp_multdb_show"
        return (1)
end
else
begin
        /* Use TSQL mode of unchained transactions */
        set chained off
end

/* Don't do "Dirty Reads" */
set transaction isolation level 1

/* initialize variables */
select @creategroups = 0
select @createdbs = 0
select @createbind = 0

select @isSDC = case 
		    when @@clustermode = "shared disk cluster" then 1
		    else 0
		end

if (@isSDC = 1)
	select @grptdb_stat = number
		from master.dbo.spt_values
		where   type = "D3" and name = "local user temp db"
else
	select @grptdb_stat = number 
		from master.dbo.spt_values
		where   type = "D3" and name = "user created temp db"

/* do we need the groups table */
if (@option in ("all", "gr", NULL))
	select @creategroups = 1

/* do we need the databases table */
if (@option in ("all", "gr", "db", NULL))
	select @createdbs = 1

/* do we need the bindings table */
if (@option in ("all", "login", "app", NULL))
	select @createbind = 1

if (@creategroups = 1)
begin
/* stores groups */
	create table #multdb_groups
			(groupname varchar(255), 
			groupid int)
end

if (@createdbs = 1)
begin
/* stores database to group membership */
	create table #multdb_dbs
			(dbname varchar(255), 
			instancename varchar(255) null,
			groupname varchar(255))
end

if (@createbind = 1)
begin
/* stores login/application bindings */
	create table #multdb_bindings
			(loginname varchar(255) null, 
			app varchar(255) null, 
			groupname varchar(255) null,
			dbname varchar(255) null,
			instancename varchar(255) null,
			hardness varchar(6) null)
end

if (@creategroups = 1)
begin
/* populate groups */
	insert into #multdb_groups(groupname, groupid)
   	  select object_cinfo, int_value
    	    from master..sysattributes
              where class = 16
	      AND attribute = 0
	      AND object_type = 'GR'
end

if (@createdbs = 1)
begin
	/*
	** The system tempdb is implicitly part of the
	** default group. So as long as the default group
	** has been created we will report the tempdb as 
	** belonging to that group.
	*/
	if @isSDC = 0 and 
		exists (select * 
		     from master..sysattributes
		     where class = 16
		     AND attribute = 0
		     AND object_type = 'GR'
		     AND object_cinfo = "default")
	begin
		insert into #multdb_dbs(dbname, groupname)
	  	  values ("tempdb", "default")
	end

	insert into #multdb_dbs(dbname, instancename, groupname)
  	  select a.object_cinfo, instance_name(a.object_info2), b.object_cinfo
            from master..sysattributes a, master..sysattributes b
              where a.class = 16 
	        AND b.class = 16
	        AND a.object_type = 'D ' 
	        AND b.object_type = 'GR'
	        AND a.object = b.int_value
	/* Inserting the names of temporary databases which are not added	
	** to any group
	*/
	insert into #multdb_dbs(dbname, groupname)
	 select name, " "  from master..sysdatabases
	  where status3 & @grptdb_stat != 0 AND name NOT IN
	   (select dbname from  #multdb_dbs)
	  
end

if (@createbind = 1)
begin
	/* login binding to group */
	insert into #multdb_bindings(loginname, groupname, hardness)
     	  select a.name, b.char_value, 
		 case 
			when b.object_info1 = 1 then 'HARD'
			else 'SOFT'
		 end
            from master..syslogins a, master..sysattributes b
              where b.class = 16 
                AND b.object_cinfo is NULL
                AND b.attribute = 1 
                AND (b.object_type = 'LG' OR b.object_type = 'AP') 
                AND a.suid = b.object
                AND b.int_value = 1

	/* login binding to DB */
	insert into #multdb_bindings(loginname, dbname, instancename, hardness)
          select a.name, b.char_value, 
		 case
			when @isSDC = 1 then instance_name(b.object_info2)
			else NULL
		 end,
		 case 
			when b.object_info1 = 1 then 'HARD'
			else 'SOFT'
		 end
            from master..syslogins a, master..sysattributes b
              where b.class = 16
              AND b.object_cinfo is NULL
              AND b.attribute = 1
              AND (b.object_type = 'LG' OR b.object_type = 'AP')
              AND a.suid = b.object
              AND b.int_value = 0

	/* application binding to group */
 	insert into #multdb_bindings(app, groupname, hardness)
          select a.object_cinfo, a.char_value,  
		 case 
			when a.object_info1 = 1 then 'HARD'
			else 'SOFT'
		 end
            from master..sysattributes a
              where a.class = 16 
              AND (a.object_type = 'LG' OR a.object_type = 'AP') 
              AND a.object is NULL
              AND a.attribute = 1
              AND a.int_value = 1

	/* application binding to DB */
	insert into #multdb_bindings(app, dbname, instancename, hardness)
  	  select a.object_cinfo, a.char_value, 
		 case
			when @isSDC = 1 then instance_name(a.object_info2)
			else NULL
		 end,
		 case 
			when a.object_info1 = 1 then 'HARD'
			else 'SOFT'
		 end
            from master..sysattributes a
              where a.class = 16
              AND (a.object_type = 'LG' OR a.object_type = 'AP')
              AND a.object is NULL
              AND a.attribute = 1
              AND a.int_value = 0


	/* application with login scope binding to group */
	insert into #multdb_bindings(loginname, app, groupname, hardness)
          select a.name, b.object_cinfo, b.char_value,
		 case 
			when b.object_info1 = 1 then 'HARD'
			else 'SOFT'
		 end
            from master..syslogins a, master..sysattributes b
              where b.class = 16 
      		AND b.attribute = 1 
      		AND (b.object_type = 'LG' OR b.object_type = 'AP') 
      		AND a.suid = b.object
      		AND b.object_cinfo is not NULL 
      		AND b.object is not NULL
      		AND b.int_value = 1

	/* application with login scope binding to DB */
	insert into #multdb_bindings(loginname, app, dbname, 
					instancename, hardness)
  	  select a.name, b.object_cinfo, b.char_value,  
		 case
			when @isSDC = 1 then instance_name(b.object_info2)
			else NULL
		 end,
		 case 
			when b.object_info1 = 1 then 'HARD'
			else 'SOFT'
		 end
    	    from master..syslogins a, master..sysattributes b
      	      where b.class = 16
      		AND b.attribute = 1
      		AND (b.object_type = 'LG' OR b.object_type = 'AP')
      		AND a.suid = b.object
      		AND b.object_cinfo is not NULL
      		AND b.object is not NULL
      		AND b.int_value = 0

end

select @membership_list = "'Database' = dbname,'GroupName' = groupname"
select @groupmember_list = "'Member Databases' = dbname"
select @login_binding_list = "'Login' = loginname,'Application' = app,\
			      'Group' = groupname,'Database' = dbname,\
			      'Hardness' = hardness"
select @app_binding_list = "'Application' = app,'Login' = loginname, \
			    'Group' = groupname, 'Database' = dbname, \
			    'Hardness' = hardness"




if (@option is NULL) or (@option = "all")
begin
	/* Print list of database groups */
	exec sp_autoformat @fulltabname = #multdb_groups,
		@selectlist = "'Temporary Database Groups' = groupname"

	/* Print database to group membership */
	print " "
	exec sp_autoformat @fulltabname = #multdb_dbs,
		@selectlist = @membership_list 

	/* Print information about each binding */
	print " "
	exec sp_autoformat @fulltabname = #multdb_bindings, 
		@selectlist = @login_binding_list
	print " "
end

if (@option = "gr")
begin
	if (@name is NULL)
	begin
		/* Print list of database groups */
		exec sp_autoformat @fulltabname = #multdb_groups,
        		@selectlist = "'Temporary Database Groups' = groupname" 
	end
	else
	begin
		/* Print databases bound to this group */
		select dbname, instancename 
		into #multdb_dbs1rs
		from #multdb_dbs
		where groupname = @name
		exec sp_autoformat @fulltabname = #multdb_dbs1rs,
			@selectlist = @groupmember_list
		drop table #multdb_dbs1rs
	end
end


if (@option = "db")
begin
	if (@name is NULL)
	begin
		/* Print database to group membership */
        	print " "
		exec sp_autoformat @fulltabname = #multdb_dbs,
        		@selectlist = @membership_list
	end
	else
	begin
		/* Print database to group membership for given database */
		print " "
		select dbname, instancename, groupname
		into #multdb_dbs2rs 		
		from #multdb_dbs
		where dbname = @name
		exec sp_autoformat @fulltabname = #multdb_dbs2rs,
			@selectlist = @membership_list
		drop table #multdb_dbs2rs
	end
end

if (@option = "login")
begin
	if (@name is NULL)
	begin
		print " "
		exec sp_autoformat @fulltabname = #multdb_bindings,
			@selectlist = @login_binding_list,
		     	@whereclause = "where  loginname is not null"
	end
	else
	begin
		print " "
                select  loginname, app, groupname, dbname, instancename, 
			hardness
		into #multdb_bindings1rs
                  from #multdb_bindings
                    where loginname = @name
		exec sp_autoformat @fulltabname = #multdb_bindings1rs,
			@selectlist = @login_binding_list
		drop table #multdb_bindings1rs
	end
end

if (@option = "app")
begin
	if (@name is NULL)
	begin
		print " "
		exec sp_autoformat @fulltabname = #multdb_bindings,
		 @selectlist = @app_binding_list,
                 @whereclause = "where app is not null"
        end
        else
        begin
                print " "
                select  app, loginname, groupname, dbname, instancename, 
			hardness
		into #multdb_bindings2rs
                from #multdb_bindings
                where app = @name
		exec sp_autoformat @fulltabname = #multdb_bindings2rs,
			@selectlist = @app_binding_list
		drop table #multdb_bindings2rs
        end
end

if (@option = "who")
begin
	if @@clustermode != "shared disk cluster"
	begin
	    select "spid" = spid, "loginame" = suser_name(suid), 
		   "application"= program_name 
	    into #multdb_show1rs
	       from master..sysprocesses
	          where tempdb_id(spid) = db_id(@name)
	    exec sp_autoformat @fulltabname = #multdb_show1rs
	    drop table #multdb_show1rs
	end
	else
	begin

	    select "spid" = spid, "loginame" = suser_name(suid),

		"application"= program_name

	    into #multdb_show2rs
	       from master..sysprocesses
		  where 

			tempdb_id(spid) = db_id(@name)
	    exec sp_autoformat @fulltabname = #multdb_show2rs
	    drop table #multdb_show2rs
	end
end
	
if (@creategroups = 1)
	drop table #multdb_groups
if (@createdbs = 1)
	drop table #multdb_dbs
if (@createbind = 1)
	drop table #multdb_bindings

return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_tempdb')
begin
	drop procedure sp_tempdb
end
go
print "Installing sp_tempdb"
go


/*
** Messages for "sp_tempdb"
**
** 17240, "'%1!' is not a valid name."
** 17260, "Can't run %1! from within a transaction."
** 18954, "Usage:"
** 18955, "sp_tempdb 'help' "
** 18956, "sp_tempdb 'create', <groupname>"
** 18957, "sp_tempdb 'drop', <groupname>"
** 18958, "sp_tempdb 'add', <tempdbname>, <groupname>"
** 18959, "sp_tempdb 'remove', <tempdbname>, <groupname>"
** 18960, "sp_tempdb 'bind', <objtype>, <objname>, <bindtype>, <bindobj>[, <scope>[, <hardness>]]"
** 18961, "sp_tempdb 'unbind', <objtype>, <objname>[, <scope>]"  [for SMP]
** 19588, "sp_tempdb 'unbind', <objtype>, <objname>[, <scope>[, <instancename>]]" [For SDC]
** 18971, "sp_tempdb 'unbindall_db', <tempdbname>"
** 19583, "sp_tempdb 'unbindall_gr', <groupname>"
** 18962, "sp_tempdb 'show', <command>, <name>"
** 18963, "<objtype> = ['LG' ('login_name') | 'AP' ('application_name')]; <bindtype> = ['GR' ('group') | 'DB' ('database')] "
** 18973, "<hardness> = ['hard' | 'soft']"
** 18964, "<command> = ['all' | 'gr' ('groups') | 'db' ('databases') | 'login' ('logins') | 'app' ('applications') | 'who']"
** 18965, "sp_tempdb : Unrecognized command %1!. execute 'sp_tempdb help' for usage."
** 18970, "sp_tempdb 'who', <dbname>"
** 19875  "Parameter '%1!' is too long. Maximum length is '%2!'."
*/

/*
**      Procedure sp_tempdb
**
**      This procedure provides the administration interface for
**	managing temporary database groups, and user defined bindings.
**	
**	This procedure does its work by calling other stored procedures
**	based on the command passed in.
**      
*/

create procedure sp_tempdb
	@cmd	varchar(30) = null,	/* the operation to perform */
	@arg1	varchar(255) = null,	/* first argument */
	@arg2	varchar(265) = null,	/* second argument */
	@arg3	varchar(255) = null,	/* third argument */
	@arg4	varchar(255) = null,	/* fourth argument */
	@arg5	varchar(255) = null,	/* fifth argument  <scope> */
	@arg6	varchar(255) = null	/* sixth argument <hardness> */
as


declare @retstat	int		/* return status */
declare @msg            varchar(250)    /* buffer for message */
declare	@arg1_temp	varchar(255)	/* temp. holder of arg1 */
declare	@svrmode	int		/* Indicates the SMP or SDC mode */
declare	@SMP		int		/* Indicates SMP Server */
declare	@SDC		int		/* Indicates SDC Server */

select @SMP = 0, 
	@SDC = 1

if @@clustermode != "shared disk cluster"
begin
	select @svrmode = @SMP
end
else
begin
	select @svrmode = @SDC
end

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_tempdb"
	return (1)

end
begin
	set chained off
end
set transaction isolation level 1

/*
** Check if user has sa role. Procedure can only be executed 
** if user has sa_role. proc_role will print any error message.
*/
if (proc_role("sa_role") = 0)
	return 1

/*
** Print usage info or "help" or in absense of a command 
*/
if (@cmd = "help") or (@cmd is NULL)
begin
	exec sp_getmessage 18954, @msg output
	print @msg
	exec sp_getmessage 18955, @msg output
	print @msg
	exec sp_getmessage 18956, @msg output
	print @msg
	exec sp_getmessage 18957, @msg output
	print @msg
	exec sp_getmessage 18958, @msg output
	print @msg
	exec sp_getmessage 18959, @msg output
	print @msg
	exec sp_getmessage 18960, @msg output
	print @msg
	if (@svrmode = @SMP)
	begin
		exec sp_getmessage 18961, @msg output
		print @msg
	end
	else if (@svrmode = @SDC)
	begin
		exec sp_getmessage 19588, @msg output
		print @msg
	end
	exec sp_getmessage 18971, @msg output
	print @msg
	exec sp_getmessage 19583, @msg output
	print @msg
	exec sp_getmessage 18962, @msg output
	print @msg
	exec sp_getmessage 18970, @msg output
	print @msg
	print " "
	exec sp_getmessage 18963, @msg output
	print @msg
	exec sp_getmessage 18973, @msg output
	print @msg
	exec sp_getmessage 18964, @msg output
	print @msg
	return(0)
end
/*
** Command is to create a new group 
*/
else if (@cmd = "create")
begin
	/*
	** Check for incorrect number of arguments
	*/
	if ((@arg1 is NULL) OR (@arg2 is not NULL) OR (@arg3 is not NULL)
             OR (@arg4 is not NULL) OR (@arg5 is not NULL) OR (@arg6 is not NULL))
	begin
		
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18956,  @msg output
		print @msg
		return 1
	end
	else
	/*
	** execute worker stored procedure 
	*/
	begin
		exec @retstat = sp_multdb_creategroup @arg1
		return @retstat
	end
end
/*
** Command is to delete a group  
*/
else if (@cmd = "drop")
begin
	/*
        ** Check for incorrect number of arguments
        */
	if ((@arg1 is NULL) OR (@arg2 is not NULL) OR (@arg3 is not NULL)
             OR (@arg4 is not NULL) OR (@arg5 is not NULL) OR (@arg6 is not NULL))
        begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18957,  @msg output
		print @msg
                return 1
        end
        else
	/*
        ** execute worker stored procedure 
        */
        begin
                exec @retstat = sp_multdb_dropgroup @arg1
                return @retstat
        end
end
/*
** Command is to add a temporary database to a group  
*/
else if (@cmd = "add")
begin	
	/*
        ** Check for incorrect number of arguments
        */
	if ((@arg1 is NULL) OR (@arg2 is NULL) OR (@arg3 is not NULL)
	     OR (@arg4 is not NULL) OR (@arg5 is not NULL) OR (@arg6 is not NULL))
	begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18958, @msg output
		print @msg
		return 1
	end
	else
	/*
        ** execute worker stored procedure. Invalid names
	** for @arg1 and @arg2 are caught in sp_multdb_addtogroup.
        */
	begin
		exec @retstat = sp_multdb_addtogroup @arg1, @arg2
		return @retstat
	end
end
/*
** Command is to remove a temporary database from a group  
*/
else if (@cmd = "remove")
begin   
	/*
        ** Check for incorrect number of arguments
        */
        if ((@arg1 is NULL) OR (@arg2 is NULL) OR (@arg3 is not NULL)
             OR (@arg4 is not NULL) OR (@arg5 is not NULL) OR (@arg6 is not NULL))
        begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18959, @msg output
		print @msg
                return 1
	end
        else
	/*
        ** execute worker stored procedure. Invalid names
	** for @arg1 and @arg2 are caught in sp_multdb_removefromgroup.
        */
        begin
                exec @retstat = sp_multdb_removefromgroup @arg1, @arg2
                return @retstat
        end
end
/*
** Command is to create a new binding
*/
else if (@cmd = "bind")
begin
	/*
        ** Check for incorrect number of arguments
        */
        if ((@arg1 is NULL) OR (@arg2 is NULL)
             OR (@arg3 is NULL) OR (@arg4 is NULL))
        begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18960, @msg output
		print @msg
                return 1
	end
        else if (@arg2 = "")
        /*
        ** Not a valid name (login/application)
        */
        begin
                /*
                ** 17240, "'%1!' is not a valid name."
                */
                raiserror 17240, @arg2
                return 1
        end
        else if (datalength(@arg2) > 255)
	begin
		raiserror 19875, @arg2, 255
		return 1
	end
	/*
        ** execute worker stored procedure 
        */
        begin
                exec @retstat = sp_multdb_bind @arg2, @arg1, @arg5, @arg3, @arg4, @arg6
                return @retstat
        end
end
/*
** Command is to remove a binding 
*/
else if (@cmd = "unbind")
begin
	/*
        ** Check for incorrect number of arguments
	** SMP: sp_tempdb unbind <obj_type> <obj_name> [, <scope> ]
	** SDC: sp_tempdb unbind <obj_type> <obj_name> [, <scope>, <inst_name>]
        */
	if ((@arg1 is NULL)OR (@arg2 is NULL) OR 
	    ((@svrmode = @SMP) and (@arg4 is not NULL)) OR
	    ((@svrmode = @SDC) and (@arg5 is not NULL)))
	begin
		exec sp_getmessage 18954, @msg output
		print @msg
		if (@svrmode = @SMP)
		begin
			exec sp_getmessage 18961, @msg output
			print @msg
		end
		else if (@svrmode = @SDC)
		begin
			exec sp_getmessage 19588, @msg output
			print @msg
		end
		return 1
	end
	else
	/*
        ** execute worker stored procedure 
        */
	begin
		if (@svrmode = @SMP)
		begin
			exec @retstat = sp_multdb_unbind @arg2, @arg1, @arg3
		end
		else if (@svrmode = @SDC)
		begin
			exec @retstat = sp_multdb_unbind @arg2, @arg1, @arg3, @arg4
		end
		return @retstat
	end
end
/*
** Command is to display information stored in sysattributes for class 16
*/
else if (@cmd = "show")
begin
	select @arg1_temp = @arg1

	/*
	** Get our short form for the argument.
	*/
	if (@arg1_temp = "groups")
	begin
		select @arg1 = "gr"
	end
	else if (@arg1_temp = "databases")
	begin
		select @arg1 = "db"
	end
	else if (@arg1_temp = "logins")
	begin
		select @arg1 = "login"
	end
	else if (@arg1_temp = "applications")
	begin
		select @arg1 = "app"
	end


	/* Check for invalid arguments */
	if (@arg1 not in ("all", "gr", "db", "login", "app", "who", NULL))
	begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18962, @msg output
		print @msg
		return 1
	end

	/* Always need a dbname with "who" */
	if (@arg1 = "who") and (@arg2 is NULL)
        begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18966, @msg output
		print @msg
                return 1
        end

	/*
        ** execute worker stored procedure 
        */
	exec @retstat = sp_multdb_show @arg1, @arg2
	return @retstat
end
/*
** User wants to see active sessions bound to a temp. database 
*/
else if (@cmd = "who")
begin
	if (@arg1 is NULL)
	begin
		exec sp_getmessage 18954, @msg output
                print @msg
                exec sp_getmessage 18970, @msg output
                print @msg
                return 1
        end

	/*
        ** execute worker stored procedure
        */
	exec @retstat = sp_multdb_show @cmd, @arg1
	return @retstat
end
/*
** User wants to drop all login/app bindings for a temporary database.
*/
else if (@cmd = "unbindall_db")
begin
	if (@arg1 is NULL)
	begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 18971, @msg output
		print @msg
		return 1
	end

	/*
	** execute worker stored procedure
	*/
	exec @retstat = sp_multdb_unbindall_db @arg1
	return @retstat
end
/*
** User wants to drop all login/app bindings for a temporary database group.
*/
else if (@cmd = "unbindall_gr")
begin
	if (@arg1 is NULL)
	begin
		exec sp_getmessage 18954, @msg output
		print @msg
		exec sp_getmessage 19583, @msg output
		print @msg
		return 1
	end

	/*
	** execute worker stored procedure
	*/
	exec @retstat = sp_multdb_unbindall_gr @arg1
	return @retstat
end
else
/*
** Unrecognized command 
*/
begin
	exec sp_getmessage 18965, @msg output
	print @msg, @cmd
	return 1
end

return (0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_listener')
begin
	drop procedure sp_listener
end
go
print "Installing sp_listener"
go


/*
** Messages for "sp_listener"
**
** 17260, "Can't run %1! from within a transaction."
** 19862, "Invalid input: Server name '%1!' matches the remote instance." 
** 18899, "Invalid value supplied to parameter %1!."
** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
*/

/*
**	sp_listener cmd, addr, eng
**
** This stored procedure is the interface to the
** Dynamic Listener Daemon functionality. It allows
** the sa to start, stop, suspend, resume, reserve,
** network listeners on selected ports and engines.
** The command will execute atomically unless the command
** is reserve or the engine parameter has been specified
** via the keyword remaining.
**
** Parameters:
**	cmd can be any of the following:
**		"start", "stop", "suspend", "resume", "status",
**		"reserve", "activate", "unreserve"
**	addr can be the name of the running ASE server
**		or a "proto:host:port" combination.
**		length of addr is at the most MAXDLADDR
**
**	eng can be any list of engines including ranges such
**		as "1-3,5,7,10-12", or the word "remaining"
**
** Return Value:
**	0 in case of success, 1 in case of error
*/
create procedure sp_listener
@cmd	varchar(30) = null,
@addr   varchar(612) = null,
@eng	varchar(30) = null
as

if @@trancount > 0
begin
	/* 17260, "Can't run %1! from within a transaction." */
	raiserror 17260, "sp_listener"
	return (1)
end
else
begin
	set chained off
end

set transaction isolation level 1
set nocount on

/* Must have sa_role as this stored procedure is related to config */
if (proc_role("sa_role") < 1)
	return (1)

/* Restrict listener command to local instance */
if (@@clustermode = "shared disk cluster"
    and (instance_id(@addr) is not NULL)
    and (instance_id(@addr)!= instance_id()))
begin
	/* 19862, "Invalid input: Server name '%1!' matches the remote instance." */
	raiserror 19862,@addr
	return (1)
end

if (@cmd in ("start", "stop", "suspend", "resume", "status"))
begin
	if (char_length(@addr) > 611)  
	begin
        	/*
	        ** 17325, "The length of input parameter '%1!' is longer than the permissible %2! characters."
        	*/
		raiserror 17325, @addr, 611
		return (1)
	end
	dbcc listener(@cmd, @addr, @eng)
	if (@@error != 0)
	begin
		return (1)
	end
end
else
begin
        print "Usage: sp_listener command [,'protocol:machine:port'[,engine]] "
        print "sp_listener commands:"
        print "start"
        print "stop"
        print "suspend"
        print "resume"
        print "status"
        print "help"
        print "The type of protocol can be one of the following: "
        print "tcp, tli, ssltcp, ssltli, winsock, sslnlwnsck, sslwinsock"
	print "IPV6 addresses should be enclosed in brackets, for ex 'tcp:[2001:ec8:4008:1::123]:80'"
end
return (0)

go
exec sp_procxmode 'sp_listener', 'anymode'
go
grant execute on sp_listener to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dcachestats_obj_details')
begin
	drop procedure sp_dcachestats_obj_details
end
go
print "Installing sp_dcachestats_obj_details"
go


create procedure sp_dcachestats_obj_details
@objid int,
@indid int
as
declare @tmp_obj_size_KB int
declare @owner_name varchar(30)
declare @index_name varchar(255)

select  @tmp_obj_size_KB = 0
select  @index_name = ""
select  @owner_name = ""

/* See note tagged by NOTE_ABOUT_BUILT_INS in file 
** sproc/dbcc_run_configreport
*/
if (@indid = 0)
begin
        select  @tmp_obj_size_KB = isnull(reserved_pages(db_id(), id, 
						case
							when indid = 1
							then 0
							else indid
						end), 0)
                                        * (@@maxpagesize/1024)
        from sysindexes
	where id = @objid
	and (indid = 0 or indid = 1)
end
else
begin
        select  @tmp_obj_size_KB = isnull(reserved_pages(db_id(), id, indid) , 0)
                                        * (@@maxpagesize/1024),
        @index_name = name
        from sysindexes
        where
                id = @objid
                and indid = @indid
end

select @owner_name = user_name(uid)
from sysobjects
where id = @objid

insert into #obj_details(dbid, owner, objid, indid, index_name, size_KB)
                        values(db_id(), @owner_name, @objid,
                                        @indid, @index_name,
                                        @tmp_obj_size_KB)
return 0

go
exec sp_procxmode 'sp_dcachestats_obj_details', 'anymode'
go
grant execute on sp_dcachestats_obj_details to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_rjs_register')
begin
	drop procedure sp_rjs_register
end
go
print "Installing sp_rjs_register"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_rjs_register"
**
** 17260, "Can't run %1! from within a transaction."
** 19364, "'%1!' is not a valid value for a server name."
** 19365, "A Job Scheduler server name is required; enter the name of the server with JS installed that you want to register."
** 19367, "A host name is required when registering a Job Scheduler server."
** 19368, "A host port number is required when registering a Job Scheduler server." 
** 19372, "A host port number can not be negative. Enter a valid port number."
*/

create procedure sp_rjs_register
@js_server varchar(255),        /* name of js server */
@host_name varchar(255),       /* name of machine hosting JS server */
@host_port int                 /* server access port on host */
as
begin

   /*
   **  If we're in a transaction, disallow this since it might make recovery
   **  impossible.
   */

   if @@trancount > 0
      begin
         /*
         ** 17260, "Can't run %1! from within a transaction."
         */
         raiserror 17260, "sp_rjs_register"
         return (1)
      end
   else
      begin
         /* Use TSQL mode of unchained transactions */
         set chained off
      end

   /* Dont do "Dirty Reads" */
   set transaction isolation level 1

   /*
   ** Check to see that the input params are correct and then hook up with
   ** sysattributes table to enter data.
   */
   if( (@js_server is NULL) OR (@js_server = "") )
      begin
         /*
         ** 19365, "A Job Scheduler server name is required; enter the name of the server with JS installed that you want to register."
         **/
         raiserror 19365
         return (1)
      end
   else
      begin
         if valid_name(@js_server) = 0
         begin
            /*
            ** 19364, "'%1!' is not a valid value for a server name."
            **/
            raiserror 19364, @js_server
            return (1)
         end
      end

   if( (@host_name is NULL) OR (@host_name = "") )
      begin
         /*
         ** 19367, 
         ** "A host name is required when registering a Job Scheduler server."
         **/
         raiserror 19367
         return (1)
      end

   if( (@host_port is NULL) OR (@host_port = 0) )
      begin
         /*
         ** 19368, "A host port number is required when registering a Job Scheduler server." 
         **/
         raiserror 19368
         return (1)
      end
   else 
      begin
         if( @host_port < 0 )
            begin
               /*
               ** 19372, "A host port number can not be negative. Enter a valid port number."
               **/
               raiserror 19372
               return (1)
            end
      end

   /* 
   ** Start a transaction so we don't lose the current JS server if the new
   ** one isn't created.
   */
   begin tran rjs_register

   /* 
   ** Remove any existing row before inserting 
   ** This statement must be deleted when multiple JS servers can be
   ** registered.
   */
   if exists (select 1 from master.dbo.sysattributes where class = 22)
      delete from master.dbo.sysattributes 
      where class = 22 and attribute = 1 and object_type = "JS"

   /*
   ** The following sysattribute columns hold the corresponding data for
   ** a registered JS:
   **
   **     object_type: JS
   **     object_cinfo: ASE server name
   **     char_value: host name
   **     int_value: host port
   **
   ** Note:  in future, if we want to register more than one Job Scheduler
   **        server, we have a natural key in object_cinfo (@js_server), 
   **        char_value (@host_name) and int_value (host_port).
   */
   insert master.dbo.sysattributes (class, attribute, object_type, 
                                    object_cinfo, char_value, int_value)
                             values(22, 1, "JS",  
                                    @js_server, @host_name, @host_port)
   if( (@@error !=0) OR (@@rowcount != 1 ) )
      begin
         rollback tran rjs_register
         return 1
      end 

   commit tran rjs_register

   return 0
end /*end sp*/
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_rjs_retrieve')
begin
	drop procedure sp_rjs_retrieve
end
go
print "Installing sp_rjs_retrieve"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_rjs_retrieve"
**   none
*/

create procedure sp_rjs_retrieve as
begin

   If @@trancount = 0
      set chained off

   /* Don't do "Dirty Reads" */
   set transaction isolation level 1

   /* Get the js rows in alpha order */
   select js_server = object_cinfo, 
          host_name = char_value, 
          host_port = int_value
   from master.dbo.sysattributes
   where class = 22
   order by object_cinfo

   return @@error
end
go
if exists (select name from sysobjects where name = 'sp_rjs_retrieve')
begin
    print 'Created sp_rjs_retrieve'
    grant execute on sp_rjs_retrieve to public
end
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_rjs_unregister')
begin
	drop procedure sp_rjs_unregister
end
go
print "Installing sp_rjs_unregister"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% */

/*
** Messages for "sp_rjs_unregister"
**
** 17260, "Can't run %1! from within a transaction."
** 19364, "'%1!' is not a valid server name."
** 19369, "A Job Scheduler server name is required;  enter the name of the server with JS installed that you want to unregister."
** 19370, "A host name is required when unregistering a Job Scheduler server."
** 19371, "A host port number is required when unregistering a Job Scheduler server." 
*/

create procedure sp_rjs_unregister
@js_server varchar(30),        /* name of js server */
@host_name varchar(255),       /* name of machine hosting JS server */
@host_port int                 /* server access port on host */
as
begin

   /*
   **  If we're in a transaction, disallow this since it might make recovery
   **  impossible.
   */

   if @@trancount > 0
      begin
         /*
         ** 17260, "Can't run %1! from within a transaction."
         */
         raiserror 17260, "sp_rjs_unregister"
         return (1)
      end
   else
      begin
         /* Use TSQL mode of unchained transactions */
         set chained off
      end

   /* Dont do "Dirty Reads" */
   set transaction isolation level 1

   /*
   ** Check to see that the input params are correct and then hook up with
   ** sysattributes table to enter data.
   */
   if( (@js_server is NULL) OR (@js_server = "") )
      begin
         /*
         ** 19369, "A Job Scheduler server name is required;  enter the name of the server with JS installed that you want to unregister."
         **/
         raiserror 19369
         return (1)
      end
   else
      begin
         if valid_name(@js_server) = 0
         begin
            /*
            ** 19364, "'%1!' is not a valid server name."
            **/
            raiserror 19364, @js_server
            return (1)
         end
      end

   if( (@host_name is NULL) OR (@host_name = "") )
      begin
         /*
         ** 19370, 
         ** "A host name is required when unregistering a Job Scheduler server."
         **/
         raiserror 19370
         return (1)
      end

   if( (@host_port is NULL) OR (@host_port = 0) )
      begin
         /*
         ** 19371, "A host port number is required when unregistering a Job Scheduler server." 
         **/
         raiserror 19371
         return (1)
      end

   /*
   ** The following sysattribute columns hold the corresponding data for
   ** a unregistered JS:
   **
   **     object_type: JS
   **     object_cinfo: ASE server name
   **     char_value: host name
   **     int_value: host port
   **
   ** Note:  in future, if we want to unregister more than one Job Scheduler
   **        server, we have a natural key in object_cinfo (@js_server), 
   **        char_value (@host_name) and int_value (host_port).
   */
   delete from master.dbo.sysattributes 
   where class = 22 and  attribute = 1 and  object_type = "JS" and  
         object_cinfo = @js_server and  char_value = @host_name and  
         int_value = @host_port

   return @@error
end /*end sp*/
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_show_options')
begin
	drop procedure sp_show_options
end
go
print "Installing sp_show_options"
go


/* 
** This stored procedure prints all the server options, which have been set in
** current session. @@options the array of bits corresponding to server options.
** For every option, "low" is the byte number in @@options, and "high" is the 
** bit within that byte corresponding to the option. If the bit is set, print
** name of that option.
*/
create procedure sp_show_options
as
select a.number, a.name
        from master.dbo.spt_values a, master.dbo.spt_values c
        where   c.type = "P"
                and a.type='N'
                and c.low <= datalength(@@options)
                and a.number = c.number
                and convert(tinyint,substring(@@options, c.low, 1)) & c.high != 0
        return (0)
go
go
exec sp_procxmode 'sp_show_options', 'anymode'
go
grant execute on sp_show_options to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_tran_dumpable_status')
begin
	drop procedure sp_tran_dumpable_status
end
go
print "Installing sp_tran_dumpable_status"
go


/*
** This stored procedure translates to text the bitmap
** returned by the built-in tran_dumpable_status().
**
** Parameters:
**      @dbname         - DB name to query or NULL for current
**
*/
create procedure sp_tran_dumpable_status @dbname sysname = NULL
as
begin
	declare @status int

	if (@dbname is null)
		select @dbname = db_name()

	select @status = tran_dumpable_status(@dbname)

	select bit = power(2, a.number), description = a.name
        from master.dbo.spt_values a, master.dbo.spt_values c
        where   c.type ='P'
                and a.type='DX'
                and c.low <= datalength(@status)
                and a.number = c.number
                and convert(tinyint,substring(@status, c.low, 1)) & c.high != 0

        return (0)
end

go
exec sp_procxmode 'sp_tran_dumpable_status', 'anymode'
go
grant execute on sp_tran_dumpable_status to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_lmconfig')
begin
	drop procedure sp_lmconfig
end
go
print "Installing sp_lmconfig"
go

/*
** Messages for "sp_lmconfig"
**
** 17260, "Can't run %1! from within a transaction."
*/
create procedure sp_lmconfig
@configname varchar(255) = NULL,	/* license config option name */
@configvalue varchar(255) = "1"		/* license config value */
as
declare @config_id int			/* config id for dbcc lmconfig */
declare @configvaluelen int		/* length of license config value */


/*
** dbcc lmconfig is not allowed in a transaction.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_lmconfig"
	return(1)
end

set chained off

set transaction isolation level 1

/*
** Check if user has SA role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/

if (proc_role("sa_role") = 0)
	return (1)

if (@configname is NULL)
begin
	/* Display all license configuration and license status */
	dbcc lmconfig
end
else
begin
	/* Map config name to config id for dbcc lmconfig. */
	select @config_id = case @configname
				when "edition" then 1
				when "license type" then 2
				when "smtp host" then 3
				when "email recipients" then 4
				when "email severity" then 5
				when "smtp port" then 6
				when "email sender" then 7
				else 0
			    end

	if (@config_id = 0)
	begin
		print "Error: No matching configuration options."
		return (1)
	end
	else if (@configvalue = "1")
	begin
		/* (@config_id != 0) and (@configvalue is not specified) */
		/* Display the license configuration */
		dbcc lmconfig(@config_id)
	end
	else
	begin
		/* (@config_id != 0) and (@configvalue is specified) */
		/* Set the license configuration */
		if (@configvalue is null)
		begin
			select @configvalue = "null"
		end
		select @configvaluelen = datalength(@configvalue)
		dbcc lmconfig(@config_id, @configvalue, @configvaluelen)
	end
end

return(0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_post_xpload')
begin
	drop procedure sp_post_xpload
end
go
print "Installing sp_post_xpload"
go

/*
** Messages for "sp_post_xpload"
**
** 17260, "Can't run %1! from within a transaction."
*/
create procedure sp_post_xpload
as
declare @objid		int
declare @dbname		varchar(30)
declare @tablename	varchar(255)
declare @msg		varchar(400)
declare @numtable	int
declare @tablecount	int
declare @sqltext	varchar(400)

/*
** dbcc reindex is not allowed in a transaction.
*/
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_post_xpload"
	return(1)
end

set chained off

set transaction isolation level 1

/*
** Check if user has SA role, proc_role will also do auditing
** if required. proc_role will also print error message if required.
*/
  
if (proc_role("sa_role") = 0)
	return (1)

/*
** Check if this database was loaded from across platform.
*/
set flushmessage on
select @dbname = db_name()
if not exists (select 1 from master.dbo.sysdatabases
		where name = @dbname
		and (status3 & 524288) != 0)
begin
	select @msg =	"Error: Current database "
	+ @dbname
	+ " is not a database that was loaded from a byte-swapped architecture."
	print @msg
	return(1)
end

/*
** Re-partition hash partition tables.
*/

/* Get the number of hash partition tables */
select @numtable = count(*)
	from dbo.sysindexes, dbo.sysobjects
	where sysobjects.type = 'U'
	and sysindexes.partitiontype = 2
	and sysobjects.id = sysindexes.id
	and (sysindexes.indid = 0 or sysindexes.indid = 1)
	and sysobjects.sysstat2 & 1024 = 0

if (@numtable != 0)
begin
	select @tablecount = 0
	declare sysobjects_hash_cursor insensitive cursor for
		select sysobjects.name
		from dbo.sysindexes(index csysindexes),
		     dbo.sysobjects(index csysobjects)
		where type = 'U'
		and sysindexes.partitiontype = 2
		and sysobjects.id = sysindexes.id
		and (sysindexes.indid = 0 or sysindexes.indid = 1)
		and sysobjects.sysstat2 & 1024 = 0
	open sysobjects_hash_cursor
	fetch sysobjects_hash_cursor into @tablename
	while (@@sqlstatus != 2 and @@sqlstatus != 1)
	begin
		select @tablecount = @tablecount + 1
		select @msg = "sp_post_xpload: Repartitioning hash partition table " + @tablename + " ("
			+ convert(varchar,@tablecount) + "/"
			+ convert(varchar,@numtable) + ")"
		print @msg
		select @sqltext = "reorg rebuild " + @tablename
		exec(@sqltext)
		if (@@error != 0)
		begin
			select @msg = "sp_post_xpload: Failed to repartition hash partition table " + @tablename
			print @msg
		end
		fetch sysobjects_hash_cursor into @tablename
	end
end

/*
** Rebuild global clustered index on rr partition tables to regenerate
** partition condition, if the partition key is unichar or univarchar.
*/

/* Get the number of such rr partition tables */
select @numtable = count(*)
	from sysobjects o, sysindexes i1
	where o.id = i1.id
	and i1.indid != 0 and i1.indid != 255 and i1.status3 & 1 = 1
	and o.type = 'U' and o.sysstat2 & 1024 = 0
	and i1.id in (select i2.id
		from sysindexes i2, syspartitionkeys p, syscolumns c
		where i2.id = p.id and p.id = c.id 
		and i2.indid = p.indid
		and i2.indid != 255 and i2.status3 & 1 = 1
		and p.colid = c.colid
		and c.type in (135, 155))
if (@numtable != 0)
begin
	select @tablecount = 0
	declare	sysobjects_rrind_cursor cursor for
		select o.name
		from sysobjects o(index csysobjects),
		     sysindexes i1(index csysindexes)
		where o.id = i1.id
		and i1.indid != 0 and i1.indid != 255 and i1.status3 & 1 = 1
		and o.type = 'U' and o.sysstat2 & 1024 = 0
		and i1.id in (select i2.id
			from sysindexes i2(index csysindexes),
			     syspartitionkeys p(index csyspartitionkeys),
			     syscolumns c(index csyscolumns)
			where i2.id = p.id and p.id = c.id 
			and i2.indid = p.indid
			and i2.indid != 255 and i2.status3 & 1 = 1
			and p.colid = c.colid
			and c.type in (135, 155))
	open sysobjects_rrind_cursor
	fetch sysobjects_rrind_cursor into @tablename
	while (@@sqlstatus != 2 and @@sqlstatus != 1)
	begin
		select @tablecount = @tablecount + 1
		select @msg = "sp_post_xpload: Rebuilding clustered index on table " + @tablename + " ("
			+ convert(varchar,@tablecount) + "/"
			+ convert(varchar,@numtable) + ")"
		print @msg
		/* Force rebuild of indexes including APL clustered index */
		dbcc reindex(@tablename,24)
		fetch sysobjects_rrind_cursor into @tablename
	end
end

/*
** Rebuild indexes on user tables.
*/

select @numtable = count(*)
	from dbo.sysobjects
	where type = 'U'

select @tablecount = 0

declare sysobjects_cursor cursor for
	select id, name
	from dbo.sysobjects(index ncsysobjects)
	where type = 'U'

open sysobjects_cursor

fetch sysobjects_cursor into @objid, @tablename

while (@@sqlstatus != 2 and @@sqlstatus != 1)
begin
	select @tablecount = @tablecount + 1
	select @msg = "sp_post_xpload: Processing table " + @tablename + " ("
			+ convert(varchar,@tablecount) + "/"
			+ convert(varchar,@numtable) + ")"
			
	print @msg
	if exists (select id
		   from dbo.sysindexes
		   where id = @objid
		   and indid > 1 and indid != 255)
	begin
		/*	
		** We don't need to check a APL table which has
		** only clustered index.
		** Need to check and rebuild non-clustered index on APL or
		** clusterd/non-cluster index on DOL.
		*/
		dbcc reindex(@objid,14)
	end

	fetch sysobjects_cursor into @objid, @tablename
end

close sysobjects_cursor

deallocate cursor sysobjects_cursor

checkpoint

return(0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_index_row_size_est')
begin
	drop procedure sp_index_row_size_est
end
go
print "Installing sp_index_row_size_est"
go


/*
** NOTES/COMMENTS
** --------------
**
** This procedures uses data from sysindexes (to extract each index key column
** through the index_col() built-in)and from syscolumns (to get column length,
** fixed/variable-column length) and then using the row-format of the index, 
** estimates the "average" row size for each index leaf-row. We can't simply use
** (minlen + maxlen)/2 from sysindexes, as that estimation does not take into 
** account differences due to fixed-, variable-length columns in an index row.
**
**
** The row format assumed is as follows:
**
**
** APL CI 	
** --------------------------------------------------------------------------------
** #varCols | dataFixed | childPageid | rowLength | dataVar | adjustTab | offsetTab
** --------------------------------------------------------------------------------
** 1-byte     n-byte	  4-byte	2-byte*	    m-byte*    x-byte~	  1-byte/varCol*
**									+ 1-byte terminator*
**
**
** APL NCI 	
** ---------------------------------------------------------------------------
** #varCols | dataFixed | RID    | rowLength | dataVar | adjustTab | offsetTab
** ---------------------------------------------------------------------------
** 1-byte     n-byte	  6-byte   2-byte*     m-byte*    x-byte~    1-byte/varCol*
**								   + 1-byte terminator*
**
** DOL PI/NCI
** 
** For indexes of DOL TABLES, we assume the following: 
**	No suffix compression is done 
**	All the keys in the index are unique [non-duplicate], and 
**	There is no difference b/w clustered/placement and nonclustered index
**
** --------------------------------------
** #rowHdr | dataFixed | RID    | dataVar 
** --------------------------------------
** 1-byte     n-byte	  6-byte   m-byte*^
**	
**
** (* => only for variable length columns)
** (~ => ignored)
** (^ => instead of separate column offset for variable length columns, the 
**       length is encoded within the data. Each variable length column would
**	 take 2-bytes.)
*/
go


/*
** SP_INDEX_ROW_SIZE_EST
**
** Internal stored sproc to return an estimate of the index row size given 
** the table id and the index id. 
**
** Parameters:
**	@table_id	- ID of the object for which index row size is being 
**			  etimated.
**	@index_id	- ID of the index for which index row size is being 
**			  estimated.
**	@table_type	- Lock scheme of the object passed. Will be either 
**			  0(allpages), 1(datapages), or 2(datarows).
**	@cols_to_max	- comma separated list of var column names for which 
**			  max size is to be used while index row size 
**			  estimation.
**
** Returns:
**	@row_size	- the estimated index row size
**
**	return status 	= 1 => Invalid table ID
**			= 2 => Invalid index ID
**			= 3 => Invalid lock scheme
**
*/
create procedure sp_index_row_size_est (
			  @table_id	int
			, @index_id	int
			, @table_type	tinyint
			, @cols_to_max	varchar(2060)	= NULL
			, @row_size	int 		output
)
as
begin -- {

	/* Declare variables */
	declare   @sum_fixed		int
		, @sum_var		int
		, @num_var		int
		, @index_name		varchar(255)
		, @index_type		varchar(20)
		, @maxcols_in_key	int
		, @i			int
		, @key			varchar(255)
		, @table_name		varchar(511)
		, @type			tinyint
		, @length		int
		, @vartype		smallint
		, @dol_ind_fixed_ovhd	smallint
		, @dol_ind_var_ovhd	smallint
		, @apl_cind_fixed_ovhd	smallint
		, @apl_cind_var_ovhd	smallint
		, @apl_ncind_fixed_ovhd	smallint
		, @apl_ncind_var_ovhd	smallint
		, @ind_data_len		int
	
	
	/* 
	** RESOLVE (anushas) Why not return silently without raising errors here
	** as this is an internal only sproc?
	*/
	
	/* Do parameter check */
	if exists(select * from sysobjects where id = @table_id)
	begin
		select	@index_name = name 
		from	sysindexes
		where	id    = @table_id 
		    and indid = @index_id

		if @index_name is null
		begin
			/* 18091, "The target index does not exist." */
			raiserror 18091
			return (2)
		end
	end
	else
	begin
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return(1)
	end

	if @table_type not in (0, 1, 2)
	begin
		/* 17579, "Lock scheme Unknown or Corrupted" */
		raiserror 17579
		return (3)	
	end
	
	/* Initialize variables */
	select 	  @table_name 	  = object_name(@table_id)
		, @row_size 	  = 0
		, @sum_fixed 	  = 0
		, @sum_var 	  = 0
		, @num_var 	  = 0
		, @maxcols_in_key = 31
		
	
	/* 
	** Look up each of the key fields for the index, and get the data length
	** and the number of variable length keys.
	*/
	select @i = 1
	
	while @i <= @maxcols_in_key
	begin -- {
		select @key = index_col(@table_name, @index_id, @i)
	
		if @key is null
			break
		else			-- Process one key field
		begin
			select	  @type	   = type
				, @length  = length
				, @vartype = offset
			from	syscolumns
			where	id   = @table_id
			    and name = @key
	
			if @vartype < 0
				select @num_var = @num_var + 1
			else
				select @sum_fixed = @sum_fixed + @length

			-- If variable length column, check whether max length 
			-- or average length is to be used.
			--
			if   (	   @type = 37 	-- varbinary
				or @type = 39	-- varchar, nvarchar
				or @type = 155)	-- univarchar
			begin
				select @sum_var = @sum_var 
						  + (case charindex(@key, 
						  		@cols_to_max)
							when 0 then @length/2
							else @length
						     end)
			end
		end
	
		select @i = @i + 1	-- Get next key field in this index
	end -- } 	-- End of while
	
	
	
	/* 
	** Estimate the row size for this index as follows. 
	** 
	** Refer to the row formats for clarity (given in the comments at the
	** beginning of this file)
	*/	
	select	  @dol_ind_fixed_ovhd 	= 1 + 6
		, @dol_ind_var_ovhd 	= 1 + 6 + (2 * @num_var)
		, @apl_cind_fixed_ovhd 	= 1 + 4
		, @apl_cind_var_ovhd	= 1 + 4 + 2 + 1 + (1 * @num_var)
		, @apl_ncind_fixed_ovhd	= 1 + 6
		, @apl_ncind_var_ovhd	= 1 + 6 + 2 + 1 + (1 * @num_var)
		, @ind_data_len 	= @sum_fixed + @sum_var
	
	if @table_type = 0 	-- APL table 
	begin
		select @row_size =   @ind_data_len
				   + (case @num_var
					when 0 then (case @index_id
							when 1 then @apl_cind_fixed_ovhd
							else @apl_ncind_fixed_ovhd
						     end)
					else (case @index_id
						when 1 then @apl_cind_var_ovhd
						else @apl_ncind_var_ovhd
					      end)
				      end)
	end
	else		-- DOL table 
	begin
		select @row_size =  @ind_data_len 
				  + (case @num_var
				  	when 0 then @dol_ind_fixed_ovhd
					else @dol_ind_var_ovhd
				     end)
	end
end --} 	-- Procedure done! 
go
exec sp_procxmode 'sp_index_row_size_est', 'anymode'
go
grant execute on sp_index_row_size_est to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_index_space_est')
begin
	drop procedure sp_index_space_est
end
go
print "Installing sp_index_space_est"
go


/*
** NOTES/COMMENTS
** --------------
**
** 1.	Lock scheme of the table can be found by interpreting the lockscheme 
** 	column as follows: 
**		0 => allpages, 1=> datarows, 2 => datapages 
**
** 2.	This procedure assumes that the <tableID, indexID, partitionID> threesome 
**	passed as input has a corresponding input row in the #indexData table, 
**	with indexlevel set to -1. If not found, the procedure silently returns
**	with a status of 1.
**
** 3.	Valid values for @pagesize is 1024, 2048, 4096, 8192, 16384. This 
**	procedure assumes that the calling procedure does this check before 
**	passing the correct value. If valid @pagesize is not passed, the 
**	procedure would return silently with a status of 2.
**
** 4.	Following constants are being used for better code readability -
**
**	@input_index_level (-1)		   : indexlevel column in the #indexData
**					     table is set to this value for the 
**					     input row corresponding to the 
**					     <id,indid,ptnid> threesome.
**
**	@dataval_na (-1)		   : Value that a column is set to in 
**					     case no value is applicable, or 
**					     needed to be set for it.
**
**	@max_apl_rowsperpage_possible (256): The maximum no of rows that an APL 
**					     page can hold.
**
**	@max_index_level_possible (255)	   : The maximum height of an index tree
**	
**	@aplpagehdrsize	(32)		   : The APL page header size.
**	@dolpagehdrsize (44)		   : The DOL page header size.
**
** 4.	If index level exceeds 255, the index is too big and can not be built. 
**	In that case, the procedure returns silently with a status of 4.
**	[This scenario is possible only when this sproc is called by sp_estspace.
**	Not possible for an existing index.]
**
** 5.	The used pages related calculations are somewhat incorrect. But the 
**	sp_estspace sproc uses it, and hence, it is retained in this sproc too.
**
*/
go

/* 
** Create the dummy table that is referenced in this procedure, so that this
** procedure can be created/loaded.
*/
if object_id("#indexData") is not null
	drop table #indexData
go

create table #indexData
(
	  id		int
	, indid		int
	, ptnid		int
	, name		varchar(255)
	, type		varchar(20)
	, indexlevel	int
	, ffactor	smallint
	, maxrowsperpage	smallint
	, datalayerpages	int
	, numrows		float
	, leafrowsize		float
	, nonleafrowsize	float
	, lockscheme		tinyint
	, numofdatapages	int
	, datasizeinkb		float
	, numofusedpages	int
	, usedsizeinkb		float
)
go

if (@@error != 0) select syb_quit() 
go

/* 
** SP_INDEX_SPACE_EST
**
** internal stored sproc that returns an estimate of the space usage for an 
** index of a table. 
**
** Parameters:
**	@table_id	-	object for which the estimate is to be computed.
**	@index_id	-	index for which the estimate is to be computed.
**	@partition_id	-	partition for which the estimate is to be 
**				computed. 
**	@pagesize	-	page size. if not supplied, the server page size
**				will be used.
**
**
** Pre-req:
**
** expects the #indexData table with the following schema
**
**	id			int
**	indid			int
**	ptnid			int
**	name			varchar(255)
**	type			varchar(20)
**	indexlevel		int
**	ffactor			smallint
**	maxrowsperpage		smallint
**	datalayerpages		int
**	numrows			float
**	leafrowsize		float
**	nonleafrowsize		float
**	lockscheme		tinyint
**	numofdatapages		int
**	datasizeinkb		float
**	numofusedpages		int
**	usedsizeinkb		float
**
** to be created and appropriately populated by the caller before calling this
** procedure (a row for the input <tableID, indexID, partitionID> threesome with 
** indexlevel set to -1 and the ffactor, maxrowsperpage, datalayerpages, 
** numrows, leafrowsize, nonleafrowsize, lockscheme set accordingly). 
**
** This temp table acts like a placeholder for these various space related 
** parameters that will be used for the index's space estimates, and are like 
** [indirect] inputs to this sproc. 
**
**
** Returns:
**	Nothing. But insterts values - numofdatapages, datasizeinkb, 
**	numofusedpages, usedsizeinkb - for each level of the index 
**	in the #indexData. And sums the numofdatapages and numofusedpages and 
**	places that in index level = -1.
**	
**	return status	= 1 => the <tableID, indexID, partitionID> threesome 
**			       passed is invalid. It does not have a 
**			       corresponding input row in #indexData table.
**			= 2 => invalid pagesize passed.
**			= 3 => invalid lock scheme
**			= 4 => index level out of bounds
**
*/

create procedure sp_index_space_est (
			  @table_id 		int
			, @index_id 		int
			, @partition_id 	int
			, @pagesize 		int 	= NULL 
)
as
begin -- {
	
	declare 
		  @table_type	 		tinyint
		, @index_name			varchar(255)
		, @index_type			varchar(20)
		, @level			smallint
		, @fillfactor			float
		, @mrpg				smallint
		, @datalayerpages		float
		, @numrows			float
		, @leafrowsize			float
		, @nonleafrowsize		float
		, @level_datapages		float
		, @level_usedpages		float
		, @total_datapages		float
		, @total_usedpages		float
		, @leaf_rows_per_page		int
		, @nonleaf_rows_per_page	int
		, @next_level_rows		float
		, @page_K			int
		, @status2			int
		, @more				bit

		/* Temporary placeholder variables */
		, @tmp1				int
		, @tmp2				int
		, @tmp3				int
		
		/* Constants */
		, @input_index_level		smallint
		, @dataval_na			smallint
		, @max_apl_rowsperpage_possible	smallint
		, @max_index_level_possible	tinyint
		, @aplpagehdrsize		tinyint
		, @dolpagehdrsize		tinyint
		

	/* Constant initialization */
	select 	  @input_index_level		= -1
		, @dataval_na		 	= -1
		, @max_apl_rowsperpage_possible	= 256
		, @max_index_level_possible	= 255
		, @aplpagehdrsize		= 32
		, @dolpagehdrsize		= 44
		
	
	/* Parameter checks */
	if ( @pagesize is null )
	begin
		-- Get server page size if user did not specify one
		select @pagesize = @@maxpagesize

	end
	else
	begin
		if @pagesize not in (2048, 4096, 8192, 16384) 
		begin
			return (2)
		end
	end
		
	select @page_K = @pagesize/1024

	/* 
	** Check if the <id, indid, ptnid> threesome is valid and extract the 
	** space parameters required for estimation.
	*/
	select	  @tmp1 	  = id
		, @tmp2 	  = indid
		, @tmp3 	  = ptnid
		, @fillfactor 	  = ffactor
		, @mrpg 	  = maxrowsperpage
		, @datalayerpages = datalayerpages
		, @numrows 	  = numrows
		, @leafrowsize 	  = leafrowsize
		, @nonleafrowsize = nonleafrowsize
		, @table_type 	  = lockscheme
	from 	#indexData
	where	id	   = @table_id 
	    and indid	   = @index_id 
	    and ptnid	   = @partition_id
	    and indexlevel = @input_index_level

	if (@tmp1 is null or @tmp2 is null or @tmp3 is null)
	begin
		return (1)
	end
	
	/* Check for valid lock scheme */
	if @table_type not in (0, 1, 2)
	begin
		return(3)		
	end
	
	/* Code starts here */
	select	  @total_datapages = 0.0
		, @total_usedpages = 0.0
		, @fillfactor = @fillfactor/100.0


	/* Extract the index name and type */		
	select	  @index_name = name
		, @status2 = status2
	from	sysindexes
	where 	id = @table_id 
	    and indid = @index_id
	
	if @index_id = 1
	begin
		select @index_type = 'clustered'
	end
	else
	if @index_id > 1
	begin
		if (@status2 & 512 = 512)
		begin
			select @index_type = 'clustered'
		end
		else
		begin
			select @index_type = 'nonclustered'
		end
	end

	/*
	** Note: the case where number of rows is zero can not occur when this
	** sproc is called by sp_estspace [it does not allow it].
	*/
	if @numrows = 0
	begin -- {
		if @table_type = 0	-- APL table
		begin
			select	  @total_datapages = 1
				, @total_usedpages = 1
				
		end
		else
		begin
			select	  @total_datapages = 2
				, @total_usedpages = 2
				
			-- Root page (level 1)
			insert #indexData 
			( id, indid, ptnid, name, type, indexlevel, numofdatapages,
			  datasizeinkb, numofusedpages, usedsizeinkb)
			values
			( @table_id, @index_id, @partition_id, @index_name, 
			  @index_type, 1, 1, @page_K, 1, @page_K)
		end

		-- One leaf page (level 0)
		insert #indexData 
		( id, indid, ptnid, name, type, indexlevel, numofdatapages, 
		  datasizeinkb, numofusedpages, usedsizeinkb)		
		values		
		( @table_id, @index_id, @partition_id, @index_name, @index_type,
		  0, 1, @page_K, 1, @page_K)


		-- Update the total data and used pages
		update	#indexData
		set 	  numofdatapages = ceiling(@total_datapages)
			, numofusedpages = ceiling(@total_usedpages)
		where 	id	   = @table_id 
		    and indid	   = @index_id 
		    and ptnid	   = @partition_id
		    and indexlevel = @input_index_level
	
		update	 #indexData
		set	  datasizeinkb = numofdatapages * @page_K
			, usedsizeinkb = numofusedpages * @page_K
		where 	id	   = @table_id 
		    and indid	   = @index_id 
		    and ptnid	   = @partition_id
		    and indexlevel = @input_index_level

		return (0)
	end -- } 	-- End of if
	
	/* 
	** Compute the number of rows per page (may be extracted into a 
	** separate module later) as folows. 
	*/

	/* Account for the page header space */
	select @pagesize = @pagesize - case @table_type
					when 1 then @dolpagehdrsize
					when 2 then @dolpagehdrsize
					else @aplpagehdrsize
				       end
					
	
	/*
	** Fill factor applies as follows on the leaf pages:
	** -- For APL tables, it applies only on NCI [indid >1].
	** -- For DOL tables, it applies on both CI and	NCI [indid >1].
	** -- For NCI in APL/DOL tables, if fill factor is not set server-wide 
	**    default is used.
	**
	** Also, fill factor if set to 0, leaves room for 2 rows in each page. 
	** If set to 100, it does not leave any space on the page.
	*/
	if ( @index_id = 1)		-- APL CI
	begin
		select @leaf_rows_per_page = @pagesize/@leafrowsize - 2
	end
	else
	begin
		 
		-- Use the fill factor passed, if any. [It could be the value
		-- passed by user to sp_estspace, or extracted from sysindexes
		-- by other calling procedures] 
		--
		-- If not set, use the server wide default value.
		--		
		if @fillfactor = 0
		begin
			select @fillfactor = value/100.0 
			from master.dbo.syscurconfigs
			where comment = 'dafault fill factor percent'
		end
		
		if (@fillfactor != 0)
		begin
			select @leaf_rows_per_page = 
					 @pagesize*@fillfactor/@leafrowsize 
		end
		else 
		begin
			select @leaf_rows_per_page = 
					@pagesize/@leafrowsize - 2
		end
	end

	/*
	** Fillfactor is not applicable on nonleaf pages. However, we assume 
	** this is treated same as the case of fill factor = 0 and leave room
	** for 2 rows in each page.
	*/
	select @nonleaf_rows_per_page = @pagesize/@nonleafrowsize - 2

	if @leaf_rows_per_page < 1
	begin
		select @leaf_rows_per_page = 1
	end

	if  @nonleaf_rows_per_page < 1
	begin
		select @nonleaf_rows_per_page = 1
	end
	
	/* For APL table NCI, account for the max rows per page, if set. */
	if @table_type = 0 and @index_id != 1 and @mrpg != 0
	begin
		if (@leaf_rows_per_page > @mrpg)
			select @leaf_rows_per_page = @mrpg
	end

	/* 
	** For APL tables, the no. of rows per page can not exceed the maximum 
	** limit (of 256).
	*/
	if @table_type = 0
	begin
		if @leaf_rows_per_page > @max_apl_rowsperpage_possible
		begin
			select 	@leaf_rows_per_page 
				= @max_apl_rowsperpage_possible
		end
			
		if @nonleaf_rows_per_page > @max_apl_rowsperpage_possible
		begin
			select	@nonleaf_rows_per_page 
				= @max_apl_rowsperpage_possible
		end
	end
	
	
	/* Prestage index building information */
	select @more = 1, @level = 0

	/* Now, estimate the #levels and #pages */
	
	/* 
	** For APL CI, the first level of index is based on the number of data 
	** pages. For APL NCI, and any DOL index, it is the number of data rows
	*/
	select @next_level_rows = case @index_id 
					when 1 then @datalayerpages
					else @numrows
				  end

	while @more = 1
	begin -- {
		if @level > @max_index_level_possible
		begin
			-- This index is too big to build 
			-- raiserror 19414, @index_name
 			--
			return (4)
		end
		
		-- Calculate the number of pages at a single index level
		select @level_datapages = 
			@next_level_rows/convert(float, 
						 case @level
						   when 0 then @leaf_rows_per_page
						   else @nonleaf_rows_per_page
						 end
						)
		
		select @next_level_rows = @level_datapages

		-- Note: The used pages counts are retained only to be used by 
		-- 	 sp_estspace that might call this in future.
		--
		
		-- Account for allocation/oam pages.
		select @level_usedpages = @level_datapages + 
						(@level_datapages/256.0) + 1.0
		
		
		-- Insert the row into the results table
		insert 	#indexData 
		( id, indid, ptnid, name, type, indexlevel, numofdatapages, 
		  datasizeinkb, numofusedpages, usedsizeinkb)
		values
		( @table_id, @index_id, @partition_id, @index_name, @index_type,
		  @level, ceiling(@level_datapages), @level_datapages * @page_K,
		  ceiling(@level_usedpages), @level_usedpages * @page_K)

		select	  @total_datapages = @total_datapages 
						+ ceiling(@level_datapages)
			, @total_usedpages = @total_usedpages
						+ ceiling(@level_usedpages)
			, @level = @level + 1
		
		-- Can we fit the next level in 1 page? If yes, we are done
		if @next_level_rows <= @nonleaf_rows_per_page
			select @more = 0
	
	end -- } 	-- End of while
	
	/* 
	** Account for the root page. For APL tables, if the entire index fits 
	** on a single page, that becomes the root page and there are no 
	** intermediate or leaf levels. DOL tables, however, always have a leaf 
	** level between the root page and the data pages.
	*/
	if @table_type != 0 or @level_datapages > 1
	begin
		insert	#indexData 
		( id, indid, ptnid, name, type, indexlevel, numofdatapages, 
		  datasizeinkb, numofusedpages, usedsizeinkb)
		values	
		( @table_id, @index_id, @partition_id, @index_name, @index_type,
		  @level, 1, @page_K, 1, @page_K)
	 
		 select	  @total_datapages = @total_datapages + 1
		 	, @total_usedpages = @total_usedpages + 1
	end		

		
	/*
	** Update the #indexData with the total number of index pages across all 
	** levels. The numofdatapages, numofusedpages, datasizeinkb, usedsizeinkb
	** for indexlevel = -1 is the place holder for this total count. This will be
	** used by sp_fragmentation for its estimates. Not by sp_estspace which 
	** gives a level-wise break up.
	*/
	update	#indexData
	set 	  numofdatapages = ceiling(@total_datapages) 
		, numofusedpages = ceiling(@total_usedpages)
	where	id    = @table_id 
	    and indid = @index_id 
	    and ptnid = @partition_id
	    and indexlevel = @input_index_level

	update #indexData
	set	  datasizeinkb = numofdatapages * @page_K
		, usedsizeinkb = numofusedpages * @page_K
	where 	id    = @table_id 
	    and indid = @index_id 
	    and ptnid = @partition_id
	    and indexlevel = @input_index_level

end  --} 	-- Procedure done!
go

/* Drop the temporay table that was created initially */
drop table #indexData
go

go
exec sp_procxmode 'sp_index_space_est', 'anymode'
go
grant execute on sp_index_space_est to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_paramcheck')
begin
	drop procedure sp_spaceusage_paramcheck
end
go
print "Installing sp_spaceusage_paramcheck"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:58 2006 
*/
/*
** raiserror Messages for spaceusage_paramcheck [Total 4]
**
** 17993, "'%1!' is not a valid argument."
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
** 19536, "No value for the %1! name given."
** 19537, "Invalid syntax or illegal use of the USING clause."
*/
/*
** sp_getmessage Messages for spaceusage_paramcheck [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
**	SP_SPACEUSAGE_PARAMCHECK
**
**	The sub-procedure that does some basic syntactic checks on the
**	parameters passed to the sp_spaceusage procedure. Called by
**	sp_spaceusage.
**
**	Parameters:
**		@actionword	- The action to be performed. 
**		@entity_type	- Type of entity. Can be "table"/"index".
**		@entity_name	- The entity name identifier pattern string.
**		@using_clause	- The USING clause, if any, specified as part of
**				  the action string in case of "archive", 
**				  "report" and "report summary" action and 
**				  extracted from it in sp_spaceusage.
**		@command	- A command, if any, that is to be run on the
**				  object before generating space usage
**				  estimates for it.
**		@from_date	- Date, if any, from when on to look for data 
**				  in the archive table to generate report.
**		@to_date	- Date, if any, till when to look for data in 
**				  the archive table to generate report.
**		@select_list	- The input SELECT list string
**		@where_clause	- The input WHERE clause string
**		@orderby_clause	- The input ORDER BY clause string
**	
**	Returns
**		0 - if all goes well
**		3 - invalid entity name
**		4 - invalid command
**		5 - invalid USING clause
**		7 - invalid datetime format [from_date/to_date]
**		8 - invalid SELECT list, WHERE clause or ORDER BY clause
{
*/
create procedure sp_spaceusage_paramcheck
(
	  @actionword		varchar(20)
	, @entity_type		varchar(12)
	, @entity_name		varchar(550)
	, @using_clause		varchar(350)	= NULL
	, @command		varchar(100)	= NULL
	, @from_date		varchar(30)	= NULL
	, @to_date		varchar(30)	= NULL
	, @select_list	 	varchar(1536)	= NULL
	, @where_clause 	varchar(1536)	= NULL
	, @orderby_clause	varchar(768)	= NULL	
)
as
begin	-- { 	-- procedure begins! 

	declare	  @left_substr		varchar(350)
		, @right_substr		varchar(350)
		, @middle_substr	varchar(350)
		, @rest			varchar(350)
		, @compactedcmd		varchar(100)
		, @updstatcmd		varchar(20)
		, @updtabstatcmd	varchar(25)
		, @updindstatcmd	varchar(25)
		, @updallstatcmd	varchar(25)
		, @validcommands	varchar(120)
		, @partcnt		int
		, @commacnt		int
		, @dbnamepattern	varchar(10)
		, @prefixpattern	varchar(10)
		, @unitpattern1		varchar(12)
		, @unitpattern2		varchar(12)
		, @retvalue		int
		, @errorfound		bit
		, @wherepattern		varchar(15)
		, @orderbypattern	varchar(15)
		
	select	  @compactedcmd  = NULL
		, @updstatcmd	 = "update statistics"
		, @updtabstatcmd = "update table statistics"
		, @updindstatcmd = "update index statistics"
		, @updallstatcmd = "update all statistics"
		, @errorfound	 = 0
		, @dbnamepattern = "dbname=%"
		, @prefixpattern = "prefix=%"
		, @unitpattern1  = "unit=[kmg]b"
		, @unitpattern2  = "unit=pages"
		, @wherepattern  = "where %"
		, @orderbypattern= "order by %"
	
	select	  @validcommands =   "'" + @updstatcmd 	  + "'"
				 + ", '" + @updtabstatcmd + "'"
				 + ", '" + @updindstatcmd + "'"	

	/* 
	** Assume action and entity types are checked prior to calling this
	** sproc and are valid. Based on it, we do some checks.
	**
	** Checks include :-
	** o entity_name is valid 
	**	. It can not be NULL for 'table'/'index' enity type
	**	. For 'table' entity type, it has to be 1-part or 2-part.
	**	. For 'index' entity type, it has to be 2-part or 3-part.
	**	. For 'tranlog' entity type, it has to be "syslogs" or NULL.
	**
	** o using_clause is a valid string
	**	. It is invalid for display mode [and will be ignored, if set].
	**	. The string contains "dbname=<db>", or "prefix=<pre>", or both.
	**
	** o command is a valid allowed command
	**	. Currently valid commands are 'update statistics', 'update table
	**	  statistics', 'update all statistics'. 
	**
	*/
	if @entity_name is NULL and @entity_type != "tranlog"
	begin
		raiserror 19536, @entity_type
		return (3)
	end

	select @partcnt = 0
	
	exec sp_substring_count @entity_name, ".", 1, @partcnt out

	if	   @partcnt > 3 
		or (@entity_type = "table" and @partcnt not in (0,1) ) 
		or (@entity_type = "index" and @partcnt not in (1,2) ) 
		or (@entity_type = "tranlog" 
			and @entity_name is not NULL
			and lower(ltrim(rtrim(@entity_name))) != "syslogs" )
	begin
		raiserror 17993, @entity_name
		return (3)
	end

	if @command is not NULL
	begin
		exec sp_replace_string_plus @command, "", "", 0
						, @compactedcmd out

		select @compactedcmd =	lower(ltrim(rtrim(@compactedcmd)))

		if @compactedcmd not in (@updstatcmd, @updtabstatcmd, @updindstatcmd)
		begin
			raiserror 19194, @command, @validcommands
			return (4)
		end
	end
	
	-- Use sp_replace_string_plus to remove the white space, if any, in the
	-- USING clause and then check for case "dbname=%" and the like. This is
	-- required because, as there's no other way to selectively allow 
	-- any white space in and around "=" and at the same time disallow 
	-- other characters, using the regular expression support in T-SQL.
	--
	if @using_clause is not NULL
	begin	-- {
	
		select	  @left_substr  = NULL
			, @right_substr = NULL
			, @middle_substr= NULL
			, @rest		= NULL
			, @retvalue	= 0
			, @commacnt	= 0
			, @errorfound 	= 0
		
		exec sp_substring_count @using_clause, ",", 1, @commacnt out

		if @commacnt = 0
		begin	-- {	-- coma not found
	
			exec @retvalue = sp_replace_string_plus @using_clause
						, "", NULL, 0, @using_clause out

			select @using_clause = lower(@using_clause)
			
			-- For display action only the unit specifier is valid
			-- as part of the USING clause.
			--
			if @actionword in ( "display" , "display summary" )
			begin
				if 	@using_clause not like @unitpattern1
				    and @using_clause not like @unitpattern2
				begin				
					raiserror 19537
					return (5)
				end
			end
			
			if 	@using_clause not like @dbnamepattern
			    and @using_clause not like @prefixpattern
			    and @using_clause not like @unitpattern1
			    and @using_clause not like @unitpattern2
			begin
				select @errorfound = 1
			end
			
		end	-- }
		else if @commacnt = 1 or @commacnt = 2		
		begin	-- {	
		
			exec @retvalue = sp_split_string @using_clause, ",", 1, 
							@left_substr out, 
							@rest out
					
			if @commacnt = 2				
			begin	
				exec @retvalue = sp_split_string @rest, ",", 1,
							  @middle_substr out,
							  @right_substr out
			end
			else
			begin
				select @right_substr = @rest
			end
		
			if 	@left_substr is NULL 
			     or @right_substr is NULL
			     or (@middle_substr is NULL and @commacnt = 2)
			begin
					select @errorfound = 1
			end 
			else 
			begin	-- {
			
				exec sp_replace_string_plus @left_substr, ""
						, NULL, 0, @left_substr out
				
				exec sp_replace_string_plus @right_substr, ""
						, NULL, 0, @right_substr out
				
				exec sp_replace_string_plus @middle_substr, ""
						, NULL, 0, @middle_substr out
			
				select 	  @left_substr  = lower(@left_substr)
					, @right_substr = lower(@right_substr)
					, @middle_substr= lower(@middle_substr)

				if @left_substr like @dbnamepattern
				begin	-- {
				
					if  (  @right_substr like @prefixpattern
					    and (    @middle_substr like 
					    			@unitpattern1
					     	  or @middle_substr like 
						  		@unitpattern2
					    	  or @commacnt = 1))
					   or
					   (	(    @right_substr like 
					   			@unitpattern1
						  or @right_substr like 
						  		@unitpattern2)
					    and (    @middle_substr like 
					    			@prefixpattern
					    	  or @commacnt = 1))
					begin
						select @errorfound = 0
					end
					else
					begin
						select @errorfound = 1
					end
					
				end	-- }
				else if @left_substr like @prefixpattern
				begin	-- {
				
					if  (  @right_substr like @dbnamepattern
					    and (    @middle_substr like 
					    			@unitpattern1
					     	  or @middle_substr like 
						  		@unitpattern2
					    	  or @commacnt = 1))
					   or
					   (	(    @right_substr like 
					   			@unitpattern1
					   	  or @right_substr like 
						  		@unitpattern2)
					    and (    @middle_substr like 
					    			@dbnamepattern
					    	  or @commacnt = 1))
					begin
						select @errorfound = 0
					end
					else
					begin
						select @errorfound = 1
					end
					
				end	-- }
				else if	   @left_substr like @unitpattern1
					or @left_substr like @unitpattern2
				begin	-- {
				
					if (@right_substr like @prefixpattern
					     and (@middle_substr like 
					     			@dbnamepattern
					    	   or @commacnt = 1 ))
					   or
					   (@right_substr like @dbnamepattern 
					     and (@middle_substr like 
					     			@prefixpattern
					    	   or @commacnt = 1))
					begin
						select @errorfound = 0
					end
					else
					begin
						select @errorfound = 1
					end
					
				end	-- }
				else
				begin
					select @errorfound = 1
				end
				
			end	-- }
			
		end	-- }
		else 
		begin
			select @errorfound = 1
		end
		
		if @errorfound = 1
		begin
			raiserror 19537
			return (5)
		end
	
	end	-- }

	if @from_date is not NULL
	begin
		if isdate(@from_date) = 0
		begin
			-- invalid from_date
			select @from_date = "'" + @from_date + "'"
			raiserror 19123, "'@from_date'", @from_date
			return (7)
		end
	end
	
	if @to_date is not NULL
	begin

		if isdate(@to_date) = 0
		begin
			-- invalid to_date
			select @to_date = "'" + @to_date + "'"
			raiserror 19123, "'@to_date'", @to_date
			return (7)
		end
	end

	if @select_list is not NULL
	begin
		exec sp_replace_string_plus @select_list, "", "", 0
						, @select_list out

		select @select_list = lower(ltrim(rtrim(@select_list)))

		if    @select_list LIKE @wherepattern 
		   or @select_list LIKE @orderbypattern
		begin
			-- invalid SELECT list
			select @select_list = "'" + @select_list + "'"
			raiserror 19123, "'@select_list'", @select_list
			return (8)
		end
	end
	
	if @where_clause is not NULL
	begin
		exec sp_replace_string_plus @where_clause, "", "", 0
						, @where_clause out

		select @where_clause =	lower(ltrim(rtrim(@where_clause)))

		if    @where_clause NOT LIKE @wherepattern
		   or @where_clause LIKE @orderbypattern
		begin
			-- invalid WHERE clause
			select @where_clause = "'" + @where_clause + "'"
			raiserror 19123, "'@where_clause'", @where_clause
			return (8)
		end
	end
	
	if @orderby_clause is not NULL
	begin
		exec sp_replace_string_plus @orderby_clause, "", "", 0
						, @orderby_clause out

		select @orderby_clause = lower(ltrim(rtrim(@orderby_clause)))

		if    @orderby_clause NOT LIKE @orderbypattern
		   or @orderby_clause LIKE @wherepattern
		begin
			-- invalid ORDER BY clause
			select @orderby_clause = "'" + @orderby_clause + "'"
			raiserror 19123, "'@orderby_clause'", @orderby_clause
			return (8)
		end
	end
	
end	-- } 	-- }
go
go
exec sp_procxmode 'sp_spaceusage_paramcheck', 'anymode'
go
grant execute on sp_spaceusage_paramcheck to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_processusing')
begin
	drop procedure sp_spaceusage_processusing
end
go
print "Installing sp_spaceusage_processusing"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:58 2006 
*/
/*
** raiserror Messages for spaceusage_processusing [Total 0]
*/
/*
** sp_getmessage Messages for spaceusage_processusing [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
**	SP_SPACEUSAGE_PROCESSUSING
**
**	The sub-procedure that processes the USING clause that is supplied as
**	input to the sp_spaceusage procedure and extracts and returns the 
**	database name and the prefix string and the unit specifier from it. 
**	Called by sp_spaceusage.
**
**	Parameters
**		@using_clause	- The USING clause string.
**	
**	NOTE: 	The procedure assumes that the USING clause is valid and in one
**		of the following forms:
**		using[ ]+dbname[ ]+=%
**		using[ ]+prefix[ ]+=%
**		using[ ]+unit[ ]+=%
**		using[ ]+dbname[ ]+=%,prefix[ ]+=%
**		using[ ]+dbname[ ]+=%,unit[ ]+=%
**		using[ ]+prefix[ ]+=%,dbname[ ]+=%
**		using[ ]+prefix[ ]+=%,unit[ ]+=%
**		using[ ]+unit[ ]+=%,dbname[ ]+=%
**		using[ ]+unit[ ]+=%,prefix[ ]+=%
**		using[ ]+dbname[ ]+=%,prefix[ ]+=%,unit[ ]+=%
**		using[ ]+dbname[ ]+=%,unit[ ]+=%,prefix[ ]+=%
**		using[ ]+prefix[ ]+=%,dbname[ ]+=%,unit[ ]+=%
**		using[ ]+prefix[ ]+=%,unit[ ]+=%,dbname[ ]+=%
**		using[ ]+unit[ ]+=%,dbname[ ]+=%,prefix[ ]+=%
**		using[ ]+unit[ ]+=%,prefix[ ]+=%,dbname[ ]+=%
**		
**	Returns
**		- The database name.
**		- The prefix string.
**		- The unit for page counts.
{
*/
create procedure sp_spaceusage_processusing
(
	  @using_clause		varchar(350)
	, @database		varchar(30)	output
	, @prefixstring		varchar(255)	output
	, @unit			varchar(6)	output
)
as
begin	-- {	-- Procedure begins! 
	
	declare	
		  @left_substr		varchar(350)
		, @right_substr		varchar(350)
		, @rest			varchar(350)
		, @firstpart		varchar(350)
		, @secondpart		varchar(350)
		, @thirdpart		varchar(350)
		, @dbnamekeyword	varchar(7)
		, @prefixkeyword	varchar(7)
		, @unitkeyword		varchar(5)
		, @savedRsubstr		varchar(350)
		, @returnStatus		int
	
	select	  @database = NULL
		, @prefixstring = NULL
		, @unit	= NULL
		, @dbnamekeyword = "dbname"
		, @prefixkeyword = "prefix"
		, @unitkeyword   = "unit"
		
	exec @returnStatus = sp_split_string @using_clause, ",", 1
						, @firstpart out, @rest out
	
	if @returnStatus = 1	
	begin	-- {
	
		/*
		** Comma not found. It's either dbname, or prefix, or unit,
		** keyword, not a combination. 
		*/
		exec sp_split_string @using_clause, "=", 1, @left_substr out
							  , @right_substr out

		select	  @left_substr = ltrim(rtrim(lower(@left_substr)))
			, @right_substr = ltrim(rtrim(@right_substr))
			
		if @left_substr = @dbnamekeyword
			select @database = @right_substr
		else if @left_substr = @prefixkeyword
			select @prefixstring = @right_substr
		else
			select @unit = @right_substr

		return (0)
			
	end	-- }	-- End of if 
	else
	begin	-- {
	
		/* 
		** Comma found. It's a combination of 2 or more of dbanme,
		** prefix, unit keywords. 
		*/
		exec @returnStatus = sp_split_string @rest, ",", 1
					, @secondpart out, @thirdpart out
	
		if @returnStatus = 1	-- Second comma not found
		begin
			select	  @secondpart = @rest
				, @thirdpart  = NULL
		end
		
		select	  @firstpart  = ltrim(rtrim(@firstpart))
			, @secondpart = ltrim(rtrim(@secondpart))
			, @thirdpart  = ltrim(rtrim(@thirdpart))

		exec sp_split_string @firstpart, "=", 1, @left_substr out
						, @right_substr out

		select	  @left_substr = ltrim(rtrim(lower(@left_substr)))
			, @right_substr = ltrim(rtrim(@right_substr))

		if @left_substr = @dbnamekeyword
		begin	-- {
		
			select @database = @right_substr
			
			exec sp_split_string @secondpart, "=", 1
					, @left_substr out, @right_substr out
			
			select	  @left_substr=ltrim(rtrim(lower(@left_substr)))
				, @right_substr = ltrim(rtrim(@right_substr))
				
			if @left_substr = @prefixkeyword
			begin	-- {
			
				select @prefixstring = @right_substr
				
				if @thirdpart is not NULL
				begin
					exec sp_split_string @thirdpart, "=", 1
							, @left_substr out
							, @right_substr out
					
					select @unit =	
						ltrim(rtrim(@right_substr))
				end
				
			end	-- }
			else
			begin	-- {
			
				select @unit = @right_substr

				if @thirdpart is not NULL
				begin
					exec sp_split_string @thirdpart, "=", 1
							, @left_substr out
							, @right_substr out
					
					select @prefixstring = 
						ltrim(rtrim(@right_substr))
				end
				
			end	-- }
			
		end	-- }
		else if @left_substr = @prefixkeyword
		begin	-- {
		
			select @prefixstring = @right_substr
			
			exec sp_split_string @secondpart, "=", 1
					, @left_substr out, @right_substr out
			
			select	  @left_substr=ltrim(rtrim(lower(@left_substr)))
				, @right_substr = ltrim(rtrim(@right_substr))
				
			if @left_substr = @dbnamekeyword
			begin	-- {
			
				select @database = @right_substr
				
				if @thirdpart is not NULL
				begin
					exec sp_split_string @thirdpart, "=", 1
							, @left_substr out
							, @right_substr out
					
					select @unit =	
						ltrim(rtrim(@right_substr))
				end
				
			end	-- }
			else
			begin	-- {
			
				select @unit = @right_substr

				if @thirdpart is not NULL
				begin
					exec sp_split_string @thirdpart, "=", 1
							, @left_substr out
							, @right_substr out
					
					select @database = 
						ltrim(rtrim(@right_substr))
				end
				
			end	-- }
			
		end	-- }
		else
		begin	-- {
		
			select @unit = @right_substr
			
			exec sp_split_string @secondpart, "=", 1
					, @left_substr out, @right_substr out
			
			select	  @left_substr=ltrim(rtrim(lower(@left_substr)))
				, @right_substr = ltrim(rtrim(@right_substr))
				
			if @left_substr = @prefixkeyword
			begin	-- {
			
				select @prefixstring = @right_substr
				
				if @thirdpart is not NULL
				begin
					exec sp_split_string @thirdpart, "=", 1
							, @left_substr out
							, @right_substr out
					
					select @database =	
						ltrim(rtrim(@right_substr))
				end
				
			end	-- }
			else
			begin	-- {
			
				select @database = @right_substr

				if @thirdpart is not NULL
				begin
					exec sp_split_string @thirdpart, "=", 1
							, @left_substr out
							, @right_substr out
					
					select @prefixstring = 
						ltrim(rtrim(@right_substr))
				end
				
			end	-- }
			
		end	-- }

		return (0)
		
	end	-- }	-- End of else

end	--}	-- }
go
go
exec sp_procxmode 'sp_spaceusage_processusing', 'anymode'
go
grant execute on sp_spaceusage_processusing to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_runcmd')
begin
	drop procedure sp_spaceusage_runcmd
end
go
print "Installing sp_spaceusage_runcmd"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:58 2006 
*/
/*
** raiserror Messages for spaceusage_runcmd [Total 0]
*/
/*
** sp_getmessage Messages for spaceusage_runcmd [Total 1]
**
** 19538, "Command '%1!' successful."
*/
/*
** End spgenmsgs.pl output.
*/
/*
**	SP_SPACEUSAGE_RUNCMD
**	
**	Internal [only] stored procedure that will run the command passed on all
**	the tables that match the input pattern for table name and owned by user
**	name that match the input pattern for onwer name.
**
**	Parameters
**		@uname	- The owner name pattern string.
**		@tname	- The table name pattern string.
**		@command- The command to be run.
**		@verbose- If set, will print user information that the command
**			  was run successfully on the object.
**	
**	Returns
**		0 - if all goes well.
**	    other - error during execution.
{
*/
create procedure sp_spaceusage_runcmd
(
	  @uname 	varchar(255)
	, @tname 	varchar(255)
	, @command	varchar(100)
	, @verbose	bit	= 0
)
as
begin	-- { 	-- procedure begins! 

	declare	  @objname	varchar(255)
		, @ownername	varchar(30)
		, @sysstat	int
		, @sysstat2	int
		, @sqlstmt	varchar(400)
		, @retvalue	int
		, @whoami	varchar(50)
		, @msg		varchar(256)

	select @whoami = "sp_spaceusage_runcmd"

	declare objname_cur cursor for
		select	name, user_name(uid), sysstat, sysstat2
		from	sysobjects
		where	user_name(uid) like @uname
		
		    and name like @tname
		    
		    -- Eliminate some catalogs on which we know that
		    -- certain commands cannot be run. Otherwise, we'll
		    -- get unnecessary errors from UPDATE * STATISTICS
		    -- command on this table.
		    --
		    and name NOT IN (  'syslogs', 'sysgams')

		    -- Eliminate fake catalogs (e.g. sysprocesses, syslocks
		    -- and such like). 
		    --
		    and ((sysstat & 1024) != 1024)

		    -- Eliminate proxy tables 
		    and ((sysstat2 & 1024) != 1024)

		    -- Eliminate any views or other objects that user 
		    -- might have selected by "<pattern>%" specifier.
		    --
		    and type IN ('U', 'S')

	open objname_cur
	
	while (1 = 1)
	begin	-- {
	
		fetch objname_cur into @objname, @ownername, @sysstat, @sysstat2
		
		if (@@sqlstatus != 0)
			break

		select @sqlstmt = @command + " " + @ownername + "." + @objname

		exec @retvalue = sp_exec_SQL @sqlstmt, @whoami
		
		if @retvalue != 0
		begin	
			close objname_cur
			deallocate cursor objname_cur
			return (@retvalue)
		end
		
		if @verbose = 1
		begin
			exec sp_getmessage 19538, @msg out
			print @msg, @sqlstmt
		end
	
	end	-- }	-- End of while

	close objname_cur

	deallocate cursor objname_cur

end	-- } 	-- }
go
go
exec sp_procxmode 'sp_spaceusage_runcmd', 'anymode'
go
grant execute on sp_spaceusage_runcmd to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_showhelp_display')
begin
	drop procedure sp_spaceusage_showhelp_display
end
go
print "Installing sp_spaceusage_showhelp_display"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_showhelp_report')
begin
	drop procedure sp_spaceusage_showhelp_report
end
go
print "Installing sp_spaceusage_showhelp_report"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_showhelp_archive')
begin
	drop procedure sp_spaceusage_showhelp_archive
end
go
print "Installing sp_spaceusage_showhelp_archive"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_showhelp_all')
begin
	drop procedure sp_spaceusage_showhelp_all
end
go
print "Installing sp_spaceusage_showhelp_all"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_showhelp')
begin
	drop procedure sp_spaceusage_showhelp
end
go
print "Installing sp_spaceusage_showhelp"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:59 2006 
*/
/*
** raiserror Messages for spaceusage_showhelp [Total 1]
**
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
*/
/*
** sp_getmessage Messages for spaceusage_showhelp [Total 35]
**
** 18954, "Usage:"
** 19539, "For more information, use:"
** 19540, "For entity '%1!':"
** 19541, "Examples:"
** 19542, "%1!Display %2!information in '%3!' for"
** 19543, "%1!Display %2!information in '%3!' for any index starting with '%4!' on"
** 19544, "%1!Display summary information in '%2!' for table '%3!' owned by you"
** 19545, "%1!Display summary information in '%2!' for all index on table '%3!' owned by you"
** 19546, "%1!any table starting with '%2!' owned by %3!"
** 19547, "%1!Run '%2!' on each."
** 19548, "%1!where %2!"
** 19549, "%1!where %2!%3!ordered by %4! descending"
** 19550, "%1!any table starting with '%2!' owned by anyone"
** 19551, "%1!Report %2!information in '%3!' for"
** 19552, "%1!Report %2!information in '%3!' for any index starting with '%4!' on"
** 19553, "%1!from archive table '%2!' in current database"
** 19554, "%1!from archive table '%2!' in '%3!' database"
** 19555, "%1!and dated between '%2!' and %3!"
** 19556, "%1!and dated before %2!"
** 19557, "%1!Report summary information in '%2!' for table '%3!' owned by you"
** 19558, "%1!Report summary information in '%2!' for all index on table '%3!' owned by you"
** 19559, "%1!Archive %2!information in '%3!' for"
** 19560, "%1!Archive %2!information in '%3!' for any index starting with '%4!' on"
** 19561, "%1!into table '%2!' in current database"
** 19562, "%1!into table '%2!' in '%3!' database"
** 19563, "%1!Print usage help on the display action"
** 19564, "%1!Print usage help on the report action for the index entity"
** 19565, "The USING clause can be used with the action keyword (except 'help') as follows:"
** 19566, "%1!for 'display' and 'display summary' action"
** 19567, "%1!for 'archive', 'report' and 'report summary' action"
** 19589, "Display the space usage information for an entity in the current database."
** 19590, "Report from an archive table the space usage information for an entity in the current database."
** 19591, "Archive into an archive table the space usage information for an entity in the current database."
** 19592, "The USING clause may be used to specify the unit, the archive database name, and the prefix string for the archive table."
** 19593, "By default, unit is assumed 'KB', current database is the archive database and no prefix string is assumed."
*/
/*
** End spgenmsgs.pl output.
*/
/*
**	SP_SPACEUSAGE_SHOWHELP_DISPLAY
**
**	The sub-procedure to print "display" action specific help/usage 
**	information for the sp_spaceusage procedure. Called by sp_spaceusage.
**
**	Parameters
**		@helpentity	- Entity type on which help is sought.
**		@verbose	- Information mode is verbose or terse.
**
**	Returns 
**		0 - always. Prints the usage information or error messge for
**		    invalid action/entity.
{
*/
create procedure sp_spaceusage_showhelp_display
(
	  @helpentity	varchar(12) 
	, @verbose	bit
)
as
begin	-- {

	declare	  @pattern		varchar(50)
		, @pattern4table	varchar(50)
		, @pattern4index	varchar(50)
		, @msg			varchar(256)

	select	  @helpentity = lower(ltrim(rtrim(@helpentity)))
		, @pattern4index = "nc%"
		, @pattern4table = "my%"
		
	if 	@helpentity is NULL 
	     or @helpentity not in ("index", "table", "tranlog") 
	     or @verbose = 1
	     
	begin	-- {

		exec	sp_getmessage 19589, @msg out
		print	@msg
		print	""

		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'display', {'table'|'index'}, <name>"
		print	"			[,<select_list> [,<where_clause> [,<order_by> [,<command>]]]]"
		print 	""
		print 	"sp_spaceusage 'display summary', {'table'|'index'}, <name>"
		print	"			[,<where_clause> [,<order_by> [,<command>]]]"
		print 	""
		print 	"sp_spaceusage 'display', 'tranlog' [,{'syslogs'|NULL}"
		print	"			[,<select_list> [,<where_clause> [,<order_by>]]]]"
		print 	""
		
		exec	sp_getmessage 19539, @msg out
		print	@msg
		
		print	"sp_spaceusage 'help', 'display', 'table'"
		print	"sp_spaceusage 'help', 'display', 'index'"		
		print	"sp_spaceusage 'help', 'display', 'tranlog'"		
		print 	""
		print 	""
		
	end	-- }
	
	select @pattern = case @helpentity
				when "index" 
				then @pattern4table + "." + @pattern4index
				else @pattern4table
			  end
				  
	if @helpentity in ( "table" , "index" )
	begin	-- {
		
		exec	sp_getmessage 19540, @msg out
		print	@msg, @helpentity
		
		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'display [using unit=<unit>]', '%1!', <name>"
				, @helpentity
		print	"		[,<select_list> [,<where_clause> [,<order_by> [,<command>]]]]"
		print	""
		print 	"sp_spaceusage 'display summary [using unit=<unit>]', '%1!', <name>"
				, @helpentity	
		print	"		[,<where_clause> [,<order_by> [,command]]]"
		print 	""

		exec	sp_getmessage 19541, @msg out
		print	@msg
		print 	""
		
		if @helpentity = "table"
		begin
			exec	sp_getmessage 19542, @msg out
		end
		else
		begin
			exec	sp_getmessage 19543, @msg out
		end
		print	@msg, "  -- ", NULL, "KB", "nc"
		
		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'user1'"
		
		print	"  -- "
		print 	"  sp_spaceusage 'display', '%1!', 'user1.%2!'"
			, @helpentity
			, @pattern
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19542, @msg out
		end
		else
		begin
			exec	sp_getmessage 19543, @msg out
		end	
		print	@msg, "  -- ", NULL, "MB", "nc"
		
		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'user1'"
		
		exec	sp_getmessage 19547, @msg out
		print	@msg, "  -- ", "update table statistics"
		
		print	"  -- "
		print 	"  sp_spaceusage 'display using unit=MB', '%1!', 'user1.%2!', NULL, NULL, NULL,"
				, @helpentity, @pattern
		print	"		 'update table statistics'"
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19542, @msg out
		end
		else 
		begin
			exec	sp_getmessage 19543, @msg out
		end
		print	@msg, "  -- ", "ALL ", "pages", "nc"		
				
		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'dbo'"

		exec	sp_getmessage 19549, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40", ", "
			    , "PctBloatRsvdPages"
			    
		print	"  -- "
		print 	"  sp_spaceusage 'display using unit=pages', '%1!', 'dbo.%2!', '*',"
				, @helpentity, @pattern
		print	"		 'where PctBloatRsvdPages > 40','order by PctBloatRsvdPages desc'"
		
		print 	""
		
		if @helpentity = "table"
		begin
			exec	sp_getmessage 19542, @msg out
		end
		else
		begin
			exec	sp_getmessage 19543, @msg out
		end
		print	@msg, "  -- ", "'Id, IndId, PtnId, PctBloatRsvdPages' "
			    , "KB", "nc"

		exec	sp_getmessage 19550, @msg out
		print	@msg, "  -- ", "my"
		
		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40"
		
		select @pattern = "%." + @pattern

		print	"  -- "
		print 	"  sp_spaceusage 'display using unit=KB', '%1!', '%2!',"
				, @helpentity, @pattern
		print	"		 'Id,IndId,PtnId,PctBloatRsvdPages', 'where PctBloatRsvdPages > 40'"

		print 	""

		select @pattern = case @helpentity
					when "index" 
					then "mytable.%"
					else "mytable"
				  end
				  
		if @helpentity = "table"
		begin
			exec	sp_getmessage 19544, @msg out
		end
		else
		begin
			exec	sp_getmessage 19545, @msg out
		end
		print	@msg, "  -- ", "KB", "mytable"

		exec	sp_getmessage 19549, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40", ", "
			    , "PctBloatRsvdPages"
			    
		print	"  -- "
		print 	"  sp_spaceusage 'display summary', '%1!', '%2!',"
				, @helpentity, @pattern
		print	"		 'where PctBloatRsvdPages > 40', 'order by PctBloatRsvdPages desc'"
		
		print 	""

	end	-- }
	else if @helpentity = "tranlog"
	begin	-- {
	
		exec	sp_getmessage 19540, @msg out
		print	@msg, @helpentity
		
		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'display [using unit=<unit>]', 'tranlog' [,{'syslogs'|NULL}"
		print	"		[,<select_list> [,<where_clause> [,<order_by>]]]]"
		print	""

		exec	sp_getmessage 19541, @msg out
		print	@msg
		print 	""

		exec	sp_getmessage 19542, @msg out		
		select	@msg = @msg + " transaction log"
		print	@msg, "  -- ", NULL, "KB"
		
		print	"  -- "
		print 	"  sp_spaceusage 'display', 'tranlog', 'syslogs'"
		print	""

		exec	sp_getmessage 19542, @msg out		
		select	@msg = @msg + " transaction log"
		print	@msg, "  -- ", "ALL ", "pages"
				
		exec	sp_getmessage 19549, @msg out
		print	@msg, "  -- ", "IsLogFull = 1", ", "
			    , "TotalPages"
			    
		print	"  -- "
		print 	"  sp_spaceusage 'display using unit=pages', 'tranlog', NULL, '*',"
		print	"		 'where IsLogFull = 1','order by TotalPages desc'"
		
		print 	""

		exec	sp_getmessage 19542, @msg out		
		select	@msg = @msg + " transaction log"
		print	@msg, "  -- ", "'DBName, Id, TotalPages, UsedPages, FreePages' "
			    , "MB"

		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "TotalPages > 2"
		
		print	"  -- "
		print 	"  sp_spaceusage 'display using unit=MB', 'tranlog', NULL,"
		print	"		 'DBName,Id,TotalPages,UsedPages,FreePages', 'where TotalPages > 2'"

		print 	""

	end	-- }
	
	return (0)
	
end	-- }	-- }
go

/*
**	SP_SPACEUSAGE_SHOWHELP_REPORT
**
**	The sub-procedure to print "report" action specific help/usage 
**	information for the sp_spaceusage procedure. Called by sp_spaceusage.
**
**	Parameters
**		@helpentity	- Entity type on which help is sought.
**		@verbose	- Information mode is verbose or terse.
**
**	Returns 
**		0 - always. Prints the usage information or error messge for
**		    invalid action/entity.
{
*/
create procedure sp_spaceusage_showhelp_report
(
	  @helpentity	varchar(12) 
	, @verbose	bit
)
as
begin	-- {
	
	declare	  @pattern		varchar(50)
		, @pattern4table	varchar(50)
		, @pattern4index	varchar(50)
		, @msg			varchar(256)
	
	select	  @helpentity = lower(ltrim(rtrim(@helpentity)))
		, @pattern4index = "nc%"
		, @pattern4table = "my%"
		
	if 	@helpentity is NULL 
	     or @helpentity not in ("index", "table", "tranlog") 
	     or @verbose = 1
	begin	-- {

		exec 	sp_getmessage 19590, @msg output
		print 	@msg
		print	""

		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'report', {'table'|'index'}, <name>"
		print	"		[,<select_list> [,<where_clause> [,<order_by> [,<from_date> [,<to_date>]]]]]"
		print	""
		print 	"sp_spaceusage 'report summary', {'table'|'index'}, <name>"
		print	"		[,<where_clause> [,<order_by> [,<from_date> [,<to_date>]]]]"
		print 	""
		print 	"sp_spaceusage 'report', 'tranlog' [,{'syslogs'|NULL}"
		print	"		[,<select_list> [,<where_clause> [,<order_by> [,<from_date> [,<to_date>]]]]]]"
		print 	""
		
		exec	sp_getmessage 19539, @msg out
		print	@msg
		
		print	"sp_spaceusage 'help', 'report', 'table'"
		print	"sp_spaceusage 'help', 'report', 'index'"
		print	"sp_spaceusage 'help', 'report', 'tranlog'"
		print 	""
		print 	""

	end	-- }

	select @pattern = case @helpentity
				when "index" 
				then @pattern4table + "." + @pattern4index
				else @pattern4table
			  end
				  
	if @helpentity in ( "table" , "index" )
	begin	-- {
		
		exec	sp_getmessage 19540, @msg out
		print	@msg, @helpentity
		
		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'report [using {<using_item>[,<using_item>]...}]', '%1!', <name>"
				, @helpentity
		print	"		[,<select_list> [,<where_clause> [,<order_by> [,<from_date> [,<to_date>]]]]]"
		print	""
		print 	"sp_spaceusage 'report summary [using {<using_item>[,<using_item>]...}]', '%1!', <name>"
				, @helpentity
		print	"		[,<where_clause> [,<order_by> [,<from_date> [,<to_date>]]]]"
		print 	""
		
		print	"%1!<using_item> :: { unit={KB|MB|GB|PAGES} | dbname=<db> | prefix=<string> }"
				, "	"
		print 	""
		
		exec	sp_getmessage 19541, @msg out
		print	@msg
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19551, @msg out
		end
		else
		begin
			exec	sp_getmessage 19552, @msg out
		end
		print	@msg, "  -- ", NULL, "MB", "nc"

		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'user1'"

		exec	sp_getmessage 19553, @msg out
		print	@msg, "  -- ", "spaceusage_object"
		
		print	"  -- "
		print 	"  sp_spaceusage 'report using unit=MB', '%1!', 'user1.%2!'"
				, @helpentity, @pattern
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19551, @msg out
		end
		else
		begin
			exec	sp_getmessage 19552, @msg out
		end
		print	@msg, "  -- ", NULL, "KB", "nc"

		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'user1'"

		exec	sp_getmessage 19554, @msg out
		print	@msg, "  -- ", "spaceusage_object", "mydb"
		
		exec	sp_getmessage 19555, @msg out
		print	@msg, "  -- ", "Aug 30 2005  6:21AM", "'today'"
		
		print	"  -- "
		print 	"  sp_spaceusage 'report using dbname=mydb', '%1!', 'user1.%2!', NULL, NULL,"
				, @helpentity, @pattern
		print	"		 NULL, 'Aug 30 2005  6:21AM'"
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19551, @msg out
		end
		else
		begin
			exec	sp_getmessage 19552, @msg out
		end
		print	@msg, "  -- ", "ALL ", "KB", "nc"

		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'dbo'"

		exec	sp_getmessage 19553, @msg out
		print	@msg, "  -- ", "spaceusage_object"
		
		exec	sp_getmessage 19556, @msg out
		print	@msg, "  -- ", "'Aug 30 2005  6:21AM'"
		
		exec	sp_getmessage 19549, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40", ", "
			    , "PctBloatRsvdPages"
			    
		print	"  -- "
		print 	"  sp_spaceusage 'report', '%1!', 'dbo.%2!', '*',"
				, @helpentity, @pattern
		print	"		'where PctBloatRsvdPages > 40','order by PctBloatRsvdPages desc',"
		print	"		 NULL, 'Aug 30 2005  6:21AM'"
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19551, @msg out
		end
		else
		begin
			exec	sp_getmessage 19552, @msg out
		end
		print	@msg, "  -- ", "'Id, IndId, PtnId, PctBloatRsvdPages' "
			    , "KB", "nc"
			    
		exec	sp_getmessage 19550, @msg out
		print	@msg, "  -- ", "my"
		
		exec	sp_getmessage 19553, @msg out
		print	@msg, "  -- ", "weekly_spaceusage_object"
		
		exec	sp_getmessage 19555, @msg out
		print	@msg, "  -- ", "Aug 30 2005 6:21AM"
			    , "'Aug 30 2006 6:21AM'"
			    
		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40" 
		
		select @pattern = "%." + @pattern

		print	"  -- "
		print 	"  sp_spaceusage 'report using prefix=weekly_', '%1!', '%2!',"
				, @helpentity, @pattern
		print	"		 'Id,IndId,PtnId,PctBloatRsvdPages', 'where PctBloatRsvdPages>40',"
		print	"		 NULL, 'Aug 30 2005 6:21AM', 'Aug 30 2006  6:21AM'"

		print 	""
	
		select @pattern = case @helpentity
					when "index" 
					then "mytable.%"
					else "mytable"
				  end
				  
		if @helpentity = "table"
		begin
			exec	sp_getmessage 19557, @msg out
		end
		else
		begin
			exec	sp_getmessage 19558, @msg out
		end
		print	@msg, "  -- ", "KB", "mytable"
		
		exec	sp_getmessage 19554, @msg out
		print	@msg, "  -- ", "weekly_spaceusage_object", "mydb"
		
		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40"
		
		print	"  -- "			
		print 	"  sp_spaceusage 'report summary using dbname=mydb,prefix=weekly_', '%1!', '%2!',"
				, @helpentity, @pattern
		print	"		 'where PctBloatRsvdPages > 40'"
		
		print 	""
		
	end	-- }
	if @helpentity = "tranlog"
	begin	-- {
		
		exec	sp_getmessage 19540, @msg out
		print	@msg, @helpentity
		
		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'report [using {<using_item>[,<using_item>]...}]', 'tranlog' [,{'syslogs'|NULL}"
		print	"		[,<select_list> [,<where_clause> [,<order_by> [,<from_date> [,<to_date>]]]]]]"
		print	""
		
		print	"%1!<using_item> :: { unit={KB|MB|GB|PAGES} | dbname=<db> | prefix=<string> }"
				, "	"
		print 	""
		
		exec	sp_getmessage 19541, @msg out
		print	@msg
		print 	""

		exec	sp_getmessage 19551, @msg out
		select 	@msg = @msg + " transaction log"
		print	@msg, "  -- ", NULL, "MB"

		exec	sp_getmessage 19553, @msg out
		print	@msg, "  -- ", "spaceusage_tranlog"
		
		print	"  -- "
		print 	"  sp_spaceusage 'report using unit=MB', 'tranlog', 'syslogs'"
		print 	""

		exec	sp_getmessage 19551, @msg out
		select 	@msg = @msg + " transaction log"
		print	@msg, "  -- ", NULL, "KB"

		exec	sp_getmessage 19554, @msg out
		print	@msg, "  -- ", "spaceusage_tranlog", "mydb"
		
		exec	sp_getmessage 19555, @msg out
		print	@msg, "  -- ", "Aug 30 2005  6:21AM", "'today'"
		
		print	"  -- "
		print 	"  sp_spaceusage 'report using dbname=mydb', 'tranlog', NULL, NULL,"
		print	"		 NULL, 'Aug 30 2005  6:21AM'"
		
		print 	""

		exec	sp_getmessage 19551, @msg out
		select 	@msg = @msg + " transaction log"
		print	@msg, "  -- ", "ALL ", "KB", "nc"

		exec	sp_getmessage 19553, @msg out
		print	@msg, "  -- ", "spaceusage_tranlog"
		
		exec	sp_getmessage 19556, @msg out
		print	@msg, "  -- ", "'Aug 30 2005  6:21AM'"
		
		exec	sp_getmessage 19549, @msg out
		print	@msg, "  -- ", "IsLogFull = 1", ", "
			    , "TotalPages"
			    
		print	"  -- "
		print 	"  sp_spaceusage 'report', 'tranlog', NULL, '*',"
		print	"		'where IsLogFull = 1','order by TotalPages desc',"
		print	"		 NULL, 'Aug 30 2005  6:21AM'"
		
		print 	""

		exec	sp_getmessage 19551, @msg out
		select 	@msg = @msg + " transaction log"
		print	@msg, "  -- ", "'DBName, Id, TotalPages, UsedPages, FreePages' "
			    , "MB"
			    
		exec	sp_getmessage 19553, @msg out
		print	@msg, "  -- ", "weekly_spaceusage_tranlog"
		
		exec	sp_getmessage 19555, @msg out
		print	@msg, "  -- ", "Aug 30 2005 6:21AM"
			    , "'Aug 30 2006 6:21AM'"
			    
		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "TotalPages > 2" 
		
		print	"  -- "
		print 	"  sp_spaceusage 'report using unit=MB,prefix=weekly_', 'tranlog', NULL,"
		print	"		 'DBName,Id,TotalPages,UsedPages,FreePages', 'where TotalPages>2',"
		print	"		 NULL, 'Aug 30 2005 6:21AM', 'Aug 30 2006  6:21AM'"

		print 	""
	
	end	-- }

	return (0)
	
end	-- }	-- }
go

/*
**	SP_SPACEUSAGE_SHOWHELP_ARCHIVE
**
**	The sub-procedure to print "archive" action specific help/usage 
**	information for the sp_spaceusage procedure. Called by sp_spaceusage.
**
**	Parameters
**		@helpentity	- Entity type on which help is sought.
**		@verbose	- Information mode is verbose or terse.
**
**	Returns 
**		0 - always. Prints the usage information or error messge for
**		    invalid action/entity.
{
*/
create procedure sp_spaceusage_showhelp_archive
(
	  @helpentity	varchar(12) 
	, @verbose	bit
)
as
begin	-- {
	
	declare	  @pattern		varchar(50)
		, @pattern4table	varchar(50)
		, @pattern4index	varchar(50)
		, @msg			varchar(256)

	select	  @helpentity = lower(ltrim(rtrim(@helpentity)))
		, @pattern4index = "nc%"
		, @pattern4table = "my%"
		
	if 	@helpentity is NULL 
	     or @helpentity not in ("index", "table", "tranlog") 
	     or @verbose = 1
	begin	-- {

		exec 	sp_getmessage 19591, @msg output
		print 	@msg
		print	""

		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'archive', {'table'|'index'}, <name>"
		print	"		[,<where_clause> [,<command>]]"
		print 	""
		print 	"sp_spaceusage 'archive', 'tranlog' [,{'syslogs'|NULL}"
		print	"		[,<where_clause>]]"
		print 	""
		
		exec	sp_getmessage 19539, @msg out
		print	@msg
		
		print	"sp_spaceusage 'help', 'archive', 'table'"
		print	"sp_spaceusage 'help', 'archive', 'index'"
		print	"sp_spaceusage 'help', 'archive', 'tranlog'"
		print 	""
		print 	""

	end	-- }

	select @pattern = case @helpentity
				when "index" 
				then @pattern4table + "." + @pattern4index
				else @pattern4table
			  end
				  
	if @helpentity in ( "table" , "index" )
	begin	-- {
		
		exec	sp_getmessage 19540, @msg out
		print	@msg, @helpentity
		
		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'archive [using {<using_item>[,<using_item>]...} ]', '%1!', <name>"
				, @helpentity
		print	"		[[,where_clause] [,command]"
		print 	""
		print	"%1!<using_item> :: { unit={KB|MB|GB|PAGES} | dbname=<db> | prefix=<string> }"
				, "	"
		print 	""
		
		exec	sp_getmessage 19541, @msg out
		print	@msg
		print 	""
	
		if @helpentity = "table"
		begin
			exec	sp_getmessage 19559, @msg out
		end
		else
		begin
			exec	sp_getmessage 19560, @msg out
		end
		print	@msg, "  -- ", NULL, "MB", "nc"

		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'user1'"

		exec	sp_getmessage 19561, @msg out
		print	@msg, "  -- ", "spaceusage_object"

		print	"  -- "			
		print 	"  sp_spaceusage 'archive using unit=MB', '%1!', 'user1.%2!'"
				, @helpentity, @pattern
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19559, @msg out
		end
		else
		begin
			exec	sp_getmessage 19560, @msg out
		end
		print	@msg, "  -- ", NULL, "KB", "nc"

		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'user1'"

		exec	sp_getmessage 19562, @msg out
		print	@msg, "  -- ", "spaceusage_object", "mydb"

		exec	sp_getmessage 19547, @msg out
		print	@msg, "  -- ", "update table statistics"
		
		print	"  -- "			
		print 	"  sp_spaceusage 'archive using dbname=mydb', '%1!', 'user1.%2!', NULL,"
				, @helpentity, @pattern
		print	"		 'update table statistics'"
		
		print 	""

		if @helpentity = "table"
		begin
			exec	sp_getmessage 19559, @msg out
		end
		else
		begin
			exec	sp_getmessage 19560, @msg out
		end
		print	@msg, "  -- ", NULL, "KB", "nc"
		
		exec	sp_getmessage 19546, @msg out
		print	@msg, "  -- ", "my", "'dbo'"

		exec	sp_getmessage 19561, @msg out
		print	@msg, "  -- ", "dbo_gt40pct_spaceusage_object"

		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40"
		
		print	"  -- "			
		print 	"  sp_spaceusage 'archive using prefix=dbo_gt40pct_', '%1!', 'dbo.%2!',"
				, @helpentity, @pattern
		print	"		 'where PctBloatRsvdPages > 40'"
		
		print 	""
		
		if @helpentity = "table"
		begin
			exec	sp_getmessage 19559, @msg out
		end
		else
		begin
			exec	sp_getmessage 19560, @msg out
		end
		print	@msg, "  -- ", NULL, "KB", "nc"
		
		exec	sp_getmessage 19550, @msg out
		print	@msg, "  -- ", "my"

		exec	sp_getmessage 19562, @msg out
		print	@msg, "  -- ", "gt100pct_spaceusage_object", "mydb"

		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "PctBloatRsvdPages > 40"
		
		exec	sp_getmessage 19547, @msg out
		print	@msg, "  -- ", "update table statistics"
			
		select @pattern = "%." + @pattern

		print	"  -- "			
		print 	"  sp_spaceusage 'archive using dbname=mydb,prefix=all_gt100pct_', '%1!', '%2!',"
				, @helpentity, @pattern
		print	"		 'where PctBloatRsvdPages > 100', 'update table statistics'"

		print 	""
	
	end	-- }
	else if @helpentity = "tranlog"
	begin 	-- {
	
		exec	sp_getmessage 19540, @msg out
		print	@msg, @helpentity
		
		exec 	sp_getmessage 18954, @msg output
		print 	@msg
		
		print 	"sp_spaceusage 'archive [using {<using_item>[,<using_item>]...} ]', 'tranlog' [,{'syslogs'|NULL}"
		print	"		[,where_clause]]"
		print 	""
		print	"%1!<using_item> :: { unit={KB|MB|GB|PAGES} | dbname=<db> | prefix=<string> }"
				, "	"
		print 	""
		
		exec	sp_getmessage 19541, @msg out
		print	@msg
		print 	""
	
		exec	sp_getmessage 19559, @msg out
		select	@msg = @msg + " transaction log"
		print	@msg, "  -- ", NULL, "MB"

		exec	sp_getmessage 19561, @msg out
		print	@msg, "  -- ", "spaceusage_tranlog"

		print	"  -- "			
		print 	"  sp_spaceusage 'archive using unit=MB', 'tranlog', 'syslogs'"
		
		print 	""

		exec	sp_getmessage 19559, @msg out
		select	@msg = @msg + " transaction log"
		print	@msg, "  -- ", NULL, "KB"
		
		exec	sp_getmessage 19561, @msg out
		print	@msg, "  -- ", "canupgrd_spaceusage_tranlog"

		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "HasSpaceForUpgrade = 1"
		
		print	"  -- "			
		print 	"  sp_spaceusage 'archive using prefix=canupgrd_', 'tranlog', NULL,"
		print	"		 'where HasSpaceForUpgrade = 1'"
		
		print 	""
		
		exec	sp_getmessage 19559, @msg out
		select	@msg = @msg + " transaction log"
		print	@msg, "  -- ", NULL, "KB"
		
		exec	sp_getmessage 19562, @msg out
		print	@msg, "  -- ", "mld_spaceusage_tranlog", "mydb"

		exec	sp_getmessage 19548, @msg out
		print	@msg, "  -- ", "IsMLD = 1"
		
		print	"  -- "			
		print 	"  sp_spaceusage 'archive using dbname=mydb,prefix=mld_', 'tranlog', NULL,"
		print	"		 'where IsMLD = 1'"

		print 	""
	
	end	-- }
	
	return (0)
	
end	-- }	-- }
go

/*
**	SP_SPACEUSAGE_SHOWHELP_ALL
**
**	The sub-procedure to print help/usage information for all actions and
**	entitites supported by the sp_spaceusage procedure. Called by 
**	sp_spaceusage_showhelp.
**
**	Parameters
**		@verbose	- Information mode is verbose or terse.
**
**	Returns 
**		0 - always. Prints the usage information or error messge for
**		    invalid action/entity.
{
*/
create procedure sp_spaceusage_showhelp_all
(
	@verbose	bit
)
as
begin	-- {
	
	if @verbose = 1
	begin
		exec sp_spaceusage_showhelp_display "table",   1
		exec sp_spaceusage_showhelp_display "index",   0
		exec sp_spaceusage_showhelp_display "tranlog", 0
		exec sp_spaceusage_showhelp_archive "table",   1
		exec sp_spaceusage_showhelp_archive "index",   0
		exec sp_spaceusage_showhelp_archive "tranlog", 0
		exec sp_spaceusage_showhelp_report  "table",   1
		exec sp_spaceusage_showhelp_report  "index",   0
		exec sp_spaceusage_showhelp_report  "tranlog", 0
	end
	else
	begin
		exec sp_spaceusage_showhelp_display NULL, 0
		exec sp_spaceusage_showhelp_archive NULL, 0
		exec sp_spaceusage_showhelp_report  NULL, 0
	end
	
	return (0)
	
end	-- }	-- }
go

/*
**	SP_SPACEUSAGE_SHOWHELP
**
**	The sub-procedure to print help/usage iformation for the sp_spaceusage
**	procedure. Called by sp_spaceusage.
**
**	Parameters
**		@helpaction 	- Action on which help is sought.
**		@helpentity	- Entity type on which help is sought.
**		@validactions	- The string containing all valid actions.
**		@validentities	- The string containing all valid entities.
**
**	Returns 
**		0 - always. Prints the usage information or error messge for
**		    invalid action/entity.
{
*/
create procedure sp_spaceusage_showhelp
(
	  @helpaction		varchar(20) 
	, @helpentity		varchar(12) 
	, @validactions		varchar(75)
	, @validentities	varchar(30)
)
as
begin	-- { 	-- procedure begins! 

	declare	  @procToCall	varchar(50)
		, @msg		varchar(256)

	select 	  @validactions = @validactions + ", 'all'"
		, @helpaction = ltrim(rtrim(@helpaction))
		, @helpentity = ltrim(rtrim(@helpentity))
		
	if 	@helpaction is NULL 
	     or lower(@helpaction) in ( "all", "help" )
	begin 	-- { generic help
	
		exec 	sp_getmessage 18954, @msg output
		print 	@msg		
		print	"sp_spaceusage 'help' [, 'all' ]" 
		print	"sp_spaceusage 'help' [, {'display'|'display summary'|'report'|'report summary'|'archive'} [, {'table'|'index'|'tranlog'}]]" 
		print 	""	
		
		exec	sp_getmessage 19541, @msg out
		print	@msg
		
		exec	sp_getmessage 19563, @msg out
		print	@msg, "  -- "
		
		print 	"  sp_spaceusage 'help', 'display'"
		print 	""
		
		exec	sp_getmessage 19564, @msg out
		print	@msg, "  -- "
		
		print 	"  sp_spaceusage 'help', 'report', 'index'"
		print 	""

		if lower(@helpaction) = "help"
			return (0)

		exec 	sp_getmessage 18954, @msg output
		print 	@msg		
		
		print	"sp_spaceusage {'display'|'display summary'|'report'|'report summary'|'archive'}, {'table'|'index'} [,... ]" 
		print 	""	
		print	"sp_spaceusage {'display'|'report'|'archive'}, 'tranlog' [,{'syslogs'|NULL} [,... ]]" 
		print 	""	
	
		exec 	sp_getmessage 19592, @msg output
		print 	@msg
		
		exec 	sp_getmessage 19593, @msg output
		print 	@msg

		exec	sp_getmessage 19565, @msg out
		print	@msg

		print 	""	
		print	"using { <using_item> [, <using_item> ] ... }"
		print 	""	
		
		exec	sp_getmessage 19566, @msg out
		print	@msg, "  -- "

		print	"%1!<using_item> :: { unit={KB|MB|GB|PAGES} }"
				, "	"
		print 	""
		
		exec	sp_getmessage 19567, @msg out
		print	@msg, "  -- "

		print	"%1!<using_item> :: { unit={KB|MB|GB|PAGES} | dbname=<db> | prefix=<string> }" 
				, "	"
		print 	""
		print 	""

		if lower(ltrim(rtrim(@helpaction))) = "all"
			exec sp_spaceusage_showhelp_all 1 
		else 
			exec sp_spaceusage_showhelp_all 0
		
		return (0)
		
	end 	-- } generic help done!
	
	select @procToCall = "sp_spaceusage_showhelp_" 
	
	if lower(@helpaction) in ("display", "display summary")
	begin
		select @procToCall = @procToCall + "display" 
	end
	else if lower(@helpaction) = "archive"
	begin
		select @procToCall = @procToCall + "archive" 
	end
	else if lower(@helpaction) in ("report", "report summary")
	begin
		select @procToCall = @procToCall + "report" 
	end
	else
	begin
		raiserror 19194, @helpaction, @validactions
		return (1)
	end

	if 	@helpentity is not NULL
	    and	lower(@helpentity) not in ( "table", "index", "tranlog" )
	begin
		raiserror 19194, @helpentity, @validentities
		return (2)
	end
	
	exec @procToCall @helpentity, 0

end	-- }	-- }
go

go
exec sp_procxmode 'sp_spaceusage_showhelp_display', 'anymode'
go
grant execute on sp_spaceusage_showhelp_display to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_showhelp_report', 'anymode'
go
grant execute on sp_spaceusage_showhelp_report to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_showhelp_archive', 'anymode'
go
grant execute on sp_spaceusage_showhelp_archive to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_showhelp_all', 'anymode'
go
grant execute on sp_spaceusage_showhelp_all to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_showhelp', 'anymode'
go
grant execute on sp_spaceusage_showhelp to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_cnvtounit')
begin
	drop procedure sp_spaceusage_cnvtounit
end
go
print "Installing sp_spaceusage_cnvtounit"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:57 2006 
*/
/*
** raiserror Messages for spaceusage_cnvtounit [Total 0]
*/
/*
** sp_getmessage Messages for spaceusage_cnvtounit [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
**	SP_SPACEUSAGE_CNVTOUNIT
**
**	The sub-procedure takes as input a table name and a unit specifier and
**	computes the value for the page count columns in the input table into
**	the specified units, from the corresponding raw page count columns in
**	the input table.
**	
**	Parameters
**		@unit	- A string that gives the unit into which to convert.
**			  Currently, only "KB", "MB", "GB" or "PAGES" is 
**			  supported.
**		@tabname - The table for which to do the computation.
** 	
**	Returns
**		0 - if all goes well
**		1 - if the table name is invalid
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_cnvtounit
(
	  @unit		varchar(6)
	, @tabname	varchar(255)
)
as
begin	-- {

	declare   @factorBy		float
		, @factorBy_str		varchar(20)
		, @bytesPerUnit		float		
		, @sqlstmt		varchar(650)
		, @objecttmptab		varchar(20)
		, @tranlogtmptab	varchar(20)
		, @whoami		varchar(50)
		, @returnStatus		int

	select    @unit 	 = upper(ltrim(rtrim(@unit)))
		, @objecttmptab	 = "#spaceusageinfo"
		, @tranlogtmptab = "#syslogsinfo"
		, @whoami	 = "sp_spaceusage_cnvtounit"
	
	-- The proc assumes that only valid unit specifier is supplied through
	-- the @unit paramater and this has been checked/verfied before calling
	-- this proc. It, however, tries to not do anything in case unit
	-- specifier is not supported.
	--
	-- NOTE: If higher units are added, then the @bytesPerUnit variable
	-- might overflow. For example, "TB". 
	--
	select @bytesPerUnit = 	case @unit
					when "KB" then 1024.0
					when "MB" then 1024.0 * 1024.0
					when "GB" then 1024.0 * 1024.0 * 1024.0
					when "PAGES" then 1.0
					else @@maxpagesize
				end
				
	select @factorBy = case @unit
				when "PAGES" then 1.0
				else @@maxpagesize/@bytesPerUnit
			   end

	select @factorBy_str = convert(varchar, @factorBy)

	select @sqlstmt = "UPDATE " + @tabname + " SET " 

	if lower(ltrim(rtrim(@tabname))) = @objecttmptab
	begin	-- {

		select @sqlstmt = @sqlstmt + " DataPages=DataPageCount*" 
						+ @factorBy_str
					   + ", UsedPages=UsedPageCount*"
					 	+ @factorBy_str
					   + ", RsvdPages=RsvdPageCount*"
					 	+ @factorBy_str
					   + ", EmptyPages=EmptyPageCount*"
					 	+ @factorBy_str
					   + ", LeafPages=LeafPageCount*"
					 	+ @factorBy_str
					   + ", ExpDataPages=ExpDataPageCount*"
					 	+ @factorBy_str
					   + ", ExpUsedPages=ExpUsedPageCount*"
					 	+ @factorBy_str
					   + ", ExpRsvdPages=ExpRsvdPageCount*"
					 	+ @factorBy_str
					   + ", ExpLeafPages=ExpLeafPageCount*"
					 	+ @factorBy_str
						
	
	end	-- }
	else if lower(ltrim(rtrim(@tabname))) = @tranlogtmptab
	begin	-- {

		select @sqlstmt = @sqlstmt + " LCTPages=LCTPageCount*"
					 	+ @factorBy_str
					   + ", TotalPages=TotalPageCount*"
					 	+ @factorBy_str
					   + ", CLRPages=CLRPageCount*"
					 	+ @factorBy_str
					   + ", UsedPages=UsedPageCount*"
					 	+ @factorBy_str
					   + ", FreePages=FreePageCount*"
					 	+ @factorBy_str
			
	end	-- }
	else 	-- invalid table name
		return (1)
		
	exec @returnStatus = sp_exec_SQL @sqlstmt, @whoami
			
	return (@returnStatus)
						       
end	-- }	-- }
go
go
exec sp_procxmode 'sp_spaceusage_cnvtounit', 'anymode'
go
grant execute on sp_spaceusage_cnvtounit to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_object_init')
begin
	drop procedure sp_spaceusage_object_init
end
go
print "Installing sp_spaceusage_object_init"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_object_populate')
begin
	drop procedure sp_spaceusage_object_populate
end
go
print "Installing sp_spaceusage_object_populate"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_object_genoutput')
begin
	drop procedure sp_spaceusage_object_genoutput
end
go
print "Installing sp_spaceusage_object_genoutput"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_object_archdata')
begin
	drop procedure sp_spaceusage_object_archdata
end
go
print "Installing sp_spaceusage_object_archdata"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_object')
begin
	drop procedure sp_spaceusage_object
end
go
print "Installing sp_spaceusage_object"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:58 2006 
*/
/*
** raiserror Messages for spaceusage_object [Total 3]
**
** 17870, "Table '%1!' does not exist in database '%2!'. %3!"
** 18322, "There is not a database named '%1!'."
** 19531, "Either no match found for %1! '%2!' in database '%3!', or, no physical space is allocated for the object."
*/
/*
** sp_getmessage Messages for spaceusage_object [Total 4]
**
** 19532, "Warning: Some output column values in the result set may be incorrect. Running '%1!' may help correct them."
** 19533, "All the page counts in the result set are in the unit '%1!'."
** 19534, "All the data in the result set are dated '%1!'."
** 19535, "Data was successfully archived into table '%1!'."
*/
/*
** End spgenmsgs.pl output.
*/
/*
** All the following procedures have reference to the #spaceusageinfo table. So,
** create the dummy table so that we can install/load the following sprocs.
**
** NOTE: Any change done to this table needs a change in the corresponding 
** #spaceusageinfo table created in the procedure sp_spaceusage_object towards 
** the end of the file (at line #1688). And the inserts that are done in the 
** procedure sp_spaceusage_object_init (at lines #143, 280, 371).
*/
if object_id("#spaceusageinfo") is not NULL
	drop table #spaceusageinfo
go

create table #spaceusageinfo
(
	  VersionNum		int		NOT NULL
	, ESDNum		int		NOT NULL
	, EBFNum		int		NOT NULL
	, ArchiveDateTime	datetime	NOT NULL
	, ServerName		varchar(255)	NULL
	, MaxPageSize		int		NOT NULL
	, DBName		varchar(30)	NOT NULL
	, OwnerName		varchar(30)	NOT NULL
	, TableName		varchar(255)	NOT NULL
	, Id			int		NOT NULL
	, IndId			smallint	NOT NULL
	, IndexName		varchar(255)	NULL
	, PtnId			int		NOT NULL
	, PtnName		varchar(255)	NOT NULL
	, DataPtnId		int		NOT NULL
	, RowSize		float		NULL
	, NumRows		float		NULL
	, RowCount_ts		float		NULL
	, NumFwdRows		float		NULL
	, NumDelRows		float		NULL
	, EmptyPageCount	int		NULL
	, DataPageCount		int		NULL
	, UsedPageCount		int		NULL
	, RsvdPageCount		int		NULL
	, SpUtil		decimal(9,2)	NULL
	, DPCR			decimal(5,4)	NULL
	, DRCR			decimal(5,4)	NULL
	, IPCR			decimal(5,4)	NULL
	, LGIO			decimal(5,4)	NULL
	, FF			smallint	NULL
	, MRPP			smallint	NULL
	, ERS			smallint	NULL
	, RPG			smallint	NULL
	, LeafPageCount		int		NULL
	, IndexHeight		smallint	NULL
	, OAMAPageCount		int		NULL
	, Extent0PageCount	int		NULL
	, Status		int		NULL
	, Sysstat		smallint	NOT NULL
	, Sysstat2		int		NOT NULL
	, NonLeafRowSize	decimal(10,4)	NULL
	, ExpIndexHeight  	smallint	NULL
	, ExpDataPageCount	int		NULL
	, ExpUsedPageCount	int		NULL
	, ExpRsvdPageCount	int		NULL
	, ExpLeafPageCount	int		NULL
	, PctBloatUsedPages	decimal(7,2)	NULL
	, PctBloatRsvdPages	decimal(7,2)	NULL
	, PctBloatLeafPages	decimal(7,2)	NULL
	, ExtentUtil		decimal(5,2)	NULL
	, PctEmptyPages		decimal(5,2)	NULL
	, PctFwdRows		decimal(5,2)	NULL
	, LockScheme		tinyint		NOT NULL
	, NumVarCols		smallint	NOT NULL
	, HasAPLCI		bit		NOT NULL

	-- This is NULL'able, as we can't get the statmoddate for
	-- index entries 255. (These have rows generated for space usage.) 
	, StatModDate		date		NULL

	-- List of generated columns that will not be archived.
	, SpacePerPage		float		NULL
	, CalcRowsPerPage	float		NULL
	, EmptyPages		float		NULL
	, DataPages		float		NULL
	, UsedPages		float		NULL
	, RsvdPages		float		NULL
	, LeafPages		float		NULL
	, ExpDataPages		float		NULL
	, ExpUsedPages		float		NULL
	, ExpRsvdPages		float		NULL
	, ExpLeafPages		float		NULL
	-- End of list of generated columns that will not be archived.
)
go

if (@@error != 0) select syb_quit() 
go

/*
**	SP_SPACEUSAGE_OBJECT_INIT
**
**	The sub-procedure that initializes the temporary table #spaceusageinfo
**	with space usage information depending on the action. For "display" or
**	"display summary" or "archive" action, only the raw data extracted from
**	different system tables is loaded into #spaceusageinfo (all other data
**	will have to be computed in the next step to make the information 
**	complete) whereas for the action "report" and "report summary", the 
**	processed data in the archive table is loaded into the #spaceusageinfo 
**	table. Called by sp_spaceusage_object.
**
**	Parameters
**		@actionword	- The action to be performed.
**		@nouname	- Was no owner name provided by the user?
**		@uname		- Owner/user name.
**		@tname		- Table name.
**		@iname		- Index name.
**		@entity_type	- The type of entity.
**		@archivetabname	- The 3-part archive table name.
**		@from_date	- Date from when on to get archived data.
**		@to_date	- Date till which to get archvied data.
**
**	Returns
**		0 - if all goes well
**		6 - archive table not found
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_object_init
(
	  @actionword		varchar(20)
	, @nouname		bit
	, @uname		varchar(255)
	, @tname		varchar(255)
	, @iname		varchar(255)
	, @entity_type		varchar(12)
	, @archivetabname	varchar(320) = NULL
	, @from_date		varchar(30) = NULL
	, @to_date		varchar(30) = NULL
)
as
begin 	-- {

	declare	  @entity_table		varchar(6)
		, @entity_index		varchar(6)
		
		, @action_display		varchar(8)
		, @action_display_summary	varchar(16)
		, @action_report		varchar(7)
		, @action_report_summary	varchar(15)
		, @action_archive		varchar(8)

		, @esdnumstr		varchar(20)
		, @ebfnumstr		varchar(20)
		, @esdnum		int
		, @ebfnum		int

		, @returnStatus		int
		, @sqlstmt		varchar(4096)
		, @whoami		varchar(40)
		, @msg			varchar(256)
	
	select	  @whoami	= "sp_spaceusage_object_init"
	
		, @entity_table	= "table"
		, @entity_index	= "index"
		
		, @action_display		= "display"
		, @action_display_summary	= "display summary"
		, @action_report		= "report"
		, @action_report_summary	= "report summary"
		, @action_archive		= "archive"	
	
	/* Extract the ESD number and the EBF number from the version string.*/
	exec sp_versioncrack @@version, "ESD", @esdnumstr out, @esdnum out
	exec sp_versioncrack @@version, "EBF", @ebfnumstr out, @ebfnum out

	/*
	** NOTE1: When user does not supply owner name of a table, then current
	** user is implicitly assumed. As is the convention, in case the owner
	** name is omitted and there is no table owned by current user that
	** qualifies, but one owned by DBO qualifies, we will include that in
	** the result. 
	** 
	** For example, asumme there are tables t1 and t2 owned by user1, tables
	** t1 and t3 owned by dbo and table t1 owned user2 in a database. When 
	** user1 supplies user1.t1, only user1's table t1 should be included.
	** When user1 supplies user2.t1, only user2's table t1 should be
	** included. When user1 omits the owner and supplies t1, again only
	** user1's table t1 should be included as it exists. But if user1 omits
	** the owner and supplies t3, dbo's table t3 should be included as no
	** table t3 owned by user1 exists while t3 owned by dbo does.
	**
	** Due to this reason the WHERE clause handling the owner name has a
	** sub-query embedded.
	**
	** NOTE2: In case of 'display', 'display summary' and 'archive' action
	** for the entity type index, we need to include the data layer
	** information for all the table whose index qualifies. This is required
	** as we need the estimates for data layer in order to make estimates
	** about the index layer. Hence, an additional condition is added to the
	** WHERE clause handling the index name to take care of this.
	*/
	
	if @actionword in (   @action_display
			    , @action_display_summary
			    , @action_archive )
	
	begin	-- { 	-- Display/Archive mode
	
		/* 
		** Collect all the necessary raw data or meta data for 
		** estimation. 
		**
		*/
		insert into #spaceusageinfo
		select    
	  		  @@version_number as VersionNum		
			, @esdnum as ESDNum
			, @ebfnum as EBFNum
			, getdate() as ArchiveDateTime
			, @@servername as ServerName
			, @@maxpagesize as MaxPageSize
			, db_name() as DBName
			, user_name(o.uid) as OwnerName
			, o.name as TableName
			, i.id as Id
			, p.indid as IndId
			, i.name as IndexName
			, p.partitionid as PtnId
			, p.name as PtnName
			, p.data_partitionid as DataPtnId
		
			-- These are the values which needs to be accurate in
			-- order for us to correctly report the estimated data
			-- or reserved page counts. A recent 'update table
			-- statistics'is necessary for these values to be
			-- accurate.
			--
			, RowSize = case 
					when p.indid > 1 
					then convert(decimal(10,4), 
								t.leafrowsize)
					else convert(decimal(10,4),
								t.datarowsize)
				    end
		
			-- Compute the row count using the built-in. As the
			-- number of rows is not applicable for the index layer,
			-- it is set to NULL for indid > 0. For indid = 1, the
			-- dummy data layer row that we add in the next step
			-- would have the value set appropriately.
			--
			, NumRows = case 
					when p.indid > 0 
					then NULL
					else row_count(db_id(), i.id
								, p.partitionid)
				    end
			, t.rowcnt as RowCount_ts
				
			, t.forwrowcnt as NumFwdRows
			, t.delrowcnt as NumDelRows
			, t.emptypgcnt as EmptyPageCount
			
			-- The following built-ins return 0 in case of invalid
			-- inputs. So, no need to check for NULL. Except for
			-- used_pages(), the built-ins return only the index
			-- layer pages for indid=1. For used_pages(), however,
			-- they return both data and index layer used pages. The
			-- data layer used pages can be got by passing indid=0
			-- to the built-in and then subtracted to get the index
			-- layer used pages.
			--
			, data_pages(db_id(), i.id, p.indid, p.partitionid) 
				as DataPageCount
			, used_pages(db_id(), i.id, p.indid, p.partitionid) 
			  	- case p.indid 
				   when 1 then used_pages(db_id(), i.id, 0,
				   				p.partitionid)
				   else 0
				  end
				as UsedPageCount
			, reserved_pages(db_id(), i.id, p.indid, p.partitionid)
				as RsvdPageCount
		
			-- Placeholder for space utilizaton and cluster ratio
			-- and other statistics collected using the
			-- derived_stat() built-in.
			--
			, convert(decimal(9,2), 0) as SpUtil
			, convert(decimal(5,4), 0) as DPCR
			, convert(decimal(5,4), 0) as DRCR
			, convert(decimal(5,4), 0) as IPCR
			, convert(decimal(5,4), 0) as LGIO
		
			-- Extract the space management parameters.
			, fill_factor as FF
			, maxrowsperpage as MRPP
			, exp_rowsize as ERS
			, res_page_gap as RPG
		
			-- Other columns from systabstats that may be
			-- interesting.
			--
			, t.leafcnt as LeafPageCount
			, t.indexheight as IndexHeight
			, t.oamapgcnt as OAMAPageCount
			, t.extent0pgcnt as Extent0PageCount
			, t.status as Status
			, o.sysstat as Sysstat
			, o.sysstat2 as Sysstat2
		
			-- Some input and output columns that would be computed.
			, convert(decimal(10,4), 0) as NonLeafRowSize
			, NULL as ExpIndexHeight
			, 0 as ExpDataPageCount
			, 0 as ExpUsedPageCount
			, 0 as ExpRsvdPageCount
			, 0 as ExpLeafPageCount
			, convert(decimal(7,2), 0) as PctBloatUsedPages
			, convert(decimal(7,2), 0) as PctBloatRsvdPages
			, convert(decimal(7,2), 0) as PctBloatLeafPages
			, convert(decimal(5,2), 0) as ExtentUtil
			, convert(decimal(5,2), 0) as PctEmptyPages
			, convert(decimal(5,2), 0) as PctFwdRows
		
			-- Auxilliary columns to facilitate estimate computation
			, convert(tinyint, ((o.sysstat2 & 57344)/16384)
				 )as LockScheme
			, convert(smallint, -1) as NumVarCols
			, convert(bit, 0) as HasAPLCI
			, convert(date, t.statmoddate)		-- StatModDate

			-- List of generated columns that will not be archived.
			--
			, convert(float, 0.0) as SpacePerPage
			, convert(float, 0.0) as CalcRowsPerPage
			, convert(float, 0.0) as EmptyPages
			, convert(float, 0.0) as DataPages
			, convert(float, 0.0) as UsedPages
			, convert(float, 0.0) as RsvdPages
			, convert(float, 0.0) as LeafPages
			, convert(float, 0.0) as ExpDataPages
			, convert(float, 0.0) as ExpUsedPages
			, convert(float, 0.0) as ExpRsvdPages
			, convert(float, 0.0) as ExpLeafPages
		
		from	  sysindexes i
			, syspartitions p
		   	, systabstats t
			, sysobjects o
				
		where o.name 		   like @tname
		
		  -- Refer to NOTE1 at line# 140.
		  and (user_name(o.uid)	like @uname
		  	or (@nouname = 1
				and not exists(	select 1 
						from sysobjects o2
						where o2.name=o.name
						  and user_name(o2.uid)=@uname)
				and user_name(o.uid) = "dbo"
			   )
		      )
		
		  -- Only look for user/system tables.
		  and type 		   in ('U', 'S')
		  
		  -- Skip fake tables.
		  and ((o.sysstat & 1024)  != 1024)
		  
		  -- Skip proxy tables.
		  and ((o.sysstat2 & 1024) != 1024)
		  
		  -- Skip tables with no real storage.
		  and (p.indoampage != 0 
		  	or p.datoampage != 0)
		  
		  and o.id 		    = i.id
		  and p.id 		    = i.id
		  and p.indid 		    = i.indid

		  -- Do a right join with systabstats so as to include a row
		  -- corresponding to indid = 255, although there is no row for
		  -- it present in systabstats.
		  -- 
		  and t.id		    =* p.id		
		  and t.indid 		    =* p.indid
		  and t.partitionid	    =* p.partitionid

		  -- Refer to NOTE2 at line# 158.
		  and (i.name like @iname 
		  	or (i.indid in (0,1)
				and o.id in (select i2.id
					     from sysindexes i2
					     where name like @iname)
			    )
		      )
		
		if (@@error != 0)
			return (@@error)

		/*
		** Add a dummy row with indid = 0, for each indid = 1 column.
		** This is to separate the index and data layer for indid = 1
		** case, which is otherwise difficult.
		*/
		insert	into #spaceusageinfo
		select 	  VersionNum
			, ESDNum
			, EBFNum
			, ArchiveDateTime
			, ServerName
			, MaxPageSize
			, DBName
			, OwnerName
			, TableName
			, Id	
			, IndId		= 0
			, IndexName 	= TableName
			, PtnId
			, PtnName
			, DataPtnId
			, RowSize
			, NumRows 	= row_count(db_id(), Id, PtnId)
			, RowCount_ts
			, NumFwdRows
			, NumDelRows
			, EmptyPageCount
			, DataPageCount = data_pages(db_id(), Id, 0, PtnId)
			, UsedPageCount = used_pages(db_id(), Id, 0, PtnId)
			, RsvdPageCount = reserved_pages(db_id(), Id, 0, PtnId)
			, SpUtil
			, DPCR
			, DRCR
			, IPCR
			, LGIO
			, FF
			, MRPP
			, ERS
			, RPG
			, LeafPageCount
			, IndexHeight
			, OAMAPageCount
			, Extent0PageCount
			, Status
			, Sysstat
			, Sysstat2
			, NonLeafRowSize
			, ExpIndexHeight
			, ExpDataPageCount
			, ExpUsedPageCount
			, ExpRsvdPageCount
			, ExpLeafPageCount
			, PctBloatUsedPages
			, PctBloatRsvdPages
			, PctBloatLeafPages
			, ExtentUtil
			, PctEmptyPages
			, PctFwdRows
			, LockScheme
			, NumVarCols
			, HasAPLCI = 1
			, StatModDate
			, SpacePerPage
			, CalcRowsPerPage
			, EmptyPages
			, DataPages
			, UsedPages
			, RsvdPages
			, LeafPages
			, ExpDataPages
			, ExpUsedPages
			, ExpRsvdPages
			, ExpLeafPages

		from 	#spaceusageinfo
		where 	IndId = 1

		if (@@error != 0)
			return (@@error)
	
	end 	-- }	-- Display/Archive mode
	
	else if @actionword in (  @action_report
				, @action_report_summary )
	
	begin	-- {	-- Report action
		
		-- Check for valid archive table name is already done by the
		-- calling procedure sp_spaceusage_object.
		
		select @sqlstmt =  " INSERT INTO #spaceusageinfo "
				 + " SELECT 	 * "
				 +		", SpacePerPage"    + "=0"
				 +		", CalcRowsPerPage" + "=0"
				 +		", EmptyPages"	    + "=0" 
				 +		", DataPages"	    + "=0"   
				 +		", UsedPages"	    + "=0"
				 +		", RsvdPages"	    + "=0"
				 +		", LeafPages"	    + "=0"
				 +		", ExpDataPages"    + "=0"
				 +		", ExpUsedPages"    + "=0"
				 +		", ExpRsvdPages"    + "=0"
				 +		", ExpLeafPages"    + "=0"
				 + " FROM " +	@archivetabname + " o "
				 + " WHERE DBName LIKE '" + db_name() + "'"
				 + "   AND TableName LIKE '" + @tname + "'"
				 + "   AND IndexName LIKE '" + @iname + "'"

		-- Refer to NOTE1 at line#140
		select @sqlstmt = @sqlstmt
				 + " AND "
				 + "(OwnerName LIKE '" + @uname + "'"
				 + 	" OR ( 1=" + convert(char(1), @nouname)
				 + 		" AND NOT EXISTS("
				 +			 " SELECT 1"
				 +			 " FROM " 
				 + 			  @archivetabname 
				 + 					" i1"
				 + 			 " WHERE "
				 +				"i1.TableName"
				 +				"=o.TableName"
				 +			  " AND "
				 +				"i1.OwnerName"
				 +				"='" + @uname
				 +			"')"
				 +		 " AND o.OwnerName = 'dbo'"
			   	 + 	    ")"
		      		 + ")"
		
		-- The ArchiveDateTime part of the query does the following.
		-- When both @from_date and @to_date are NULL, it looks for the
		-- latest ArchiveDateTime for each object that qualifies and
		-- selects that entry into the #spaceusageinfo table. If only
		-- @from_date is NULL, it selects all data till @to_date. And
		-- when only @to_date is missing, it assumes @to_date to be
		-- today.
		--
		if @from_date is NULL
		begin
			if @to_date is NULL
			begin	-- both dates are null
				select @sqlstmt = @sqlstmt 
						+ " AND ArchiveDateTime "
						+ " = (SELECT "
						+	"max(ArchiveDateTime)"
						+ " FROM " + @archivetabname 
						+ 			" i2 "
						+ " WHERE i2.DBName=o.DBName"
						+   " AND i2.OwnerName"
						+		"=o.OwnerName"
						+   " AND i2.TableName"
						+		"=o.TableName"
						+   " AND i2.IndexName"
						+		"=o.IndexName"
						+   " AND (i2.ServerName is NULL"
						+   	  " or i2.ServerName"
						+		"=o.ServerName)"
						+     ")"
			end
			else
			begin	-- only from_date is null
				select @sqlstmt = @sqlstmt
						+ " AND ArchiveDateTime "
						+ " <= '" + @to_date + "'"
			end
		end
		else
		begin
			if @to_date is NULL
			begin	-- only to_date is null
				select @sqlstmt = @sqlstmt
						+ " AND ArchiveDateTime "
						+ " >= '" + @from_date + "'"
						+ " AND ArchiveDateTime "
						+ " <= getdate()"
			end
			else
			begin	-- both dates are non-null
				select @sqlstmt = @sqlstmt
						+ " AND ArchiveDateTime "
						+ " >= '" + @from_date + "'"
						+ " AND ArchiveDateTime "
						+ " <= '" + @to_date + "'"
			end
		end

		exec @returnStatus = sp_exec_SQL @sqlstmt, @whoami 

		if @returnStatus != 0
			return (@returnStatus)

	end	-- } 	-- Report action 

	-- If no row in #spaceusageinfo, no object qualified and hence report an
	-- error message indicating the same and return back.
	--
	if not exists ( select 1 from #spaceusageinfo )
	begin
		declare	  @tmpname varchar(290)
			, @tmpdbname varchar(30)
			
		select 	  @tmpname = @uname + "." + @tname 
			, @tmpdbname = db_name()

		if @entity_type = @entity_index 
			select @tmpname = @tmpname + "." + @iname
		
		raiserror 19531, @entity_type, @tmpname, @tmpdbname
		return (7)
	end	
	return (0)
	
end 	-- }	-- }
go

/*
**	SP_SPACEUSAGE_OBJECT_POPULATE
**
**	The sub-procedure that populates the temporary table #spaceusageinfo 
**	with computed space usage information based on the raw space usage 
**	information already in it. This is applicable only for the "display", 
**	"display summary" and "archive" action. Called by sp_spaceusage_object.
**
**	Parameters
**		None.	
**
**	Returns
**		0 - if all goes well
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_object_populate
as
begin	-- {	

	declare	 
		  @objid		int
		, @indid		int
		, @ptnid		int
		, @lockscheme		tinyint
		
		, @syscur_ffactor	float   -- server-wide fill factor %
		, @syscur_ers_pct	float   -- server-wide exp row size %
		
		, @datalayerpages	int
		, @datapartitionid	int
		, @numrowscovered	int
		, @indexrowsize		float
		
		, @numpagesPerExtent	int
		, @numextent0		int
		, @dummyindexlevel	smallint
		, @aplpagehdrsize	tinyint
		, @dolpagehdrsize	tinyint

		, @returnStatus		int
		, @msg			varchar(256)

	select    @dummyindexlevel   = -1
		, @numpagesPerExtent = 8
		, @numextent0	     = 1
		, @aplpagehdrsize    = 32
		, @dolpagehdrsize    = 44

	/* 
	** Get the current server wide default value for the ERS and FF. 
	**
	** NOTE: These values are not available in syscurconfigs, and hence,
	** need to get them from sysconfigures.
	*/
	select @syscur_ers_pct = value/100.0
	from master.dbo.sysconfigures
	where comment = 'default exp_row_size percent'
	
	select @syscur_ffactor = value/100.0
	from master.dbo.sysconfigures
	where comment = 'default fill factor percent'

	/* 
	** If not set(NULL), or set to 0 or NULL, handle it apprpriately as this
	** will be used later during space calculations.
	*/
	select @syscur_ffactor = case @syscur_ffactor
					when NULL then 1
					when 0 then 1
					else @syscur_ffactor
				 end
				 
	select @syscur_ers_pct = case @syscur_ers_pct
					when NULL then 0
					when 1 then 0
					else @syscur_ers_pct
				 end
	

	/*	
	** Pull out space utilizaton and cluster ratio using the derived_stat()
	** built-in. This may need to be converted into appropriate format 
	** before display to be in synch with other related output columns. 
	** Also, the derived_stat() built-in requires SA role (for objects not 
	** owned by the user running the built-in) and will be displayed only 
	** when this sproc is run with that role. Else, it will show 0.
	*/
	update 	#spaceusageinfo
	set 	  SpUtil = convert(decimal(9,2), 
					100*derived_stat(Id, IndId, PtnId,
							"space utilization"))
		, DPCR   = convert(decimal(5,4),
					derived_stat(Id, IndId, PtnId, "dpcr"))
		, DRCR	 = convert(decimal(5,4),
					derived_stat(Id, IndId, PtnId, "drcr"))
		, IPCR	 = convert(decimal(5,4),
					derived_stat(Id, IndId, PtnId, "ipcr"))
		, LGIO	 = convert(decimal(5,4),
					derived_stat(Id, IndId, PtnId, "lgio"))
	where	OwnerName = user_name() 
	   or	charindex("sa_role", show_role()) > 0
	
	if (@@error != 0)
		return (@@error)
	
	/* 
	** Compute and update current value for some space related metrics
	** like extent utilization (ratio of the pages in use to the pages
	** reserved), PctEmptyPages (ratio of the empty	pages to the total 
	** pages in use), PctFwdRows (ratio of the number of forwarded rows to
	** the total rows respectively). 
	*/	
	update #spaceusageinfo
	set	  ExtentUtil 	= convert(decimal(5,2), 
					     case RsvdPageCount
					      when 0 then 0
					      else UsedPageCount*100.0/
					      		RsvdPageCount
					     end)
						
		, PctEmptyPages	= convert(decimal(5,2),	
					     case DataPageCount
					      when 0 then 0
					      else EmptyPageCount*100.0/
					      		DataPageCount
					     end)
						
		, PctFwdRows	= convert(decimal(5,2), 
					     case NumRows
					      when 0 then 0
					      else NumFwdRows*100.0/NumRows
					     end)
						
	if (@@error != 0)
		return (@@error)
						
	update	#spaceusageinfo
	set	NumVarCols	= ( select  count(*)
				    from    syscolumns i
				    where   i.id = #spaceusageinfo.Id
				      and   i.offset < 0 )

	if (@@error != 0)
		return (@@error)
	
	/*
	** For data layer pages (indid = 0), calculate the space per page 
	** available as follows.
	**
	** Adjust for the page header, to get the actual row-storage space on
	** a page. 
	**
	** Apply fill factor as follows:
	**	APL table with CI (indid = 1), if value stored in sysindexes for
	**	indid 1, use it. If not, use the server wide default value.
	**	
	**	DOL table (indid=0), if value stored in sysindexes for indid 0,
	**	use it. If not, fully pack it.
	** 
	** Apply expected row size as follows:
	**	Applicable only for DOL tables with variable length columns. 
	**
	**	If set to 0, use the server wide default expected row size
	**	percent to leave space in each row for expanding rows.
	**
	**	If set to 1, we fully pack the data page.
	**
	**	If set to any other value, then it will be taken care of later
	**	(w.r.t to data row size value)
	*/
	update 	#spaceusageinfo
	set	SpacePerPage = 	(@@maxpagesize - @aplpagehdrsize)
				* 
				(case FF
					when NULL then 1
					when 0 then @syscur_ffactor
					else FF/100.0
				end)
	where 	IndId = 0	
	  and	LockScheme = 0 		-- APL table

	if (@@error != 0)
		return (@@error)
		
	update 	#spaceusageinfo
	set	SpacePerPage = 	(@@maxpagesize - @dolpagehdrsize)
				*
				(case FF
					when NULL then 1
					when 0 
					then case 
						when NumVarCols > 0
						 and ERS = 0
						then (1 - @syscur_ers_pct)
						else 1
					     end
					else FF/100.0
				end)
	where	IndId = 0
	  and	LockScheme != 0 	-- non-APL, i.e., DOL table

	if (@@error != 0)
		return (@@error)

	/* 
	** Calculate the number of data rows that can fit a single page based on
	** the space available per page for rows and the row size.
	**
	** For DOL tables, if ERS is set [to a value other than 0/1], inserts
	** reserve that much space for the row even if currently it is smaller
	** in size in case the table has variable length columns. 
	**
	** Figure in a 2-byte offset table overhead.
	*/
	update 	#spaceusageinfo
	set	CalcRowsPerPage = SpacePerPage/(case LockScheme
						   when 0 then RowSize
						   else case 		--DOL
						   	   when ERS is not NULL
						   	    and ERS != 0 
							    and ERS != 1
							    and ERS > RowSize
							    and NumVarCols>0
							   then ERS
							   else RowSize
							end
						end
						+ 2)  -- Row offset entry size
	where IndId = 0
	
	if (@@error != 0)
		return (@@error)
		
	/*
	** For APL tables, if MRPP is set, it limits the no of rows that can fit
	** a page. Also, an APL table can not have more than 256 rows per page.
	*/
	update 	#spaceusageinfo
	set	CalcRowsPerPage	= case 
				     when MRPP != 0 
				      and MRPP < CalcRowsPerPage
				     then MRPP
				     else case 
				     	     when CalcRowsPerPage > 256.0
					     then 256.0
					     else CalcRowsPerPage
					  end
				  end			      
	where IndId = 0 and LockScheme = 0		-- APL data layer

	if (@@error != 0)
		return (@@error)
		
	/*
	** Update the temp table to get the estimated data layer pages that
	** would be required if this were a fully packed table. 
	**
	** If the number of rows in the table is 0, then the expected data pages
	** for the data layer is 1.
	*/
	update	#spaceusageinfo
	set	ExpDataPageCount = case NumRows
				  when 0 then 1
				  else ceiling(NumRows/CalcRowsPerPage)
			       end
	where IndId = 0

	if (@@error != 0)
		return (@@error)
		
	/* 
	** Estimate number of used pages based on the data page estimate
	** assuming the same number of pages will be used for internal 
	** structures as are being used currently.
	*/
	update #spaceusageinfo 
	set ExpUsedPageCount = ExpDataPageCount + (UsedPageCount 
							- DataPageCount)
	where IndId = 0

	if (@@error != 0)
		return (@@error)
		
	/* 
	** For the text/image index [indid = 255] there isn't a way to estimate
	** the number of data/used pages. So, set it to	DataPageCount/
	** UsedPageCount.
	*/ 
	update #spaceusageinfo
	set	  ExpDataPageCount = DataPageCount
		, ExpUsedPageCount = UsedPageCount
	where IndId = 255
	
	if (@@error != 0)
		return (@@error)
		
	/*
	** Set the non-leaf row size for indid > 0 except for the text/image
	** index[indid = 255].
	**
	** For APL tables, the non-leaf row is same as leaf row for CI, and
	** has an additional 4 byte pointer [to an index page] in case of NCI.
	**
	** Ignoring the suffix compression at non-leaf levels and the duplicate
	** key handling at the leaf level, in DOL tables, the non-leaf rows has
	** a 4 byte pointer in place of the 6 byte RID of the leaf rows.
	**
	** NOTE: For indid = 1, leaf row size is not maintained and will be
	** computed later. This step will actually set it is as data row size.
	**
	*/
	update #spaceusageinfo
	set 	  NonLeafRowSize = case LockScheme
					when 0 then (case IndId
						       when 1 then (RowSize)
						       else (RowSize + 4)
						     end)
					else (RowSize - 6 + 4)
				   end
	where IndId > 0 and IndId != 255

	if (@@error != 0)
		return (@@error)
		
	/*
	** Compute/Estimate the ExpDataPageCount for the index layer [indid>0]
	**
	** Steps involved -
	** 	1. set the #indexData table [by selecting from #spaceusageinfo 
	**	   into it]. at this point, the leaf and non-leaf row sizes are
	**	   already computed and set. sp_index_space_est will compute the
	**	   leaf and non-leaf rows per page values internally based on 
	**	   them.
	**
	**	2. go thru each <id, indid, ptnid> threesome and pass it to the
	** 	   sp_index_space_est. this sproc would set the data pages and
	**	   used pages for this <id, indid, ptnid> threesome in the
	**	   #indexData table appropriately.
	**
	**	3. set the ExpDataPageCount and ExpUsedPageCount in 
	**	   #spaceusageinfo table for the index accordingly.
	**
	*/
	
	/*			STEP 1.	
	** Create and populate the #indexData table required by the sproc
	** sp_index_space_est which will be used to calculate the 
	** ExpDataPageCount, ExpUsedPageCount, ExpRsvdPageCount for the	index 
	** layer [indid >0]
	*/
	select 	  Id					as id
		, IndId					as indid
		, PtnId 				as ptnid
		, IndexName				as name
		, ""					as type
		, -1					as indexlevel
		, convert(smallint NULL, FF)		as ffactor
		, convert(smallint NULL, MRPP)		as maxrowsperpage
		, convert(int NULL, 0)			as datalayerpages
		, convert(float NULL, NumRows)	 	as numrows
		, convert(float NULL, RowSize)		as leafrowsize
		, convert(float NULL, NonLeafRowSize)	as nonleafrowsize
		, convert(tinyint NULL, LockScheme)	as lockscheme
		, 0					as numofdatapages
		, convert(float, 0)			as datasizeinkb
		, 0					as numofusedpages
		, convert(float, 0)			as usedsizeinkb
	into	#indexData
	from	#spaceusageinfo
	where 	IndId > 0 
	  and	IndId != 255

	if (@@error != 0)
		return (@@error)
		
	/* 
	** Create a unique index on #indexData in order to create an updatable
	** cursor on it.
	*/
	create unique index uind on #indexData(id, indid, ptnid, indexlevel)
	
	if (@@error != 0)
		return (@@error)
	
	/*			STEP 2.	
	** Compute the no. of index pages and used pages for the indices one at
	** a time using the sp_index_space_est sproc.
	*/
	declare indexcursor cursor for 
		select id, indid, ptnid, lockscheme 
		from #indexData
		where indexlevel = @dummyindexlevel
	for update 

	open indexcursor

	while (1 = 1)
	begin	-- {
	
		-- Go to the next <id, indid, ptnid, lockscheme> quad.
		fetch indexcursor into @objid, @indid, @ptnid, @lockscheme

		if @@sqlstatus != 0
			break

		-- For indid = 1, the index row size is not maintained. So, we
		-- will use the sproc sp_index_row_size_est to get a rough 
		-- estimate for it.
		--
		if @indid = 1
		begin 	-- {
			exec @returnStatus = sp_index_row_size_est  
							  @objid
							, @indid
							, @lockscheme
							, NULL
							, @indexrowsize out
							
			if @returnStatus != 0
				return (@returnStatus)

			-- Update the leaf row size and non leaf row size with
			-- the estimated index row size both for #indexData 
			-- [needed for index space estimate] and #spaceusageinfo
			-- [needed as it is the repository for all the collected
			-- data]
			--
			update	#indexData
			set	  leafrowsize 	 = @indexrowsize
				, nonleafrowsize = @indexrowsize 
			where 	id	   = @objid 
			  and 	indid 	   = @indid 
			  and	ptnid	   = @ptnid 
			  and	indexlevel = @dummyindexlevel

			if (@@error != 0)
				return (@@error)
	
			update 	#spaceusageinfo
			set	  RowSize 	 = @indexrowsize
				, NonLeafRowSize = @indexrowsize 
			where 	Id    = @objid 
			  and	IndId = @indid 
			  and	PtnId = @ptnid 
			
			if (@@error != 0)
				return (@@error)
	
		end	--} -- End of if 

		-- Fetch the data partition id corresponding to the index. 
		select	@datapartitionid = DataPtnId
		from 	#spaceusageinfo
		where	Id    = @objid 
		  and	IndId = @indid 
		  and	PtnId = @ptnid 

		if ( @datapartitionid = 0 )
		begin
			
			-- Global, unpartitioned index covering all data
			-- partitions.
			--
			select	  @datalayerpages = sum(ExpDataPageCount)
				, @numrowscovered = sum(NumRows)
			from	#spaceusageinfo
			where	Id    = @objid 
			  and	IndId = 0
		end
		else
		begin
			
			-- Local, partitioned index covering a single 
			-- partition.
			--
			-- APL CI are on same partition as the data they cover
			-- For them the partition ID and the data partition ID
			-- would always match.
			--
			select	  @datalayerpages = ExpDataPageCount 
				, @numrowscovered = NumRows
			from	#spaceusageinfo
			where	Id    = @objid 
			  and	IndId = 0
			  and	PtnId = @datapartitionid
		end
			
		update	#indexData
		set	  datalayerpages = @datalayerpages
			, numrows	 = @numrowscovered
		where	id	   = @objid
		  and	indid	   = @indid
		  and	ptnid	   = @ptnid
		  and	indexlevel = @dummyindexlevel
	
		if (@@error != 0)
			return (@@error)
	
		-- Get the index space estimate for the <id, indid, ptnid>
		-- threesome.
		--
		exec @returnStatus = sp_index_space_est @objid, @indid, @ptnid

		if @returnStatus != 0
			return (@returnStatus)

		-- Consolidate the result. 
		-- 
		-- sp_index_space_est sums up all the index layer data and used
		-- pages for each level and sets the numofdatapages and 
		-- numofusedpages columns for the indexlevel = -1 row with that
		-- value. We set ExpDataPageCount and ExpUsedPageCount of 
		-- #spaceusageinfo table to those values.
		--
		update	#spaceusageinfo
		set	  ExpDataPageCount = (	select	numofdatapages 
						from	#indexData
						where 	id 	   = @objid
						  and 	indid	   = @indid
						  and 	ptnid	   = @ptnid
						  and 	indexlevel = 
						  	    @dummyindexlevel )
			, ExpIndexHeight   = (  select 	max(indexlevel)
						from 	#indexData
						where 	id 	   = @objid
						  and 	indid	   = @indid
						  and 	ptnid	   = @ptnid )
					
		where	Id    = @objid 
		  and 	IndId = @indid 
		  and 	PtnId = @ptnid

		if (@@error != 0)
			return (@@error)
	
		-- Instead of using the numofusedpages from #indexData as the
		-- estimate for ExpUsedPageCount, use the current internal
		-- structure overhead (UsedPageCount - DataPageCount) and add it
		-- to ExpDataPageCount to get the ExpUsedPageCount.
		--
		update	#spaceusageinfo
		set	ExpUsedPageCount = ExpDataPageCount + 
						(UsedPageCount - DataPageCount)
		where	Id    = @objid 
		  and	IndId = @indid
		  and	PtnId = @ptnid
	
		if (@@error != 0)
			return (@@error)
	
		-- Set the ExpLeafPageCount of #spaceusageinfo table. For indid
		-- 1, the leaf pages are same as the data pages.
		--
		update	#spaceusageinfo
		set	ExpLeafPageCount = case IndId
					when 1 then 0
					else (select numofdatapages 
					      from   #indexData
					      where  id   	= @objid
						and  indid	= @indid
						and  ptnid	= @ptnid
						and  indexlevel = 0)
				   end
		where	Id    = @objid
		  and	IndId = @indid
		  and	PtnId = @ptnid

		if (@@error != 0)
			return (@@error)
		
	end	-- } 	-- End of while 
		
	close indexcursor
	deallocate cursor indexcursor
	
	/*
	** Go back and update expected reserved pages rounding up the expected
	** data pages to a multiple of # of extents.
	**
	** Incorporate the reserve page gap as follows. For CI, RPG applies
	** to both the data and index pages and for NCI it applies to only
	** data pages and leaf level pages.
	*/
	update	#spaceusageinfo
	set	ExpRsvdPageCount = ceiling((ExpUsedPageCount 
						+ case RPG
						    when 0 then 0.0
						    else 
						      ceiling(
						        (1.0/RPG)*
							case
							  when IndId <=1
							  then ExpUsedPageCount
							  else ExpLeafPageCount
							end
						      )
						  end
					)/@numpagesPerExtent
			       )*@numpagesPerExtent

	if (@@error != 0)
		return (@@error)
	
	/*
	** Now that we have got the expected data/reserved page counts,
	** compute the %age bloat values.
	*/
	update	#spaceusageinfo
	set 	  PctBloatRsvdPages = (convert(float, (RsvdPageCount
							- ExpRsvdPageCount))
					/ ExpRsvdPageCount) * 100
		, PctBloatUsedPages = (convert(float, (UsedPageCount
							- ExpUsedPageCount))
					/ ExpUsedPageCount) * 100
	where	ExpUsedPageCount > 0
	
	update	#spaceusageinfo
	set	PctBloatLeafPages = (convert(float, (LeafPageCount 
							- ExpLeafPageCount))
					/ ExpLeafPageCount) * 100
	where	ExpLeafPageCount > 0 

	if (@@error != 0)
		return (@@error)

	/*
	** Raise a warning message if the values were found suspicious.
	**
	** This message might come up often when space parameters are set. This
	** is because the procedure takes them into account even though they
	** might have not been applied yet.
	**
	** Also, the expected reserved pages may be off by the number of extent0
	** extents allocated to the object because the AP in extent0 is counted
	** by our estimates whereas in reality that is not the case. There's no
	** way to get this number for an object, we assume it to be 1 here. The
	** variable @numextent0 should be changed appropriately if this number
	** is tracked, or can be derived, in future.
	*/
	if exists (	select 1 
			from #spaceusageinfo 
			where ( PctBloatRsvdPages < 0 
				and (ExpRsvdPageCount - RsvdPageCount) >
					@numextent0
			      )
			   or PctBloatUsedPages < 0 
			   or PctBloatLeafPages < 0 
			   or PctFwdRows < 0 
			   or PctEmptyPages < 0 
		  )
	begin
		exec sp_getmessage 19532, @msg out
		print @msg, "update statistics"
	end

end	-- } 	-- }
go

/*
**	SP_SPACEUSAGE_OBJECT_GENOUTPUT
**	
**	The sub-procedure that prints on screen the space usage information on
**	the objects of interest	in detail or summary based on action. It would
**	apply the SELECT list, WHERE clause and ORDER BY clause on the base
**	table #spaceusageinfo if the user has supplied any. Else, it will use 
**	the default value for these. This is applicable only for "display", 
**	"diplay summary", "report" and "report summary" actions. Called by 
**	sp_spaceusage_object.
**
**	Parameters
**		@actionword 	- The action to be performed.
**		@unit		- Unit for the page counts.
**		@entity_type	- Type of the entity.
**		@iname		- Index name.
**		@select_list	- SELECT list, if any, to project the ouput.
**		@where_clause 	- WHERE clause, if any, to select the output.
**		@order_by_clause- ORDER BY clause, if any, to order the output.
**
**	Note:	The @entity_type and @iname are passed because for entity type
**		"index" the #spaceusageinfo table has an additional data layer
**		row that qualifies even though they may not qualify (they may
**		qualify if the index name pattern included them) and are not
**		expected in the output result. They need to be filtered out
**		using the WHERE clause.
**
**	Returns
**		0 - if all goes well
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_object_genoutput
(
		  @actionword		varchar(20)
		, @unit			varchar(6)
		, @entity_type		varchar(12)
		, @iname		varchar(255)
		, @select_list		varchar(1636)
		, @where_clause		varchar(1536)
		, @order_by_clause	varchar(768)
)
as
begin	-- {	

	declare	  @entity_table			varchar(6)
		, @entity_index			varchar(6)
		
		, @action_display		varchar(8)
		, @action_display_summary	varchar(16)
		, @action_report		varchar(7)
		, @action_report_summary	varchar(15)
		, @action_archive		varchar(8)
		
		, @summarytabname	varchar(10)  
		, @sqlstmt		varchar(600)
		, @ptntabcount		int
		, @distinctdatecount	int
		, @archdatetime		varchar(30)
		, @returnStatus		int 
		, @defaultselectlist	varchar(175) 
		, @defaultorderby	varchar(64) 
		, @whoami		varchar(50)
		, @msg			varchar(256)
	
	select 	  @whoami	= "sp_spaceusage_object_genoutput"

		, @entity_table	= "table"
		, @entity_index	= "index"

		, @action_display		= "display"
		, @action_display_summary	= "display summary"
		, @action_report		= "report"
		, @action_report_summary	= "report summary"
		, @action_archive		= "archive"

	select 	@distinctdatecount = count(distinct(ArchiveDateTime))
	from 	#spaceusageinfo
	where	IndexName like @iname

	/*
	** Sum over all the index and data layer space and 
	** display/report the summary details to the user.
	*/
	if @actionword in ( @action_display_summary, @action_report_summary )
	begin	-- {	-- summary mode
	
		if @entity_type = @entity_table
		begin	-- {	-- table summary
			
			select @summarytabname = "#summary1"

			select @defaultorderby = 
					"ORDER BY TableName, OwnerName, Type"
					+ ", ArchiveDateTime"

			if @order_by_clause is NULL
				select @order_by_clause = @defaultorderby
			
			select @select_list = case 
					  	when  @actionword=
							@action_report_summary
						  and @distinctdatecount>1
						then NULL
						else -- exclude ArchiveDateTime
						    "  OwnerName"
						  + ", TableName"
						  + ", Type"
						  + ", UsedPages"
						  + ", RsvdPages"
						  + ", ExpRsvdPages"
						  + ", PctBloatRsvdPages"
					      end
			
			-- 1. Create the summary table and get the data layer 
			--    information in one go. 
			--
			-- NOTE: Two spaces with Type is deliberate to make 
			-- enough space for the other type 'INDEX'.
			--
			select 	  ArchiveDateTime
				, OwnerName
				, TableName
				, Type = 'DATA  '
				, UsedPages
				, RsvdPages
				, ExpRsvdPages
				, PctBloatRsvdPages
			into	#summary1
			from	#spaceusageinfo
			where	IndId = 0
			
			if (@@error != 0)
				return (@@error)

			-- 2.1. Insert a row for indid = 255 (TEXT data).
			insert 	into 	#summary1
			select 	  ArchiveDateTime
				, OwnerName
				, TableName
				, Type = 'TEXT  '
				, UsedPages 
				, RsvdPages
				, ExpRsvdPages 
				, PctBloatRsvdPages 
			from	#spaceusageinfo
			where	IndId = 255

			if (@@error != 0)
				return (@@error)
		
			-- 2.2. Insert the summ of all index layers.
			insert into 	#summary1
			select distinct   ArchiveDateTime
					, OwnerName
					, TableName
					, Type = 'INDEX'
					, UsedPages = sum(UsedPages)
					, RsvdPages = sum(RsvdPages)
					, ExpRsvdPages = sum(ExpRsvdPages)
					, PctBloatRsvdPages = 0.0 
			from		#spaceusageinfo
			where		IndId > 0
			  and		IndId != 255
			group by	ArchiveDateTime,Id

			if (@@error != 0)
				return (@@error)

			-- 3. Compute the overall index layer percent bloat.
			update	#summary1
			set    	PctBloatRsvdPages = 
					(convert(float,(RsvdPages 
							- ExpRsvdPages))
					/RsvdPages)*100.0
			where	Type = 'INDEX'
			  and	RsvdPages > 0
			  
			if (@@error != 0)
				return (@@error)

		end	-- } 	-- table summary done!
		else 
		begin 	-- {	-- index summary

			select @summarytabname = "#summary2"

			select @defaultorderby = 
				"ORDER BY TableName, OwnerName, IndId" 
				+ ", ArchiveDateTime"
	
			if @order_by_clause is NULL
				select @order_by_clause = @defaultorderby
				
			select @select_list = case 
					  	when  @actionword=
							@action_report_summary
						  and @distinctdatecount > 1
						then NULL
						else -- exclude ArchiveDateTime
						    "  OwnerName"
						  + ", TableName"
						  + ", IndexName"
						  + ", IndId"
						  + ", UsedPages"
						  + ", RsvdPages"
						  + ", ExpRsvdPages"
						  + ", PctBloatRsvdPages"
					      end
			
			-- 1. Create the tempory summary index table.
			select 	  ArchiveDateTime
				, OwnerName
				, TableName
				, IndexName
				, IndId
				, UsedPages
				, RsvdPages
				, ExpRsvdPages
				, PctBloatRsvdPages
			into	#summary2
			from	#spaceusageinfo
			where 	1 = 0

			if (@@error != 0)
				return (@@error)

			-- 2. Get the index level information.
			select @sqlstmt =  " INSERT INTO #summary2 "
					 + " SELECT DISTINCT  ArchiveDateTime"
					 +		  ", OwnerName"
					 + 		  ", TableName"
					 +		  ", IndexName"
					 +		  ", IndId"
					 +		  ", UsedPages="
					 +		      "sum(UsedPages)"
					 +		  ", RsvdPages="
					 +		      "sum(RsvdPages)"
					 +		  ", ExpRsvdPages="
					 +		    "sum(ExpRsvdPages)"
					 +		  ", PctBloatRsvdPages="
					 +		    "convert(float, 0) "
					 + " FROM #spaceusageinfo "
					 + " WHERE IndexName LIKE '" + @iname 
					 				   + "'"
					 + " GROUP BY Id, IndId, ArchiveDateTime"
				
			exec @returnStatus = sp_exec_SQL @sqlstmt, @whoami
			
			if @returnStatus != 0
				return (@returnStatus)
						       
			-- 3. Compute the overall index layer percent bloat.
			update	#summary2
			set	PctBloatRsvdPages =
					(convert(float,(RsvdPages 
							- ExpRsvdPages))
					/RsvdPages)*100.0
			where	RsvdPages > 0
			
			if (@@error != 0)
				return (@@error)

		end 	-- } 	-- index summary done!
		
		-- 4. Display the output.

		-- Print information message regarding the unit specifier.
		exec sp_getmessage 19533, @msg out
		print @msg, @unit

		-- Print information message regarding the datetimestamp, if
		-- all data are dated same.
		--
		if 	@distinctdatecount = 1 
		    and @actionword = @action_report_summary
		begin
			select 	@archdatetime = max(ArchiveDateTime)
			from 	#spaceusageinfo
			where	IndexName like @iname
		
			exec sp_getmessage 19534, @msg out
			print @msg, @archdatetime
		end
	
		set NOCOUNT on

		exec @returnStatus = sp_autoformat @fulltabname=@summarytabname
						 , @selectlist = @select_list
						 , @whereclause= @where_clause
						 , @orderby   = @order_by_clause

		set NOCOUNT OFF
			
		if @returnStatus != 0
			return (@returnStatus)
		else 
			return (0)

	end	-- } 	-- summary mode done
	else
	begin	-- {	-- normal mode
	
		/*
		** Get the partitioned table count. If 0, we will skip PtnId 
		** column while reporting.
		*/
		select	@ptntabcount = count(*) 
		from	#spaceusageinfo
		where	Id != PtnId

		select @defaultselectlist = 	case 
						  when  @actionword=
						  		@action_report
						    and @distinctdatecount > 1
						  then "ArchiveDateTime, "
						  else ""
						end
						+
						"OwnerName, TableName, IndId"
						+ 
						case @entity_type
							when @entity_index 
							then ", IndexName"
							else ""
						end
						+
						case
						   when @ptntabcount != 0
						   then ", PtnId"
						   else ""
						end
						+ 
						case @entity_type
							when @entity_table 
							then ", NumRows"
							else ""
						end
						+
						+ ", UsedPages"
						+ ", RsvdPages, ExtentUtil"
						+ ", ExpRsvdPages"
						+ ", PctBloatUsedPages"
						+ ", PctBloatRsvdPages"

		select @defaultorderby = "ORDER BY TableName, OwnerName, IndId"
					+ case 
						when @ptntabcount != 0
						then ", PtnId"
						else ""
					  end
					+ ", ArchiveDateTime"
	
		if @select_list is NULL
		begin
			select @select_list = @defaultselectlist
		end
		else if ltrim(rtrim(@select_list)) = "*"
		begin
		
			-- We can not select all columns directly, as some of
			-- them are temporary placeholders for intermediate data
			-- and are not meant for display to the user. Hence, we
			-- explicitly select ALL the columns to display.
			--
			select @select_list =
				  " ArchiveDateTime, ServerName, MaxPageSize"
				+ ", DBName, OwnerName, TableName"
				+ ", Id, IndId, IndexName, PtnId, PtnName"
				+ ", DataPtnId, RowSize, NumRows, RowCount_ts"
				+ ", NumFwdRows, NumDelRows, EmptyPages"
				+ ", DataPages, UsedPages, RsvdPages, SpUtil"
				+ ", DPCR, DRCR, IPCR, LGIO, FF, MRPP, ERS"
				+ ", RPG, LeafPages, IndexHeight, OAMAPageCount"
				+ ", Extent0PageCount, Status, Sysstat"
				+ ", Sysstat2, NonLeafRowSize, ExpIndexHeight"
				+ ", ExpDataPages"
				+ ", ExpUsedPages, ExpRsvdPages, ExpLeafPages"
				+ ", PctBloatUsedPages, PctBloatRsvdPages"
				+ ", PctBloatLeafPages"
				+ ", ExtentUtil, PctEmptyPages, PctFwdRows"
				+ ", LockScheme, NumVarCols, HasAPLCI"
		end
		
		if @order_by_clause is NULL
			select @order_by_clause = @defaultorderby

		if @entity_type = @entity_index
		begin
			select @where_clause = @where_clause 
						+ case @where_clause
							when NULL
							then " WHERE "
							else " AND "
						  end
						+ " IndexName LIKE '" + @iname 
									   + "'"
		end
		
		-- Print information message regarding the unit specifier.
		exec sp_getmessage 19533, @msg out
		print @msg, @unit

		-- Print information message regarding the datetimestamp, if
		-- all data are dated same.
		--
		if 	@distinctdatecount = 1 
		    and @actionword = @action_report
		begin
			select 	@archdatetime = max(ArchiveDateTime)
			from 	#spaceusageinfo
			where	IndexName like @iname
		
			exec sp_getmessage 19534, @msg out
			print @msg, @archdatetime
		end
	
		set NOCOUNT on
		
		exec @returnStatus = sp_autoformat @fulltabname=#spaceusageinfo
						 , @selectlist = @select_list
						 , @whereclause= @where_clause
						 , @orderby = @order_by_clause

		set NOCOUNT OFF
	
		if @returnStatus != 0
			return (@returnStatus)
			
	end 	-- }	-- normal mode done!

end 	-- }	-- }
go

/*
**	SP_SPACEUSAGE_OBJECT_ARCHDATA
**
**	The sub-procedure that saves the space usage information in the
**	temporary table #spaceusageinfo into an archive table. This is
**	applicable only in case of "archive" action. It is possible to apply a
**	WHERE clause, if any, to selectively archive only the data of interest.
**	Called by sp_spaceusage_object.
**
**	Parameters
**		@archivetabname	- The 3-part name of the archive table.
**		@where_clause	- WHERE clause, if any, to select the data.
**		@entity_type	- Type of entity.
**		@iname		- Index name.
**
**	Note:	The @entity_type and @iname are passed because for entity type
**		"index" the #spaceusageinfo table has and adtitional data layer
**		row that qualifies even though they may not qualify (they may
**		qualify is the index name pattern included them) and are not
**		expected in the output result. They need to be filtered out
**		using the WHERE clause.
**
**	Returns
**		0 - if all goes well
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_object_archdata
(
	  @archivetabname	varchar(320)
	, @where_clause		varchar(1536)
	, @entity_type		varchar(12)
	, @iname		varchar(255)
)
as
begin	-- {	

	declare	  @entity_table		varchar(6)
		, @entity_index		varchar(6)
		
		, @sqlstmt		varchar(2600)
		, @returnStatus		int
		, @colsToArchive	varchar(660)
		, @whoami		varchar(50)
		, @msg			varchar(256)

	select 	  @whoami	= "sp_spaceusage_object_archdata"

		, @entity_table	= "table"
		, @entity_index	= "index"

	if @entity_type = @entity_index
	begin
		select @where_clause = @where_clause + case @where_clause 
							when NULL
							then " WHERE "
							else " AND "
						       end
					+ " IndexName LIKE '" + @iname + "'"
	end
	
	-- We do not want to archive all the columns, as some of them are 
	-- temporary placeholders for intermediate data and are not meant for 
	-- archiving. Hence, we explicitly select all the columns to archive.
	--
	select @colsToArchive =   "  VersionNum, ESDNum, EBFNum"
				+ ", ArchiveDateTime"
				+ ", ServerName, MaxPageSize"
				+ ", DBName, OwnerName, TableName"
				+ ", Id, IndId, IndexName, PtnId, PtnName"
				+ ", DataPtnId, RowSize, NumRows, RowCount_ts"
				+ ", NumFwdRows, NumDelRows, EmptyPageCount"
				+ ", DataPageCount, UsedPageCount"
				+ ", RsvdPageCount, SpUtil, DPCR, DRCR, IPCR"
				+ ", LGIO, FF, MRPP, ERS, RPG, LeafPageCount"
				+ ", IndexHeight, OAMAPageCount"
				+ ", Extent0PageCount, Status, Sysstat"
				+ ", Sysstat2, NonLeafRowSize, ExpIndexHeight"
				+ ", ExpDataPageCount"
				+ ", ExpUsedPageCount, ExpRsvdPageCount"
				+ ", ExpLeafPageCount, PctBloatUsedPages"
				+ ", PctBloatRsvdPages, PctBloatLeafPages"
				+ ", ExtentUtil, PctEmptyPages, PctFwdRows"
				+ ", LockScheme, NumVarCols, HasAPLCI"
				+ ", StatModDate"
		
	/* 
	** If archive table does not exist, create it by SELECTing
	** #spaceusageinfo  INTO int it. Else, INSERT #spaceusageinfo into it.
	*/
	if object_id(@archivetabname) is NULL
	begin
		select @sqlstmt =  " SELECT " + @colsToArchive 
				 + " INTO "   + @archivetabname 
				 + " FROM 	#spaceusageinfo "
				 +   @where_clause
	end
	else
	begin
		select @sqlstmt =  " INSERT INTO " + @archivetabname 
				 + " SELECT " 	   + @colsToArchive  
				 + " FROM 	     #spaceusageinfo "
				 +   @where_clause
	end

	exec @returnStatus = sp_exec_SQL @sqlstmt, @whoami

	if @returnStatus != 0
	begin 	
		return (@returnStatus)
	end
	else
	begin
		exec sp_getmessage 19535, @msg out
		print @msg, @archivetabname
		return (0)
	end
	
end 	-- }	-- }
go

drop table #spaceusageinfo
go

/*
**	SP_SPACEUSAGE_OBJECT
**
**	The driver procedure for the getting space usage information for entity
**	types - "table" and "index". Called by sp_spaceusage.
**
**	Parameters:
**		@actionword	- The action to be performed. 
**		@unit		- Unit for displaying page counts, if any.
**		@archive_db	- Name of the database where the archive table
**				  resides or will be created.
**		@archive_prefix - Prefix for the archive table name, if any.
**		@entity_type	- Type of entity. Can be "table"/"index".
**		@nouname	- Was no owner name provided by the user?
**		@uname		- Owner/user name.
**		@tname		- Table name.
**		@iname		- Index name.
**		@select_list	- Comma separated list of columns to project
**				  the output.
**		@where_clause	- A WHERE clause, if any, to filter the output.
**		@order_by_clause- An ORDER BY clause, to order the output.
**		@from_date	- Date, if any, from when on to look for data 
**				  in the archive table to generate report.
**		@to_date	- Date, if any, till when to look for data in 
**				  the archive table to generate report.
**	
**	Returns
**		0 - if all goes well
**		6 - archive table not found
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_object
(
	  @actionword		varchar(20)
	, @unit			varchar(6)	= NULL
	, @archive_db		varchar(30)	= NULL
	, @archive_prefix	varchar(238)	= NULL
	, @entity_type		varchar(12)
	, @nouname		bit		
	, @uname		varchar(255)
	, @tname		varchar(255)
	, @iname		varchar(255)
	, @select_list		varchar(1636)	= NULL
	, @where_clause		varchar(1536)	= NULL
	, @order_by_clause	varchar(768)	= NULL
	, @from_date		varchar(30)	= NULL
	, @to_date		varchar(30)	= NULL
	
)
as
begin	-- { 	

	declare
		  @returnStatus			int
		, @archivetabname		varchar(320)
		, @defaultarchivetabname	varchar(30)

		-- String constants for the entity type
		, @entity_table			varchar(6)
		, @entity_index			varchar(6)

		-- String constants for the action 
		, @action_display		varchar(8)
		, @action_display_summary	varchar(16)
		, @action_report		varchar(7)
		, @action_report_summary	varchar(15)
		, @action_archive		varchar(8)

	select	
		  @archivetabname = NULL
		, @defaultarchivetabname = "spaceusage_object"
		
		, @entity_table	= "table"
		, @entity_index	= "index"

		, @action_display		= "display"
		, @action_display_summary	= "display summary"
		, @action_report		= "report"
		, @action_report_summary	= "report summary"
		, @action_archive		= "archive"

	if @actionword not in (@action_display, @action_display_summary)
	begin	-- This is report/archive mode

		-- Verify that the archive database does exist.
		if not exists ( select 1 
				from master.dbo.sysdatabases
				where name like @archive_db )
		begin
			raiserror 18322, @archive_db
			return (6)
		end			

		select @archivetabname = @archive_db + "." + user_name() + "."
					 + case @archive_prefix
						when NULL
						then @defaultarchivetabname
						else @archive_prefix
							+ @defaultarchivetabname
					   end

		-- Verify the archive table does exist in the database for the
		-- report action.
		-- 
		if 	@actionword in (   @action_report
					 , @action_report_summary )
		    and object_id(@archivetabname) is NULL 
		begin
			declare @tmpname varchar(290)
			
			select @tmpname = user_name() + "." 
					+ case @archive_prefix
						when NULL
						then @defaultarchivetabname
						else @archive_prefix
							+ @defaultarchivetabname
					  end					
						
			raiserror 17870, @tmpname, @archive_db, NULL
			return (6)
		end
	end

	/* 
	** Create and initialize the temporary #spaceusageinfo table based on 
	** the action specified. For 'display'/'archive' action, the table is 
	** created by joining with system tables. For 'report' action, it is 
	** generated by selecting into it the relavant data from the archive 
	** table.
	**
	** NOTE: Any change done to this table needs a change in the
	** corresponding #spaceusageinfo table created at the beginning of the
	** file (at line #15). And the inserts that are done in the procedure
	** sp_spaceusage_object_init (at lines #147, 284, 375).
	*/
	create table #spaceusageinfo
	(
	  	  VersionNum		int		NOT NULL
		, ESDNum		int		NOT NULL
		, EBFNum		int		NOT NULL
		, ArchiveDateTime	datetime	NOT NULL
		, ServerName		varchar(255)	NULL
		, MaxPageSize		int		NOT NULL
		, DBName		varchar(30)	NOT NULL
		, OwnerName		varchar(30)	NOT NULL
		, TableName		varchar(255)	NOT NULL
		, Id			int		NOT NULL
		, IndId			smallint	NOT NULL
		, IndexName		varchar(255)	NULL
		, PtnId			int		NOT NULL
		, PtnName		varchar(255)	NOT NULL
		, DataPtnId		int		NOT NULL
		, RowSize		float		NULL
		, NumRows		float		NULL
		, RowCount_ts		float		NULL
		, NumFwdRows		float		NULL
		, NumDelRows		float		NULL
		, EmptyPageCount	int		NULL
		, DataPageCount		int		NULL
		, UsedPageCount		int		NULL
		, RsvdPageCount		int		NULL
		, SpUtil		decimal(9,2)	NULL
		, DPCR			decimal(5,4)	NULL
		, DRCR			decimal(5,4)	NULL
		, IPCR			decimal(5,4)	NULL
		, LGIO			decimal(5,4)	NULL
		, FF			smallint	NULL
		, MRPP			smallint	NULL
		, ERS			smallint	NULL
		, RPG			smallint	NULL
		, LeafPageCount		int		NULL
		, IndexHeight		smallint	NULL
		, OAMAPageCount		int		NULL
		, Extent0PageCount	int		NULL
		, Status		int		NULL
		, Sysstat		smallint	NOT NULL
		, Sysstat2		int		NOT NULL
		, NonLeafRowSize	decimal(10,4)	NULL
		, ExpIndexHeight	smallint	NULL
		, ExpDataPageCount	int		NULL
		, ExpUsedPageCount	int		NULL
		, ExpRsvdPageCount	int		NULL
		, ExpLeafPageCount	int		NULL
		, PctBloatUsedPages	decimal(7,2)	NULL
		, PctBloatRsvdPages	decimal(7,2)	NULL
		, PctBloatLeafPages	decimal(7,2)	NULL
		, ExtentUtil		decimal(5,2)	NULL
		, PctEmptyPages		decimal(5,2)	NULL
		, PctFwdRows		decimal(5,2)	NULL
		, LockScheme		tinyint		NOT NULL
		, NumVarCols		smallint	NOT NULL
		, HasAPLCI		bit		NOT NULL
		, StatModDate		date		NULL
		, SpacePerPage		float		NULL
		, CalcRowsPerPage	float		NULL
		, EmptyPages		float		NULL
		, DataPages		float		NULL
		, UsedPages		float		NULL
		, RsvdPages		float		NULL
		, LeafPages		float		NULL
		, ExpDataPages		float		NULL
		, ExpUsedPages		float		NULL
		, ExpRsvdPages		float		NULL
		, ExpLeafPages		float		NULL
	)

	if (@@error != 0)
		return (@@error)
	
	exec @returnStatus = sp_spaceusage_object_init 	  @actionword
							, @nouname
							, @uname
							, @tname
							, @iname
							, @entity_type
							, @archivetabname
							, @from_date
							, @to_date

	if @returnStatus != 0
		return (@returnStatus)
	
	/* 
	** Populate the #spaceusageinfo table that was created and initialized 
	** only with raw data in case of display/archive action.
	*/
	if @actionword	in (   @action_display
			     , @action_display_summary
			     , @action_archive )
	begin 	-- {	
	
		exec @returnStatus = sp_spaceusage_object_populate

		if @returnStatus != 0
			return (@returnStatus)

	end 	-- } 

	/*
	** Depending on the unit specifier, convert the page counts into the
	** appropriate data type before display.
	**
	** NOTE: Although, archive mode ideally would only archive the value
	** in pages, it may have a WHERE clause on these computed columns for
	** which it requires these converted values.
	*/
	exec @returnStatus = sp_spaceusage_cnvtounit @unit, "#spaceusageinfo"

	if @returnStatus != 0
		return (@returnStatus)

	/* 
	** Now, display/archive the information collected and computed to the 
	** user based on the action. For display/report the user expects to see
	** the output on screen. And for archive action the user expects the 
	** output to be appended to the archive table.
	*/
	if @actionword in (   @action_display
			    , @action_display_summary
			    , @action_report
			    , @action_report_summary )
	begin	-- {

		exec @returnStatus = sp_spaceusage_object_genoutput
							  @actionword
							, @unit
							, @entity_type
							, @iname
							, @select_list
							, @where_clause
							, @order_by_clause

		if @returnStatus != 0
			return (@returnStatus)
		
	end	-- }
	else if @actionword = @action_archive
	begin	-- {
		
		exec @returnStatus = sp_spaceusage_object_archdata 
							  @archivetabname
							, @where_clause
							, @entity_type
							, @iname

		if @returnStatus != 0
			return (@returnStatus)
		
	end 	-- }

	drop table #spaceusageinfo

end	-- }	-- }
go
go
exec sp_procxmode 'sp_spaceusage_object_init', 'anymode'
go
grant execute on sp_spaceusage_object_init to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_object_populate', 'anymode'
go
grant execute on sp_spaceusage_object_populate to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_object_genoutput', 'anymode'
go
grant execute on sp_spaceusage_object_genoutput to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_object_archdata', 'anymode'
go
grant execute on sp_spaceusage_object_archdata to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_object', 'anymode'
go
grant execute on sp_spaceusage_object to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_tranlog_init')
begin
	drop procedure sp_spaceusage_tranlog_init
end
go
print "Installing sp_spaceusage_tranlog_init"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_tranlog_genoutput')
begin
	drop procedure sp_spaceusage_tranlog_genoutput
end
go
print "Installing sp_spaceusage_tranlog_genoutput"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_tranlog_archdata')
begin
	drop procedure sp_spaceusage_tranlog_archdata
end
go
print "Installing sp_spaceusage_tranlog_archdata"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage_tranlog')
begin
	drop procedure sp_spaceusage_tranlog
end
go
print "Installing sp_spaceusage_tranlog"
go

/*
** Generated by spgenmsgs.pl on Tue Oct 31 23:35:59 2006 
*/
/*
** raiserror Messages for spaceusage_tranlog [Total 3]
**
** 17870, "Table '%1!' does not exist in database '%2!'. %3!"
** 18322, "There is not a database named '%1!'."
** 19576, "No match found for transaction log %1! for database '%2!'."
*/
/*
** sp_getmessage Messages for spaceusage_tranlog [Total 3]
**
** 19533, "All the page counts in the result set are in the unit '%1!'."
** 19534, "All the data in the result set are dated '%1!'."
** 19535, "Data was successfully archived into table '%1!'."
*/
/*
** End spgenmsgs.pl output.
*/
/*
** All the following procedures have reference to the #syslogsinfo table. So,
** create the dummy table so that we can install/load the following sprocs.
**
** NOTE: Any change done to this table needs a change in the corresponding 
** #syslogsinfo table created in the procedure sp_spaceusage_tranlog towards 
** the end of the file (at line #570). And the inserts that are done in the 
** procedure sp_spaceusage_tranlog_init (at lines #116, 209).
*/
if object_id("#syslogsinfo") is not NULL
	drop table #syslogsinfo
go

create table #syslogsinfo
(
	  VersionNum		int		NOT NULL
	, ESDNum		int		NOT NULL
	, EBFNum		int		NOT NULL
	, ArchiveDateTime	datetime	NOT NULL
	, ServerName		varchar(255)	NULL
	, MaxPageSize		int		NOT NULL
	, DBName		varchar(30)	NOT NULL
	, OwnerName		varchar(30)	NOT NULL
	, TableName		varchar(255)	NOT NULL
	, Id			int		NOT NULL
	, NumRows		int		NULL
	, IsMLD			bit		NOT NULL
	, IsLogFull		bit		NOT NULL
	, LCTPageCount		int		NULL
	, TotalPageCount	int		NULL
	, RsvdPageCount		int 		NULL
	, CLRPageCount		int		NULL
	, UsedPageCount		int 		NULL
	, FreePageCount		int		NULL
	, PctFreePages		decimal(5,2)	NULL
	, PctUsedPages		decimal(5,2)	NULL
	, LCTPages		float		NULL
	, TotalPages		float		NULL
	, RsvdPages		float		NULL
	, CLRPages		float		NULL
	, UsedPages		float 		NULL
	, FreePages		float		NULL
)
go

if (@@error != 0) select syb_quit() 
go

/*
**	SP_SPACEUSAGE_TRANLOG_INIT
**
**	The sub-procedure that initializes the temporary table #syslogsinfo
**	with space usage information depending on the action. For "display" or
**	or "archive" action, it gets data using the lct_admin() built-in
**	and system tables and loads into #syslogsinfo (any other derived data,
**	if needed, will have to be computed in the next step to make the
**	information complete) whereas for the action "report", the data in the
**	archive table is loaded into the #syslogsinfo table. Called by 
**	sp_spaceusage_tranlog.
**
**	Parameters
**		@actionword	- The action to be performed.
**		@archivetabname	- The 3-part archive table name.
**		@from_date	- Date from when on to get archived data.
**		@to_date	- Date till which to get archvied data.
**
**	Returns
**		0 - if all goes well
**		6 - archive table not found
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_tranlog_init
(
	  @actionword		varchar(20)
	, @archivetabname	varchar(320) = NULL
	, @from_date		varchar(30) = NULL
	, @to_date		varchar(30) = NULL
)
as
begin 	-- {

	declare	  @action_display	varchar(8)  
		, @action_report	varchar(7)
		, @action_archive	varchar(8)
		
		, @esdnumstr		varchar(20)
		, @ebfnumstr		varchar(20)
		, @esdnum		int
		, @ebfnum		int

		, @ismld		bit
		, @totalpages 		int

		, @returnStatus		int
		, @sqlstmt		varchar(4096)
		, @whoami		varchar(40)
		, @msg			varchar(256)
		
	
	select	  @whoami	= "sp_spaceusage_tran_init"
	
		, @action_display		= "display"
		, @action_report		= "report"
		, @action_archive		= "archive"	

	/* Extract the ESD number and the EBF number from the version string.*/
	exec sp_versioncrack @@version, "ESD", @esdnumstr out, @esdnum out
	exec sp_versioncrack @@version, "EBF", @ebfnumstr out, @ebfnum out
	
	if @actionword in ( @action_display, @action_archive )	
	begin	-- { 	-- Display/Archive mode
	
		/* Collect all the necessary raw data or meta data. */
		select	@ismld = case (status2 & 32768) 
					when 32768 then 1
					else 0
				 end
		from	master.dbo.sysdatabases 
		where 	dbid = db_id()

		select 	@totalpages = sum(size)
		from 	master.dbo.sysusages
		where	dbid = db_id()
		  and	segmap & 4 = 4

		insert	into #syslogsinfo
		select	
	  		  VersionNum	 = @@version_number 
			, ESDNum	 = @esdnum 
			, EBFNum	 = @ebfnum
			, ArchiveDateTime = getdate() 
			, ServerName 	  = @@servername 
			, MaxPageSize 	  = @@maxpagesize
			, DBName 	  = db_name()
			, OwnerName 	  = "dbo"
			, TableName	  = "syslogs"
			, Id 		  = object_id("syslogs")
		
			-- This is a placeholder for the number of rows in
			-- syslogs. syslogs does not have an oam and thus
			-- getting this value is, currently, expensive. This
			-- column may be used in future.
			-- 
			, NumRows	  = 0

			-- Is the log mixed with data?
			, IsMLD 	  = @ismld 
			
			-- Is the log full (crossed LCT)?
			, IsLogFull = 
				convert(bit, lct_admin("logfull", db_id()))

			-- The current value for the LCT in pages.
			, LCTPageCount   = lct_admin("reserve", 0) 
			
			-- Total pages available for the log. 
			, TotalPageCount  = @totalpages

			-- This is a placeholder for the number of pages
			-- reserved for log in the database as is returned by
			-- the reserved_pages() built-in. The built-in uses an
			-- expensive allocation page scan to get this value. 
			-- This column may be used in future.
			--
			, RsvdPageCount = 0
				
			-- Pages reserved for rollback.
			, CLRPageCount = 
				lct_admin("reserved_for_rollbacks", db_id())

			-- The number of transaction log pages as of now. It is
			-- initially set to 0 and will be updated in the next
			-- step as it may depend on the TotalPageCount and 
			-- FreePageCount columns. 
			, UsedPageCount = 0 

			-- The number of pages free for future log.
			, FreePageCount = 
				lct_admin("logsegment_freepages", db_id())

			-- Percentage free/used pages (derived columns)
			, PctFreePages = convert(numeric(5,2), 0)
			, PctUsedPages = convert(numeric(5,2), 0) 

			-- The placeholder for pagecounts in units. 
			, LCTPages   = convert(float, 0) 
			, TotalPages = convert(float, 0) 
			, RsvdPages  = convert(float, 0) 
			, CLRPages   = convert(float, 0) 
			, UsedPages  = convert(float, 0) 
			, FreePages  = convert(float, 0) 
			
		if (@@error != 0)
			return (@@error)
		
		-- Update page counts that are dependant on other page counts.
		update	#syslogsinfo
		set	FreePageCount = FreePageCount - CLRPageCount
		where 	CLRPageCount > 0

		update 	#syslogsinfo
		set	UsedPageCount = 
				case IsMLD
					when 1 
					then lct_admin("num_logpages", db_id())
					     + 	-- Count the allocation pages.
					     TotalPageCount/256.0
					else TotalPageCount - FreePageCount
						- CLRPageCount
				end

		-- Update the percentage value for the used and free pages. 
		update	#syslogsinfo
		set	  PctFreePages = convert(numeric(5,2), 
						FreePageCount*100.0
						/TotalPageCount)
			, PctUsedPages = convert(numeric(5,2),
						UsedPageCount*100.0
						/TotalPageCount)
		where	TotalPageCount > 0

		if (@@error != 0)
			return (@@error)
	
	end 	-- }	-- Display/Archive mode
	
	else if @actionword = @action_report
	
	begin	-- {	-- Report action

		-- Check for valid archive table name is already done.

		select @sqlstmt =  " INSERT INTO #syslogsinfo "
				 + " SELECT 	 * "
				 +		", LCTPages"    + "=0"
				 +		", TotalPages"  + "=0"
				 +		", RsvdPages"   + "=0"
				 +		", CLRPages"	+ "=0" 
				 +		", UsedPages"	+ "=0"
				 +		", FreePages"	+ "=0"
				 + " FROM " +	@archivetabname + " o "
				 + " WHERE DBName LIKE '" + db_name() + "'"

		-- The ArchiveDateTime part of the query does the following.
		-- When both @from_date and @to_date are NULL, it looks for the
		-- latest ArchiveDateTime for each object that qualifies and
		-- selects that entry into the #syslogsinfo table. If only
		-- @from_date is NULL, it selects all data till @to_date. And
		-- when only @to_date is missing, it assumes @to_date to be
		-- today.
		--
		if @from_date is NULL
		begin
			if @to_date is NULL
			begin	-- both dates are null
				select @sqlstmt = @sqlstmt 
						+ " AND ArchiveDateTime "
						+ " = (SELECT "
						+	"max(ArchiveDateTime)"
						+ " FROM " + @archivetabname 
						+ 			" i2 "
						+ " WHERE i2.DBName=o.DBName"
						+   " AND i2.OwnerName"
						+		"=o.OwnerName"
						+   " AND i2.TableName"
						+		"=o.TableName"
						+   " AND (i2.ServerName is NULL"
						+   	  " or i2.ServerName"
						+		"=o.ServerName)"
						+ ")"

			end
			else
			begin	-- only from_date is null
				select @sqlstmt = @sqlstmt
						+ " AND ArchiveDateTime "
						+ " <= '" + @to_date + "'"
			end
		end
		else
		begin
			if @to_date is NULL
			begin	-- only to_date is null
				select @sqlstmt = @sqlstmt
						+ " AND ArchiveDateTime "
						+ " >= '" + @from_date + "'"
						+ " AND ArchiveDateTime "
						+ " <= getdate()"
			end
			else
			begin	-- both dates are non-null
				select @sqlstmt = @sqlstmt
						+ " AND ArchiveDateTime "
						+ " >= '" + @from_date + "'"
						+ " AND ArchiveDateTime "
						+ " <= '" + @to_date + "'"
			end
		end

		exec @returnStatus = sp_exec_SQL @sqlstmt, @whoami 

		if @returnStatus != 0
			return (@returnStatus)

	end	-- } 	-- Report action 

	-- If no row in #syslogsinfo, no object qualified and hence report an
	-- error message indicating the same and return back.
	--
	if not exists ( select 1 from #syslogsinfo )
	begin
		declare	 @tmpdbname 	varchar(30)
		select 	 @tmpdbname	= db_name()

		raiserror 19576, "'syslogs'", @tmpdbname
		return (7)
	end	
	return (0)
	
end 	-- }	-- }
go

/*
**	SP_SPACEUSAGE_TRANLOG_GENOUTPUT
**	
**	The sub-procedure that prints on screen the space usage information on
**	the transaction log. It would apply the SELECT list, WHERE clause and 
**	ORDER BY clause on the base table #syslogsinfo if the user has supplied
**	any. Else, it will use the default value for these. This is applicable 
**	only for "display" and "report" actions. Called by
**	sp_spaceusage_tranlog.
**
**	Parameters
**		@actionword 	- The action to be performed.
**		@unit		- Unit for the page counts.
**		@select_list	- Select list, if any, to project the ouput.
**		@where_clause 	- Where clause, if any, to select the output.
**		@order_by_clause- Order by clause, if any, to order the output.
**
**	Returns
**		0 - if all goes well
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_tranlog_genoutput
(
		  @actionword		varchar(20)
		, @unit			varchar(6)
		, @select_list		varchar(1536)
		, @where_clause		varchar(1536)
		, @order_by_clause	varchar(768)
)
as
begin	-- {	

	declare	 
		  @action_display		varchar(8)
		, @action_report		varchar(7)
		
		, @distinctdatecount	int
		, @archdatetime		varchar(30)
		, @returnStatus		int 
		, @defaultselectlist	varchar(116) 
		, @defaultorderby	varchar(50) 
		, @whoami		varchar(50)
		, @msg			varchar(256)
	
	select 	  @whoami	= "sp_spaceusage_tranlog_genoutput"

		, @action_display	= "display"
		, @action_report	= "report"
		
	select 	@distinctdatecount = count(distinct(ArchiveDateTime))
	from 	#syslogsinfo

	select @defaultselectlist = case 
					when   @actionword = @action_report
					   and @distinctdatecount > 1
					then "ArchiveDateTime, "
					else ""
				    end
				    + " TableName, TotalPages, UsedPages"
				    + ", CLRPages, FreePages, PctUsedPages"
				    + ", PctFreePages"

	select @defaultorderby = 
			"order by TableName, OwnerName, ArchiveDateTime"
	
	if @select_list is NULL
	begin
		select @select_list = @defaultselectlist
	end
	else if ltrim(rtrim(@select_list)) = "*"
	begin
		select @select_list = 
			  " ArchiveDateTime, ServerName, MaxPageSize, DBName"
			+ ", OwnerName, TableName, Id, IsMLD, IsLogFull"
			+ ", LCTPages, TotalPages, CLRPages, UsedPages"
			+ ", FreePages, PctFreePages, PctUsedPages"

	end
	
	if @order_by_clause is NULL
		select @order_by_clause = @defaultorderby

	set NOCOUNT on
	
	exec sp_getmessage 19533, @msg out
	print @msg, @unit

	if @distinctdatecount = 1 and @actionword = @action_report
	begin
		select 	@archdatetime = max(ArchiveDateTime)
		from 	#syslogsinfo
		
		exec sp_getmessage 19534, @msg out
		print @msg, @archdatetime
	end
	
	exec @returnStatus = sp_autoformat @fulltabname=#syslogsinfo
					 , @selectlist = @select_list
					 , @whereclause= @where_clause
					 , @orderby = @order_by_clause

	set NOCOUNT off
	
	if @returnStatus != 0
		return (@returnStatus)
	
	return (0)

end 	-- }	-- }
go

/*
**	SP_SPACEUSAGE_TRANLOG_ARCHDATA
**
**	The sub-procedure that saves the space usage information in the
**	temporary table #syslogsinfo into an archive table. This is
**	applicable only in case of "archive" action. It is possible to apply a
**	WHERE clause, if any, to selectively archive only the data of interest.
**	Called by sp_spaceusage_tranlog.
**
**	Parameters
**		@archivetabname	- The 3-part name of the archive table.
**		@where_clause	- Where clause, if any, to select the data.
**
**	Returns
**		0 - if all goes well
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_tranlog_archdata
(
	  @archivetabname	varchar(320)
	, @where_clause		varchar(1536)
)
as
begin	-- {	

	declare	  @sqlstmt		varchar(2048)
		, @returnStatus		int
		, @whoami		varchar(50)
		, @msg			varchar(256)
		, @colsToArchive	varchar(256)

	select 	  @whoami	= "sp_spaceusage_tranlog_archdata"

	/* Explicitly set the list of  columns to archive. */
	select	@colsToArchive =   "  VersionNum, ESDNum, EBFNum"
				 + ", ArchiveDateTime, ServerName, MaxPageSize"				  
				 + ", DBName, OwnerName, TableName, Id, NumRows"
				 + ", IsMLD, IsLogFull, LCTPageCount"
				 + ", TotalPageCount, RsvdPageCount"
				 + ", CLRPageCount, UsedPageCount"
				 + ", FreePageCount, PctFreePages, PctUsedPages"

	/* 
	** If archive table does not exist, create it by SELECTing
	** #syslogsinfo INTO int it. Else, INSERT #syslogsinfo into it.
	*/
	if object_id(@archivetabname) is NULL
	begin
		select @sqlstmt =  " SELECT " + @colsToArchive
				 + " INTO " + @archivetabname 
				 + " FROM   #syslogsinfo "
				 +   @where_clause
	end
	else
	begin
		select @sqlstmt =  " INSERT INTO " + @archivetabname 
				 + " SELECT " + @colsToArchive
				 + " FROM   #syslogsinfo "
				 +   @where_clause
	end

	exec @returnStatus = sp_exec_SQL @sqlstmt, @whoami

	if @returnStatus != 0
	begin 	
		return (@returnStatus)
	end
	else
	begin
		exec sp_getmessage 19535, @msg out
		print @msg, @archivetabname
		return (0)
	end
	
end 	-- }	-- }
go

drop table #syslogsinfo
go

/*
**	SP_SPACEUSAGE_TRANLOG
**
**	The driver procedure for the getting space usage information for entity
**	type - "tranlog" (transaction log). Called by sp_spaceusage.
**
**	Parameters:
**		@actionword	- The action to be performed. 
**		@unit		- Unit for displaying page counts, if any.
**		@archive_db	- Name of the database where the archive table
**				  resides or will be created.
**		@archive_prefix - Prefix for the archive table name, if any.
**		@select_list	- Comma separated list of columns to project
**				  the output.
**		@where_clause	- A WHERE clause, if any, to filter the output.
**		@order_by_clause- An ORDER BY clause, to order the output.
**		@from_date	- Date, if any, from when on to look for data 
**				  in the archive table to generate report.
**		@to_date	- Date, if any, till when to look for data in 
**				  the archive table to generate report.
**	
**	Returns
**		0 - if all goes well
**		6 - archive table not found
**	    other - error while execution 
{
*/
create procedure sp_spaceusage_tranlog
(
	  @actionword		varchar(20)
	, @unit			varchar(6)	= NULL
	, @archive_db		varchar(30)	= NULL
	, @archive_prefix	varchar(237)	= NULL
	, @select_list		varchar(1536)	= NULL
	, @where_clause		varchar(1536)	= NULL
	, @order_by_clause	varchar(768)	= NULL
	, @from_date		varchar(30)	= NULL
	, @to_date		varchar(30)	= NULL
	
)
as
begin	-- { 	

	declare
		  @returnStatus			int
		, @archivetabname		varchar(320)
		, @defaultarchivetabname	varchar(30)

		-- String constants for the action 
		, @action_display		varchar(8)
		, @action_report		varchar(7)
		, @action_archive		varchar(8)

	select	
		  @archivetabname = NULL
		, @defaultarchivetabname = "spaceusage_tranlog"
		
		, @action_display		= "display"
		, @action_report		= "report"
		, @action_archive		= "archive"

	if @actionword in (@action_report, @action_archive)
	begin	-- This is report/archive mode
	
		-- Verify that the archive database does exist.
		if not exists ( select 1 
				from master.dbo.sysdatabases
				where name like @archive_db )
		begin
			raiserror 18322, @archive_db
			return (6)
		end			

		select @archivetabname = @archive_db + "." + user_name() + "."
					 + case @archive_prefix
						when NULL
						then @defaultarchivetabname
						else @archive_prefix
							+ @defaultarchivetabname
					   end
					   
		-- Verify the archive table does exist in the database for the
		-- report action.
		-- 
		if 	@actionword = @action_report
		    and object_id(@archivetabname) is NULL 
		begin
			declare @tmpname varchar(290)
			
			select @tmpname = user_name() + "." 
					+ case @archive_prefix
						when NULL
						then @defaultarchivetabname
						else @archive_prefix
							+ @defaultarchivetabname
					  end					
						
			raiserror 17870, @tmpname, @archive_db, NULL
			return (6)
		end
	end

	/* 
	** Create and initialize the temporary #syslogsinfo table based on 
	** the action specified. For 'display'/'archive' action, the table is 
	** inserted with a single row for the current state of the syslgos using
	** the lct_admin() built-ins. For 'report' action, the table is
	** populated by selecting into it the relavant data from the archive 
	** table.
	**
	** NOTE: Any change done to this table needs a change in the
	** corresponding #syslogsinfo table created at the beginning of the
	** file (at line #15). And the inserts that are done in the procedure
	** sp_spaceusage_tranlog_init (at lines #116, 209).
	*/
	create table #syslogsinfo
	(
	  	  VersionNum		int		NOT NULL
		, ESDNum		int		NOT NULL
		, EBFNum		int		NOT NULL
		, ArchiveDateTime	datetime	NOT NULL
		, ServerName		varchar(255)	NULL
		, MaxPageSize		int		NOT NULL
		, DBName		varchar(30)	NOT NULL
		, OwnerName		varchar(30)	NOT NULL
		, TableName		varchar(255)	NOT NULL
		, Id			int		NOT NULL
		, NumRows		int		NULL
		, IsMLD			bit		NOT NULL
		, IsLogFull		bit		NOT NULL
		, LCTPageCount		int		NULL
		, TotalPageCount	int		NULL
		, RsvdPageCount		int 		NULL
		, CLRPageCount		int		NULL
		, UsedPageCount		int 		NULL
		, FreePageCount		int		NULL
		, PctFreePages		decimal(5,2)	NULL
		, PctUsedPages		decimal(5,2)	NULL
		, LCTPages		float		NULL
		, TotalPages		float		NULL
		, RsvdPages		float		NULL
		, CLRPages		float		NULL
		, UsedPages		float 		NULL
		, FreePages		float		NULL
	)

	if (@@error != 0)
		return (@@error)
	
	exec @returnStatus = sp_spaceusage_tranlog_init   @actionword
							, @archivetabname
							, @from_date
							, @to_date

	if @returnStatus != 0
		return (@returnStatus)
	
	/*
	** Depending on the unit specifier, convert the page counts into the
	** appropriate data type before display.
	**
	** NOTE: Although, archive mode ideally would only archive the value
	** in pages, it may have a WHERE clause on these computed columns for
	** which it requires these converted values.
	*/
	exec @returnStatus = sp_spaceusage_cnvtounit @unit, "#syslogsinfo"

	if @returnStatus != 0
		return (@returnStatus)

	/* 
	** Now, display/archive the information collected and computed to the 
	** user based on the action. For display/report the user expects to see
	** the output on screen. And for archive action the user expects the 
	** output to be appended to the archive table.
	*/
	if @actionword in ( @action_display, @action_report)
	begin	-- {

		exec @returnStatus = sp_spaceusage_tranlog_genoutput
						  @actionword
						, @unit
						, @select_list
						, @where_clause
						, @order_by_clause

		if @returnStatus != 0
			return(@returnStatus)
		
	end	-- }
	else if @actionword = @action_archive
	begin	-- {
		
		exec @returnStatus = sp_spaceusage_tranlog_archdata 
							  @archivetabname
							, @where_clause

		if @returnStatus != 0
			return (@returnStatus)
		
	end 	-- }

	drop table #syslogsinfo

end	-- }	-- }
go
go
exec sp_procxmode 'sp_spaceusage_tranlog_init', 'anymode'
go
grant execute on sp_spaceusage_tranlog_init to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_tranlog_genoutput', 'anymode'
go
grant execute on sp_spaceusage_tranlog_genoutput to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_tranlog_archdata', 'anymode'
go
grant execute on sp_spaceusage_tranlog_archdata to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_spaceusage_tranlog', 'anymode'
go
grant execute on sp_spaceusage_tranlog to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_spaceusage')
begin
	drop procedure sp_spaceusage
end
go
print "Installing sp_spaceusage"
go

/*
** Generated by spgenmsgs.pl on Mon Nov 20 03:34:15 2006 
*/
/*
** raiserror Messages for spaceusage [Total 4]
**
** 17993, "'%1!' is not a valid argument."
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
** 19491, "Archive prefix name '%1!' cannot exceed %2! bytes as this can cause the extended name of the archive table to be an invalid identifier."
** 19530, "Argument '%1!' is invalid with argument '%2!'. Type '%3!' for usage information."
*/
/*
** sp_getmessage Messages for spaceusage [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
/*
**	 SP_SPACEUSAGE
**
** 	Driver interface to get space usage information on different types of 
** 	enitities. This will in turn call the entity and action specific 
**	sub-procedures.
**
**	Parameters
**		@action	- The action to be performed. The using_clause, if any,
**			  is part of this string. The real action keyword is 
**			  extracted from this string.
**		@arg1	- This is:
**			   o action word on which help is sought, if @action = 
**			     "help".
**			   o entity type string.
**		@arg2	- This is:
**			   o entity type string, if @action = "help".
**			   o entity name identifier pattern string.
**		@optarg1- This optional argument can be:
**			   o SELECT list to project the result set for 'display'
**			     or 'report' action word.
**			   o WHERE clause to filter the result set otherwise.
**		@optarg2- This optional argument can be:
**			   o WHERE clause to filter the result set for 'display'
**			     or 'report' action word.
**			   o ORDER BY clause to order the result set for 
**			     'display summary' or 'report summary' action word.
**			   o command to run on the table for 'archive' action
**			     word.
**		@optarg3- This optional argument can be:
**			   o ORDER BY clause to order the result set for 
**			     'display' or 'report' action word.
**			   o command to run on the table for 'display summary'
**			     action word.
**			   o archive date from when on to get data for 'report
**			     summary' action word.
**			   o ignored otherwise.
**		@optarg4- This optional argument can be:
**			   o command to run on the table for 'display' action 
**			     word.
**			   o archive date from when on to get data for 'report'
**			     action word.
**			   o archive date till when to get data for 'report
**			     summary' action word.
**			   o ignored otherwise.
**		@optarg5- This optional argument can be:
**			   o archive date till when to get data for 'report' 
**			     action word.
**			   o ignored otherwise.
**				
**	Returns
**		0 - if all goes well
**		1 - invalid action
**		2 - invalid entity type
**		3 - invalid entity name
**		4 - invalid command
**		5 - invalid USING clause
**		6 - archive table not found
**		7 - invalid datetime format [from_date/to_date]
**		8 - invalid SELECT list, WHERE clause or ORDER BY clause
**	    other - error while execution 
{
*/
create procedure sp_spaceusage 
(
	  @action	varchar(350)	= NULL
	, @arg1		varchar(20)	= NULL
	, @arg2		varchar(550)	= NULL
	, @optarg1	varchar(1536)	= NULL
	, @optarg2	varchar(1536)	= NULL
	, @optarg3	varchar(768)	= NULL
	, @optarg4	varchar(100)	= NULL
	, @optarg5	varchar(30)	= NULL
)
as
begin	-- { 	

	declare 
		  @entity_type			varchar(12)
		, @entity_name			varchar(550)
		, @select_list			varchar(1536)
		, @where_clause			varchar(1536)
		, @orderby_clause		varchar(768)
		, @command			varchar(100)
		, @from_date			varchar(30)
		, @to_date			varchar(30)
		
		, @actionword			varchar(20)
		, @action_help			varchar(5)
		, @action_archive		varchar(10) 
		, @action_display		varchar(10) 
		, @action_display_summary	varchar(20)
		, @action_report		varchar(10)
		, @action_report_summary	varchar(20) 

		, @uname			varchar(255)
		, @tname			varchar(255)
		, @iname			varchar(255)
		, @tmpname			varchar(255)
		, @tmpname2			varchar(255)
		, @archive_db			varchar(30) 
		, @archive_prefix		varchar(255)
		, @unit				varchar(6)
		, @maxtabnamelen		int
		, @maxtranlogprefix		int
		, @maxobjectprefix		int
		
		, @entity_table			varchar(6)
		, @entity_index			varchar(6)
		, @entity_tranlog		varchar(8)
		, @entity_database		varchar(9)		
		, @valid_actions		varchar(75)
		, @valid_entity_types		varchar(30)	

		, @archive_table_name		varchar(320)
		, @using_clause			varchar(350)
		, @left_substr			varchar(350)
		, @right_substr			varchar(350)
		, @usingIndex			int
		, @returnStatus			int
		, @commaPos			int
		, @nouname			bit
	
		, @msg				varchar(256)

	select 
		  @action_help			= "help"
		, @action_archive		= "archive"
		, @action_display		= "display"
		, @action_display_summary	= "display summary"
		, @action_report		= "report"
		, @action_report_summary	= "report summary"
		
		, @entity_table			= "table"
		, @entity_index			= "index"
		, @entity_tranlog		= "tranlog"
	
		, @usingIndex		= 0
		, @unit			= "KB"
		, @archive_db		= db_name()
		, @nouname		= 0

	/* Get the maximum length of a table name. */
	select	@maxtabnamelen = c.length
	from 	master..syscolumns c
	where	c.id 	= object_id('sysobjects')
	  and	c.name	= 'name'

	/* Get the maximum length allowed for the prefizx strenth. */
	select	  @maxtranlogprefix = @maxtabnamelen 
					- datalength("spaceusage_tranlog")
		, @maxobjectprefix  = @maxtabnamelen
					- datalength("spaceusage_object")
	
	select	
		  @valid_entity_types	= "'" + @entity_table 
					  + "', '" + @entity_index 
					  + "', '" + @entity_tranlog 
					  + "'"
						  
		, @valid_actions	= "'" + @action_help 
					  + "', '" + @action_archive
					  + "', '" + @action_display
					  + "', '" + @action_display_summary
					  + "', '" + @action_report
					  + "', '" + @action_report_summary 
					  + "'"
	
	/* Extract the action word from the input action string. */
	if @action is NULL
	begin
		select @actionword = @action_help
	end
	else
	begin
		select @usingIndex = charindex("USING", upper(@action))
		
		select @actionword = case @usingIndex
					when 0 then @action
					else substring(@action, 1, 
						@usingIndex -1)
				     end

		select @actionword = lower(ltrim(rtrim(@actionword)))
	end

	/* Extract the USING clause from the input action string. */
	if @usingIndex = 0
		select @using_clause = NULL
	else
	begin
		exec sp_split_string @action, "USING", 0, @left_substr out
							, @right_substr out
					
		select @using_clause = ltrim(rtrim(@right_substr))
	end
	
	if @actionword not in (	  @action_help	
				, @action_archive
				, @action_display
				, @action_display_summary
				, @action_report
				, @action_report_summary )
	begin
		raiserror 19194, @actionword, @valid_actions
		return (1)
	end

	if @actionword = @action_help 
	begin
		exec sp_spaceusage_showhelp @arg1, @arg2
						 , @valid_actions
						 , @valid_entity_types
		return (0)
	end

	select 	  @entity_type = lower(ltrim(rtrim(@arg1)))
		, @entity_name = @arg2
		
	if @entity_type not in (   @entity_table
				 , @entity_index
				 , @entity_tranlog )
	begin
		raiserror 19194, @entity_type, @valid_entity_types
		return (2)
	end
	
	if @entity_type in (@entity_table, @entity_index)
	begin	-- {	-- Index/Table begins

		if @actionword not in  (   @action_archive				
					 , @action_display
					 , @action_display_summary
					 , @action_report
					 , @action_report_summary )
		begin
			raiserror 19530, @actionword, @entity_type, "sp_spaceusage [help]"
			return (1)
		end

		if @actionword = @action_display
		begin
			select	  @select_list = @optarg1
				, @where_clause = @optarg2
				, @orderby_clause = @optarg3
				, @command = @optarg4
		end
		else if @actionword = @action_display_summary
		begin		
			select	  @where_clause = @optarg1
				, @orderby_clause = @optarg2
				, @command = @optarg3		
		end		
		else if @actionword = @action_report
		begin		
			select	  @select_list = @optarg1
				, @where_clause = @optarg2
				, @orderby_clause = @optarg3
				, @from_date = @optarg4
				, @to_date = @optarg5		
		end		
		else if @actionword = @action_report_summary	
		begin
			select	  @where_clause = @optarg1
				, @orderby_clause = @optarg2
				, @from_date = @optarg3
				, @to_date = @optarg4		
		end
		else if @actionword = @action_archive		
		begin
			select	  @where_clause = @optarg1
				, @command = @optarg2
		end
		
		exec @returnStatus = sp_spaceusage_paramcheck 
							  @actionword
							, @entity_type
							, @entity_name
							, @using_clause
							, @command
							, @from_date
							, @to_date
							, @select_list
							, @where_clause
							, @orderby_clause
		
		if @returnStatus != 0
			return (@returnStatus)

		/* 
		** Extract the owner name, object name and index name pattern
		** from the entity name string.
		*/
		if @entity_type = @entity_index 
		begin
		
			-- The name would be 3-part or 2-part, i.e., either 
			-- 'owner.table.index' or '.table.index' or
			-- 'table.index'.
			--
			exec sp_namecrack @entity_name, @tmpname out
						      , @uname out
						      , @tname out
						      , @iname out
			
			if @uname is NULL
			begin
				select 	  @uname = user_name()
					, @nouname = 1
			end
			
			if @tname is NULL or @iname is NULL
			begin
				raiserror 17993, @entity_name
				return(3)
			end

		end
		else 	-- entity type is 'table'
		begin

			-- The name would be 2-part or 1-part, i.e., either 
			-- 'owner.table' or '.table' or 'table'.
			--
			exec sp_namecrack @entity_name, @tmpname out
						      , @tmpname2 out
						      ,	@uname out
						      , @tname out
			
			if @uname is NULL
			begin
				select 	  @uname = user_name()
					, @nouname = 1
			end
			
			if @tname is NULL 
			begin
				raiserror 17993, @entity_name
				return(3)
			end

			select @iname = "%"
			
		end

		/* Run the command, if any, for the display/archive action. */
		if @actionword in (   @action_archive
				    , @action_display
				    , @action_display_summary )
		begin
			if @command is not NULL
			begin
				exec @returnStatus = sp_spaceusage_runcmd
								  @uname
								, @tname
								, @command
								, 1

				if @returnStatus != 0
					return (@returnStatus)

			end
		end
		
		/* 
		** Extract the archive database and/or the prefix string from 
		** the using_clause, if any, for the archive/report action, and
		** the unit specifier, if any.
		*/
		if @using_clause is not NULL
		begin
			exec @returnStatus = sp_spaceusage_processusing
							  @using_clause
							, @archive_db out
							, @archive_prefix out
							, @unit out
							
			if @returnStatus != 0
				return (@returnStatus)
		
			if	@archive_prefix is not NULL
			    and datalength(@archive_prefix) > @maxobjectprefix
			begin
				raiserror 19491, @archive_prefix, @maxobjectprefix
				return	(5)
			end
			
			if @archive_db is NULL
				select @archive_db = db_name()

			if @unit is NULL
				select @unit = "KB"

		end

		exec @returnStatus = sp_spaceusage_object
							  @actionword
							, @unit
							, @archive_db
							, @archive_prefix
							, @entity_type
							, @nouname
							, @uname
							, @tname
							, @iname
							, @select_list
							, @where_clause
							, @orderby_clause
							, @from_date
							, @to_date
				
		if @returnStatus != 0
			return (@returnStatus)
			
	end	-- }	-- Index/Table done! 
	
	else if @entity_type = @entity_tranlog
	
	begin	-- {	-- Transaction log begins

		if @actionword not in  (  @action_archive
					, @action_display
					, @action_report)
		begin
			raiserror 19530, @actionword, @entity_type, "sp_spaceusage [help]"
			return (1)
		end

		if @actionword = @action_display
		begin
			select	  @select_list = @optarg1
				, @where_clause = @optarg2
				, @orderby_clause = @optarg3
		end
		else if @actionword = @action_report
		begin		
			select	  @select_list = @optarg1
				, @where_clause = @optarg2
				, @orderby_clause = @optarg3
				, @from_date = @optarg4
				, @to_date = @optarg5		
		end		
		else if @actionword = @action_archive		
		begin
			select	  @where_clause = @optarg1
		end
		
		exec @returnStatus = sp_spaceusage_paramcheck 
							  @actionword
							, @entity_type
							, @entity_name
							, @using_clause
							, NULL
							, @from_date
							, @to_date
							, @select_list
							, @where_clause
							, @orderby_clause
		
		if @returnStatus != 0
			return (@returnStatus)

		/* 
		** Extract the archive database and/or the prefix string from 
		** the using_clause, if any, for the archive/report action, and
		** the unit specifier, if any.
		*/
		if @using_clause is not NULL
		begin
			exec @returnStatus = sp_spaceusage_processusing
							  @using_clause
							, @archive_db out
							, @archive_prefix out
							, @unit out
							
			if @returnStatus != 0
				return (@returnStatus)

			if	@archive_prefix is not NULL
			    and datalength(@archive_prefix) > @maxtranlogprefix
			begin
				raiserror 19491, @archive_prefix, @maxtranlogprefix
				return	(5)
			end
			
			if @archive_db is NULL
				select @archive_db = db_name()

			if @unit is NULL
				select @unit = "KB"

		end

		exec @returnStatus = sp_spaceusage_tranlog
							  @actionword
							, @unit
							, @archive_db
							, @archive_prefix
							, @select_list
							, @where_clause
							, @orderby_clause
							, @from_date
							, @to_date
				
		if @returnStatus != 0
			return (@returnStatus)
			
	end	-- }	-- Transaction log done! 

	return (0)
			
end	-- }	-- }	
go
go
exec sp_procxmode 'sp_spaceusage', 'anymode'
go
grant execute on sp_spaceusage to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpapptrace')
begin
	drop procedure sp_helpapptrace
end
go
print "Installing sp_helpapptrace"
go


/*
** Messages for sp_helpapptrace
**
** 17260, "Can't run %1! from within a transaction."
**
*/

create procedure sp_helpapptrace as

declare @low int
declare @high int
declare @spidlow int
declare @spidhigh int
declare @dummy int
declare @sa_role int	/* has sa role */
declare @sso_role int	/* has sso role */

/* Dont allow sp_helpapptrace to run with in a transaction */
if @@trancount > 0
begin
        /*
        ** 17260, "Can't run %1! from within a transaction."
        */
        raiserror 17260, "sp_helpapptrace"
        return (1)
end
else
begin
        set transaction isolation level 1
        set chained off
end

select @sa_role = charindex("sa_role", show_role()),
	@sso_role = charindex ("sso_role", show_role())
 
if ((@sa_role = 0) and (@sso_role = 0))
begin
	select @dummy = proc_role("sa_role")
	select @dummy = proc_role("sso_role")
	return(1)
end
else
begin
	if (@sa_role > 0)
	begin
		select @dummy = proc_role("sa_role")
	end
	if (@sso_role > 0)
	begin
		select @dummy = proc_role("sso_role")
	end
end

select @low = @@minsuid, @high = @@maxsuid, 
	@spidlow = @@minspid, @spidhigh = @@maxspid

/*
** Find all the sessions currently being traced.
*/

select traced=spid
into #table1
from master..sysprocesses
where suid >= @low and suid <= @high
	and spid >= @spidlow and spid <= @spidhigh
	and (convert(int,pssinfo(spid,"tracefile_is_set")) != 0)
	
/*
** Find all the spids and the spids that they are tracing. 
** Note that if the tracer spid has exited then there will be no entry
** for that spid.
*/

select tracer=spid, tracee=convert(int,pssinfo(spid,"trace_spid"))
into #table2
from master..sysprocesses
where suid >= @low and suid <= @high
and spid >= @spidlow and spid <= @spidhigh

/*
** Now combine the above two tables using LEFT OUTER JOIN. This will
** ensure that there is an entry for even those spids whose tracers
** have exited. Additionally also get the paths of the tracefile for
** traced spids.
*/

select traced_spid = convert(char(10),traced), 
	tracer_spid = isnull(convert(char(10),tracer),'exited'), 
	trace_file = pssinfo(traced,"trace_fname")
into #helpapptrace_result
from #table1, #table2
where traced *= tracee

exec sp_autoformat @fulltabname = #helpapptrace_result,
@selectlist = "traced_spid, tracer_spid, trace_file",
@orderby = "order by traced_spid"

drop table #table1
drop table #table2
drop table #helpapptrace_result	

return (0)
go
exec sp_procxmode 'sp_helpapptrace', 'anymode'
go
grant execute on sp_helpapptrace to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_options')
begin
	drop procedure sp_options
end
go
print "Installing sp_options"
go


/* 
** Messages for "sp_options".
**
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
** 19613, "The session id %1! does not exist."
** 19614, "The combination of input parameters %1! is invalid. Check user documentation and reenter command."
** 19615, "No option or category matching '%1!' is found. Valid categories are:"
**
*/

create procedure sp_options
@actionitem varchar(255) = NULL,
@name varchar(255) = NULL,
@displaytype varchar(255) = NULL,
@sessionid int = NULL
as

begin
	declare @currentcategory varchar(100)
	declare @msg varchar(255)
	declare @iscategory tinyint
	declare @isoption tinyint
	declare @islegalspid tinyint
	declare @optioncount smallint

	/*
	** Removing additional spaces and setting input strings
	** to lower case strings.
	*/
	select @actionitem = lower(ltrim(rtrim(@actionitem)))
	select @displaytype = lower(ltrim(rtrim(@displaytype)))

	/*
	** Display syntax of this stored procedure.
	*/
	if (@actionitem is NULL or @actionitem = "help")
	begin
		print ""
	        print "sp_options [[show|help"
	        print "             [, <option_name>|<category_name>|null"
	        print "              [, dflt|non_dflt|null"
	        print "               [, <spid>]"
	        print "              ]"
	        print "             ]"
		print "           ]]"
		return(0)
	end
	
	/*
	** 19194, "Argument '%1!' is either invalid or non-unique.
	** Valid arguments are: %2!"
	*/
	if (@actionitem != "help" and @actionitem != "show")
	begin
		select @msg = "'help' and 'show'"
		raiserror 19194, @actionitem, @msg 
		return(1)
	end

	/*
	** If session id is not provided, use current session's id.
	*/
	if (@sessionid is NULL)
	begin
		select @sessionid = @@spid
	end
	
	/*
	** cache sysoptions data for given session id.
	*/
	begin
	        select *
	        into #cachetable
	        from master.dbo.sysoptions
	        where spid = @sessionid
	end

	/*
	** Check if given session-id is valid.
	*/
	begin
		select @islegalspid = count(*)
			from #cachetable
	
		if (@islegalspid = 0)
		begin
			/*
			** 19613, "The spid %d does not exist."
			*/
			raiserror 19613, @sessionid 
			return(1)
		end
	end

	/*
	** If action item is set to 'show' and no name is
	** provided, then display options of given session
	** grouped by their categories.
	*/
	if (@actionitem = "show" and @name is NULL)
	begin
		declare category_cur cursor for
		select distinct category
		from #cachetable
	
		open category_cur

		/*
		** Display all options.
		*/
	        if (@displaytype is NULL)
		begin
			fetch category_cur into @currentcategory
			while(@@sqlstatus = 0)
			begin
				select name, currentsetting, defaultsetting, scope
				into #temptable
				from #cachetable
				where category = @currentcategory 
	
				select @msg = "Category: " + @currentcategory
				print ""
				print @msg
				print ""
				exec sp_autoformat #temptable
				fetch category_cur into @currentcategory
			end
			close category_cur
			return(0)
		end
	
		/*
		** Display default values of all options.
		*/
		if (@displaytype = "dflt")
		begin
			fetch category_cur into @currentcategory
			while(@@sqlstatus = 0)
			begin
				select name, defaultsetting
				into #temptable1
				from #cachetable
				where category = @currentcategory
	
				select @msg = "Category: " + @currentcategory
				print ""
				print @msg
				print ""
				exec sp_autoformat #temptable1
				fetch category_cur into @currentcategory
			end
			close category_cur
			return(0)
		end

		/*
		** Display all options, which are not set to their
		** default values.
		*/
		if (@displaytype = "non_dflt")
		begin
			fetch category_cur into @currentcategory
			while(@@sqlstatus = 0)
			begin
				select name, currentsetting, defaultsetting
				into #temptable2
				from #cachetable
				where 
					category = @currentcategory 
					and currentsetting != defaultsetting
	
				select @msg = "Category: " + @currentcategory
				print ""
				print @msg
				print ""
				exec sp_autoformat #temptable2
				fetch category_cur into @currentcategory
			end
			close category_cur
			return(0)
		end

		/*
		** 19194, "Argument '%1!' is either invalid or non-unique.
		** Valid arguments are: %2!"
		*/
		select @msg = "'NULL', 'dflt' and 'non_dflt'"
		raiserror 19194, @displaytype, @msg
		close category_cur
		return(1)
	end

	/*
	** If action item is set to 'show' and a name is also
	** provided. Display information regarding given name.
	*/
	if (@actionitem = "show" and @name is not NULL)
	begin

		/*
		** Check if given name is a category.
		*/
		select @iscategory = count(*)
			from #cachetable
			where category = @name

		/*
		** If given name is a category, display information
		** for given category only.
		*/
		if (@iscategory > 0)
		begin

			/*
			** Display all options in given category.
			*/
		        if (@displaytype is NULL)
			begin
				select name, currentsetting, defaultsetting, scope
				into #temptable3
				from #cachetable
				where category = @name 
	
				select @msg = "Category: " + @name
				print ""
				print @msg
				print ""
				exec sp_autoformat #temptable3
				return(0)
			end

			/*
			** Display default values of all options in given
			** category.
			*/
			if (@displaytype = "dflt")
			begin
				select name, defaultsetting
				into #temptable4
				from #cachetable
				where category = @name
	
				select @msg = "Category: " + @name
				print ""
				print @msg
				print ""
				exec sp_autoformat #temptable4
				return(0)
			end
	
			/*
			** Display all options in given category, which are
			** not set to their default values.
			*/
			if (@displaytype = "non_dflt")
			begin
				select name, currentsetting, defaultsetting
				into #temptable5
				from #cachetable
				where category = @name and currentsetting != defaultsetting
	
				select @msg = "Category: " + @name
				print ""
				print @msg
				print ""
				exec sp_autoformat #temptable5
				return(0)
			end
			
			/*
			** 19194, "Argument '%1!' is either invalid or non-unique.
			** Valid arguments are: %2!"
			*/
			select @msg = "'NULL', 'dflt' and 'non_dflt'"
			raiserror 19194, @displaytype, @msg
			return(1)
		end

		/*
		** Check if given name is an option.
		*/
		select @isoption = count(*)
			from #cachetable
			where name = @name
	
		if (@isoption = 1)
		begin
			/*
			** Display all information for given option.
			*/
		        if (@displaytype is NULL)
			begin
				select name, category, currentsetting, defaultsetting, scope
				into #temptable6
				from #cachetable
				where name = @name 
	
				exec sp_autoformat #temptable6
				return(0)
			end

			/*
			** Display default value for given option.
			*/
			if (@displaytype = "dflt")
			begin
				select name, defaultsetting
				into #temptable7
				from #cachetable
				where name = @name
	
				exec sp_autoformat #temptable7
				return(0)
			end

			/*
			** 19614, "The combination of input parameters %s 
			** is invalid. Check user documentation and reenter 
			** command."
			*/
			if (@displaytype = "non_dflt")
			begin
				select @msg = @name + " and non_dflt"
				raiserror 19614, @msg 
				return(1)
			end
			
			/*
			** 19194, "Argument '%1!' is either invalid or non-unique.
			** Valid arguments are: %2!"
			*/
			select @msg = "'NULL', 'dflt' and 'non_dflt'"
			raiserror 19194, @displaytype, @msg
			return(1)
		end

		/*
		** Check if there are any options matching given name.
		*/
		select @optioncount = count(*)
			from #cachetable
			where name like "%" + @name + "%"

		/*
		** Display information of all matching options, grouped
		** by category.
		*/
		if (@optioncount > 0)
		begin
			declare category_cur cursor for
			select distinct category
			from #cachetable
	
			open category_cur

			/*
			** Display all matching options.
			*/
			if(@displaytype is NULL)
			begin
				fetch category_cur into @currentcategory
				while (@@sqlstatus = 0)
				begin
					select name, currentsetting, defaultsetting, scope
					into #temptable8
					from #cachetable
					where name like "%" + @name + "%"
	
					select @msg = "Category: " + @currentcategory
					print ""
					print @msg
					print ""
					exec sp_autoformat #temptable8
					fetch category_cur into @currentcategory
				end
				close category_cur
				return(0)
			end

			/*
			** Display default values of all matching options.
			*/
			if(@displaytype = "dflt")
			begin
				fetch category_cur into @currentcategory
				while (@@sqlstatus = 0)
				begin
					select name, defaultsetting
					into #temptable9
					from #cachetable
					where name like "%" + @name + "%"
	
					select @msg = "Category: " + @currentcategory
					print ""
					print @msg
					print ""
					exec sp_autoformat #temptable9
					fetch category_cur into @currentcategory
				end
				close category_cur
				return(0)
			end

			/*
			** Display all matching options which are not set to
			** their default values.
			*/
			if(@displaytype = "non_dflt")
			begin
				fetch category_cur into @currentcategory
				while (@@sqlstatus = 0)
				begin
					select name, currentsetting, defaultsetting
					into #temptable10
					from #cachetable
					where name like "%" + @name + "%"
						and currentsetting != defaultsetting
	
					select @msg = "Category: " + @currentcategory
					print ""
					print @msg
					print ""
					exec sp_autoformat #temptable10
					fetch category_cur into @currentcategory
				end
				close category_cur
				return(0)
			end
			
			/*
			** 19194, "Argument '%1!' is either invalid or non-unique.
			** Valid arguments are: %2!"
			*/
			select @msg = "'NULL', 'dflt' and 'non_dflt'"
			raiserror 19194, @displaytype, @msg
			close category_cur
			return(1)
		end

		/*
		** 19615, "No option or category matching '%1!' is found. Valid categories are:"
		*/
		if (@optioncount = 0)
		begin
			raiserror 19615, @name
		
			select distinct category
			into #temptable11
			from #cachetable
			exec sp_autoformat #temptable11
			return(1)
		end
	end
end
go
exec sp_procxmode 'sp_options', 'anymode'
go
grant execute on sp_options to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_compatmode')
begin
	drop procedure sp_compatmode
end
go
print "Installing sp_compatmode"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/compatmode */

/*
** Messages for "sp_compatmode"		
** 
** 19963, "Compatibility mode is not enabled."
** 19964, "Compatibility mode is enabled."
** 19965, "WARNING: The configuration option 'histogram tuning factor' is configured with value '%1!', which is not the default value in ASE 12.5. This may lead to different accuracy of statistics and different query plans."
*/

create procedure sp_compatmode as
begin

declare @config_value_to_check int	  /* value of config option to be 
					  ** checked.
					  */
declare @msg varchar(1024)		  /* temp buffer for messages */

select @config_value_to_check = NULL

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* Get value of 'enable compatibility mode' option. */
select @config_value_to_check = value 
from  master.dbo.sysconfigures
where config = 502 

/* Nothing to check if compatibility mode is disabled.*/
if (@config_value_to_check is not NULL   
    and @config_value_to_check = 0)
begin
	exec sp_getmessage 19963, @msg output
        print @msg 
	
	return (0)
end
else if (@config_value_to_check = 1)   
begin
	exec sp_getmessage 19964, @msg output
        print @msg 
end

/*
** Raise warning message if abstract plan 
** dump/load/replace is also on. 
*/
if exists (select * 
	   from  master.dbo.sysconfigures
	   where config in (383, 384, 385)
	   	 and value = 1)
begin
	exec sp_getmessage 19961, @msg output
        print @msg 
end
	
/*
** Raise warning message 19962 if literal  
** autoparam is on, but we need to check
** if statment cache is on also. 
*/
if exists (select * 
	   from  master.dbo.sysconfigures
	   where config = 414 and value != 0) 
begin
	if exists (select *
		   from  master.dbo.sysconfigures
	           where config = 462 and value = 1) 
	begin
		exec sp_getmessage 19962, @msg output
		print @msg 
	end
end

/*
** Raise warning message if the value of histogram 
** tuning factor is not 1, the default value in
** ASE 12.5. 
*/
select @config_value_to_check = value 
from  master.dbo.sysconfigures
where config = 433 

if (@config_value_to_check is not NULL 
    and @config_value_to_check != 1)
begin
	exec sp_getmessage 19965, @msg output
        print @msg,  @config_value_to_check 
end

return (0)

end

go
exec sp_procxmode 'sp_compatmode', 'anymode'
go
grant execute on sp_compatmode to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_setup_table_transfer')
begin
	drop procedure sp_setup_table_transfer
end
go
print "Installing sp_setup_table_transfer"
go

/*
** Messages for "sp_setup_table_transfer"         17280
**
** 17260, "Can't run %1! from within a transaction." 
** 18305, "Table '%1!' has already been created."
*/
create procedure sp_setup_table_transfer
as

declare	@cmd	  varchar(100),
	@procname varchar(30),
	@procval  int,
	@tabname  varchar(30)

select	@procname = 'sp_setup_table_transfer',
	@tabname  = 'spt_TableTransfer'

/*
**  Create-table does not happen within a transaction.
*/
if @@trancount > 0
begin
	-- 17260, "Can't run %1! from within a transaction." 
	raiserror 17260, @procname
	return 1
end

set chained off
set transaction isolation level 1

/*
**  Only the Database Owner (DBO) or accounts with SA role can execute this.
**  A user with SA role has UID '1' (DBO) just as the DBO does.
*/
if (user_id() != 1)
begin
	/* user_id() is not DBO hence user does not have SA role
	** audit this as a failed sa command execution.
	*/
	select @procval = proc_role("sa_role")
	return 1
end

-- If user has sa role audit this as a successful sa command execution.
if charindex("sa_role",show_role()) > 0
	select @procval = proc_role("sa_role")

-- If spt_TableTransfer already exists, don't try to create it again.
if exists (select id from sysobjects where name = @tabname)
begin
	-- 18305, "Table '%1!' has already been created."
	raiserror 18305, @tabname
	return 0
end

-- Create the table.
create table spt_TableTransfer (
	end_code    unsigned smallint not null,
	id          int          not null,
	ts_floor    bigint       not null,
	ts_ceiling  bigint       not null,
	time_begin  datetime     not null,
	time_end    datetime     not null,
	row_count   bigint       not null,
	byte_count  bigint       not null,
	sequence_id int          not null,
	col_order   tinyint      not null,
	output_to   tinyint      not null,
	tracking_id int          null,
	pathname    varchar(512) null,
	row_sep     varchar(64)  null,
	col_sep     varchar(64)  null,
	primary key (id,sequence_id) )
lock allpages
on 'default'

if (@@error != 0)
	return 1

/*
** Let everyone see its contents.  This unfortunately does not compile
** if we create the table within this procedure, so we need to perform
** it via 'exec immediate'.
*/
select @cmd = 'grant select on ' + @tabname + ' to public'
exec (@cmd)

if (@@error != 0)
	return 1

-- Done successfully
return 0
go
exec sp_procxmode 'sp_setup_table_transfer', 'anymode'
go
grant execute on sp_setup_table_transfer to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_iqdbcheck')
begin
	drop procedure sp_iqdbcheck
end
go
print "Installing sp_iqdbcheck"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Referenced by sp_addobjectdef; purpose is to determine whether the
** current database is an IQ database.  If so, should return 1, else
** return 0
*/
create procedure sp_iqdbcheck @dbname varchar(30)
as
	/*
	** The Omni-supplied version will always return 0, since we are
	** never using an IQ database.
	*/
	return 0

go
exec sp_procxmode 'sp_iqdbcheck', 'anymode'
go
grant execute on sp_iqdbcheck to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addexternlogin')
begin
	drop procedure sp_addexternlogin
end
go
print "Installing sp_addexternlogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_addexternlogin"    18294
**
** 17240, "'%1!' is not a valid name."
** 17260, "Can't run '%1!' from within a transaction."
** 17270, "There is not a server named '%1!'."
** 17271, "'%1!' is the local server - remote login not applicable."
** 18294, "User '%1!' is not a local user -- request denied."
** 18295, "Only the 'sa' may update another's external login."
** 18296, "External login updated."
** 18297, "User '%1!' will be known as '%2!' in remote server '%3!'."
** 18342, "Invalid name '%1!'. This role or user does not exist in this SQL Server." 
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
** 18780, "Synchronization will not occur because server '%1!' is the companion server."
** 18782 "Unable to find a server with name '%1!' and id '%2!'."
** 18886, "Users with role '%1!' will be known as '%2!' in remote server '%3!'."
** 19403, "IBM MQ servers cannot have a registered login"
** 19404, "IBM MQ servers cannot have a default login"
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_addexternlogin
	@server		varchar(255),		/* name of remote server */
	@loginame	varchar(255),		/* user's local name */
	@externname	varchar(255),		/* user's remote name */
	@externpasswd	varchar(255) = NULL,	/* user's remote password */
	@rolename	varchar(255) = NULL	/* name of roll to map */
AS
BEGIN

DECLARE	@msg		varchar(1024),
	@srvid		smallint,
	@suid		int,
	@srid		int,
	@action		smallint,
	@dso_class	smallint,		/* omni's attribute  class */
	@attrib		smallint,		/* attr. id for ext. login */
	@dummy		int,
	@maxlen		int,
	@HA_CERTIFIED	tinyint,   /* Is the SP HA certified ? */
	@retstat	int,
	@srvclass	smallint 		
select @HA_CERTIFIED = 0
select @retstat = 0
select @srid = -1

if  (@externname is not null)
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.syslogins") and name = "name"

	if (char_length(@externname) > @maxlen)
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @externname
		return 1
	end
end

/* check for password */
if (@externpasswd is not null) 
begin
	select @maxlen = length from master.dbo.syscolumns
	where id = object_id("master.dbo.syslogins") and name = "password"

	if (char_length(@externpasswd) >  @maxlen) 
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @externpasswd
		return 1
	end
end



/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_addexternlogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
	if @@trancount > 0
	BEGIN
		/*		
		** 17260 Can't run '%1!' from within a transaction.
		*/
		raiserror 17260, "sp_addexternlogin"
		return 1
	END

/*
**  Check that the server name is valid.
*/

	select	@srvid = srvid,  @srvclass=srvclass
		from master.dbo.sysservers
		where srvname = @server

	if @@rowcount != 1
	BEGIN
		/*		
		** 17270  "There is not a server named %1!"  
		*/
		raiserror 17270, @server
		return (1)
	END

/*
**  If it's the local server don't bother.
*/
	if @srvid = 0
	BEGIN
		/*		
		** 17271 "'%1!' is the local server - remote login not applicable."
		*/
		raiserror 17271, @server
		return (1)
	END

/*
**  If @rolename was specified, ignore @loginame
*/
	if @rolename is not NULL
	BEGIN	
		select @loginame = NULL
/*
**  Check that the @rolename is valid.
*/

		select @srid = srid from master.dbo.syssrvroles	
			where name = @rolename

		if @@rowcount != 1
		BEGIN
			/* 
			** 18342, "Invalid name '%1!'. This role or user does 
			** not exist in this SQL Server."  
			*/ 
			raiserror 18342, @rolename
			return (1)
		END
	END

	if @loginame is NULL
	BEGIN
		select @suid = -1
	END
	else
	BEGIN
/*
**  Check that the @loginame is valid.
*/
		select @suid = suid
			from master.dbo.syslogins
			where name = @loginame
		if @@rowcount != 1
		BEGIN
			/*		
			** 18294 "User '%1!' is not a local user -- request denied."
			*/
			raiserror 18294, @loginame
			return (1)
		END
	END
/*
** Only a user with sa_role or sso_role can add extern logins for another
** user or for a role.
*/
	if @suid != suser_id()
	BEGIN
		/*
		** check if user has sa role, proc_role will
		** also do auditing if required. proc_role will also
		** print error message if required.
		*/
		if (charindex("sa_role",show_role()) = 0 and
			charindex("sso_role",show_role()) = 0)
		BEGIN
			select @dummy = proc_role("sa_role")
			select @dummy = proc_role("sso_role")
			return (1)
		END
	END


	/*
	** We don't allow IBM_MQ servers to have extern logins.
	*/
	if (@srvclass = 13)
	begin
		if @loginame is NULL
		begin
			/*
			** 19404, "IBM MQ servers cannot have a default login"
			*/
			raiserror 19404
		end
		else
		begin
			/*
			** 19403, "IBM MQ servers cannot have a registered login"
			*/
			raiserror 19403
		end
		return (1)
	end

/*
** If there is already a user for this server defined, we'll update
** it, else we'll insert a new row.
*/

	if ((@srvclass != 12) and (@srvclass != 14) and (@srvclass != 15))
		select @dso_class = 9
	else
		select @dso_class = 21

        select @attrib = 0

	if exists(select * from master.dbo.sysattributes where
			class = @dso_class and attribute = @attrib and 
			object_info1 = @srvid and object = @suid and
			(object_info2 = @srid or object_info2 is null))
		select @action = 2      /* attribute change */
	else
		select @action = 1      /* attribute add */	

/*
** First validate the row. This will also cause the password to be encrypted.
*/
	if attrib_valid(@dso_class, @attrib, "EL", @suid, @srvid, @srid, NULL,
		@externname, NULL, NULL, NULL, @externpasswd, NULL, @action) = 0
	BEGIN
		return(1)
	END



/*
** Now update/insert the row
*/
	if @action = 2
	BEGIN
		update master.dbo.sysattributes
			set	object_cinfo = @externname,
				image_value = internal_encrypt(@externpasswd)
			where	class = @dso_class and attribute = @attrib and
				object_info1 = @srvid and object = @suid and
				(object_info2 = @srid or object_info2 is null)

		if (@@error = 0)
		BEGIN
			/*
			** 18296 "External login updated."
			*/
			exec sp_getmessage 18296, @msg output
			print @msg
		END
		ELSE
			goto clean_all

	END 
	else
	BEGIN
		insert into master.dbo.sysattributes (class, attribute, 
			object_type, object_info1, object, object_cinfo,
			image_value, object_info2)
		values (@dso_class, @attrib, "EL", @srvid, @suid, @externname, 
			internal_encrypt(@externpasswd), @srid)

		if (@@error = 0)
		BEGIN
			if @rolename is not null
			BEGIN
				/*
				** 18886 "Users with role '%1!' will be
				** known as '%2!' in remote server '%3!'."
				*/
				exec sp_getmessage 18886, @msg output
				print @msg, @rolename, @externname, @server
			END
			else
			BEGIN
				/*
				** 18297 "User '%1!' will be known as '%2!' 
				** in remote server '%3!'."
				*/
				exec sp_getmessage 18297, @msg output
				print @msg, @loginame, @externname, @server
			END
		END
		ELSE
			goto clean_all
	END



	/*
	** Sync the in-memory RDES with the new values
	** in sysattributes.
	*/
	if attrib_notify(@dso_class, @attrib, "EL", @suid, @srvid, @srid,
			NULL, NULL, NULL, NULL, NULL, NULL, NULL,
			@action) = 0
		return (1)
	else
		return (@retstat)
END

clean_all:

	return (1)


go
exec sp_procxmode 'sp_addexternlogin', 'anymode'
go
grant execute on sp_addexternlogin to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addobjectdef')
begin
	drop procedure sp_addobjectdef
end
go
print "Installing sp_addobjectdef"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_addobjectdef"	18299
**
** 17240, "'%1!' is not a valid name."
** 18299, "Unknown object type '%1!'."
** 18300, "A server name is not permitted in the local object_name."
** 18301, "Database name '%1!' is not the current database."
** 18302, "User '%1!' is not a valid user in the '%2!' database."
** 18303, "You must be the System Administrator (sa) or Database Owner (dbo) to add a definition for another user's table."
** 18304, "Object '%1!' has already been defined."
** 18305, "Table '%1!' has already been created."
** 18306, "The format for the object_loc parameter is invalid."
** 18307, "Server name '%1!' does not exist in sysservers."
** 18308, "The server name in object_loc must be a remote server. '%1!' is the local server."
*/
create procedure sp_addobjectdef
	@tablename 	varchar(1023),	/* local table name */
	@objectdef	varchar(1023),
			/* remote object to which local object will be mapped */
	@objecttype	varchar(10) = "table"
			/* object type (file, table/view, rpc) */
as
begin

declare		@uid		int,
		@server		varchar(255),
		@dbname		varchar(255),
		@owner		varchar(255),
		@object		varchar(255),
		@r_object	varchar(255),
		@retcode	int,
		@type		smallint,	/* type */
		@srvclass	smallint,
		@srvid		smallint,
		@dso_class	smallint,
		@attrib		smallint,
		@objectdef_tmp 	varchar(1023),
		@maxlen		int,
		@dummy		int


set nocount on

/*
** We cannot add an Omni proxy table to a database used as an IQ catalog
** database.  Check for sysIQ_objects.
*/
select @dbname = db_name()
exec @retcode = sp_iqdbcheck @dbname
if @retcode = 1
begin
	return 1
end
select @dbname = ""


/*
** Get a value @type from @objecttype
*/
select @type = number from master.dbo.spt_values
		where type = 'Y' and name = lower(@objecttype)

if @@rowcount = 0 or lower(@objecttype) = 'directory'
begin
	/*
	** 18299, "Unknown object type '%1!'."
	*/
	raiserror 18299, @objecttype
	return (1)
end

/*
** Check that @tablename refers to object in current database,
** and determine correct user id.
*/
exec @retcode = sp_namecrack @tablename, @server output, @dbname output,
		@owner output, @object output
if @retcode != 0
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @tablename
	return (1)

end

if @server is not null
begin
	/*
	**  18300, "A server name is not permitted in the local object_name." 
	*/
	raiserror 18300
	return (1)
end

if @dbname is not null
begin
	if @dbname != db_name()
	begin
		/*
		** 18301, "Database name '%1!' is not your current database."
		*/
		raiserror 18301, @dbname
		return (1)
	end
end

if @owner is NULL
begin
	select @uid = user_id()
end
else
begin
	select @uid = user_id(@owner)
	if @uid is NULL
	begin
		select @dbname = db_name()
		/*
		** 18302, "User '%1!' is not a valid user in the '%2!' database."
		*/
		raiserror 18302, @owner, @dbname
		return (1)
	end
end

/*
** Only sa or dbo can add a definition for another user's table.
*/
if @uid != user_id()
BEGIN
	/*
	** check if user has sa role, proc_role will
	** also do auditing if required. proc_role will also
	** print error message if required.
	*/
	if (charindex("sa_role",show_role()) = 0)
	BEGIN
		select @dummy = proc_role("sa_role")
		return (1)
	END
END

/*
** Check that tabname is valid
*/
if (@object is not null)
begin
	select @maxlen = length from syscolumns
	where id = object_id("sysobjects") and name = "name"

	if valid_name(@object, @maxlen) = 0
	begin
		/*
		** 17240, "'%1!' is not a valid name."
		*/
		raiserror 17240, @object
		return 1
	end
end

/*
** Strip out quotes from table name if quoted identifier is
** on
*/
if @object like '"%"'
begin
	select @object = substring(@object,2,char_length(@object) - 2)
end


/*
** See if the object has already been defined.
*/
select @dso_class = 9, @attrib = 1

if exists (select * from sysattributes
		where class = @dso_class and attribute = @attrib and
		object_cinfo = @object and object_info1 = @uid)
begin
	/*
	** 18304, "Object '%1!' has already been defined."
	*/
	raiserror 18304, @object
	return (1)
end

/*
** See if the table has already been created.
*/
if @type != 5
begin
	if exists (select * from sysobjects
		where type = 'U' and name = @object and uid = @uid)
	begin
		/*
		** 18305, "Table '%1!' has already been created."
		*/
		raiserror 18305, @object
		return (1)
	end
end

/*
** If we are a table/view or RPC, check table definition accordingly.
*/
if @type = 1 or @type = 3
begin
	execute @retcode = sp_namecrack @objectdef, @server output,
					@dbname output, @owner output,
					@r_object output
	if @retcode != 0
	begin
		/*
		** If we are a table or view, see if object specification
		** contains an auxiliary fields:
		**
		**  	server.db.owner.tbl;auxname
		*/
		if @type = 1
		begin
			select @objectdef_tmp = substring(@objectdef,1,
					      CHARINDEX(";",@objectdef))
			execute @retcode = sp_namecrack @objectdef_tmp, 
					@server output,
					@dbname output, @owner output,
					@r_object output
		end
		if @retcode != 0
		begin
			/*
			** ** 18306, "Format for the object_loc parameter is invalid."
			*/
			raiserror 18306
			return (1)

		end
	end
	select	@srvclass = srvclass,
		@srvid = srvid
		from	master.dbo.sysservers
		where	srvname = @server
	if @@rowcount = 0
	begin
		/*
		** 18307, "Server name '%1!' does not exist in sysservers."
		*/
		raiserror 18307, @server
		return (1)
	end
	else if @srvclass = 0
	begin
		/*
		** 18308, "The server name in object_loc must be a remote server; '%1!' is the local server."
		*/
		raiserror 18308, @server
		return (1)
	end
end
else if @type = 2 or @type = 4 or @type = 5
begin
	select @srvid = 0
end

insert into sysattributes
	(class, attribute, object_type, object_cinfo, object_info1,
	object_info2, object_info3, char_value)
values (@dso_class, @attrib, "OD", @object, @uid, @type, @srvid, @objectdef)

return(0)
end

go
exec sp_procxmode 'sp_addobjectdef', 'anymode'
go
grant execute on sp_addobjectdef to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addtabledef')
begin
	drop procedure sp_addtabledef
end
go
print "Installing sp_addtabledef"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_addtabledef".  Additional messages are issued from
** sp_addobjectdef, which this procedure invokes.
**
** 18312, "Object type is '%1!'."
** 18313, "Unrecognized storage_location type '%1!'."
*/

create procedure sp_addtabledef
	@tablename 	varchar(1023),	/* local table name */
	@objectdef	varchar(255),	/* path to remote/external object */
	@objecttype	varchar(10) = "table"	/* object type  */
as
begin

declare	@msg	varchar(1024),
	@status	int

/*
** See if the objectdef actually represents a remote server
** object.
*/
if exists (select * from master.dbo.spt_values where type = 'E' and name = 'vms')
	begin
	if charindex(":", @objectdef) > 0
		begin
			/*
			** 18312, "Object type is '%1!'."
			*/
			select @objecttype = "file"
        		exec sp_getmessage 18312, @msg output
  			print @msg, @objecttype
		end
	end
else if @objectdef like "%.%.%.%" 
	begin
		/*
		** 18312, "Object type is '%1!'."
		*/
		select @objecttype = "table"
        	exec sp_getmessage 18312, @msg output
  		print @msg, @objecttype
	end
else
	begin
	/*
	** 18313, Unable to determine storage_location type for '%1!'
        */
  	raiserror 18313, @objectdef
	return(1)
	end

exec @status = sp_addobjectdef @tablename,@objectdef,@objecttype

return (@status)
end
go
exec sp_procxmode 'sp_addtabledef', 'anymode'
go
grant execute on sp_addtabledef to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_autoconnect')
begin
	drop procedure sp_autoconnect
end
go
print "Installing sp_autoconnect"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_autoconnect"	18314
** 
** 18307, "Server name '%1!' does not exist in sysservers."
** 18314, "Login '%1!' does not exist in syslogins table."
** 18315, "Only the 'sa' can modify another's autoconnect capability."
** 18316, "Autoconnect ON for user '%1!', server '%2!'."
** 18317, "Autoconnect OFF for user '%1!' server '%2!'."
** 18318, "Unrecognized flag '%1!'; must be either 'true' or 'false'."
*/

create procedure sp_autoconnect
	@server 	varchar(92),	/* remote server name */
	@truefalse	varchar(10),	/* enable/disable autoconnect */
	@loginame	varchar(30) = NULL /* login name to enable/disable */
as begin

declare		@flag		int,
		@msg		varchar(1024)

	set nocount on

	/*
	** Check server name.
	*/
	if not exists (select * from master.dbo.sysservers
					where srvname = @server)
        begin
		/*
		** 18307, "Server name '%1!' does not exist in sysservers."
		*/
		raiserror 18307, @server
		return(1)
	end

	/*
	** Establish login name.  Only the 'sa' can do this for others.
	*/
	if @loginame is NULL
		select @loginame = suser_name()

	/*
	** Check login name.
	*/
	if not exists (select * from master.dbo.syslogins
			where name = @loginame)
	begin
		/*
		** 18314, "Login '%1!' does not exist in syslogins table." 
		*/
		raiserror 18314, @loginame
		return(1)
	end

	/*
	** Check permission to perform operation.  You must be 'sa' to
	** modify someone else's autoconnect capabilities.
	*/
	if suser_id() != 1 and suser_name() != @loginame

	begin
		/*
		** 18315, "Only the 'sa' can modify another's autoconnect capability."
		*/
		raiserror 18315
		return(1)
	end

	/*
	** check true/false, and set the login status flag accordingly.
	*/
	select @truefalse = lower(@truefalse)
	select @flag = 16
	if @truefalse = "true"
	begin
		update master.dbo.syslogins
			set	status = status | @flag,
				srvname = @server
			where	name = @loginame
		/*
		**  18316, "Autoconnect ON for user '%1!', server '%2!'."
		*/
		exec sp_getmessage 18316, @msg output
		print @msg, @loginame, @server

	end
	else if @truefalse = "false"
	begin
		update master.dbo.syslogins
			set	status = status & ~@flag,
				srvname = NULL
			where	name = @loginame
		/*
		**  18317, "Autoconnect OFF for user '%1!', server '%2!'."
		*/
		exec sp_getmessage 18317, @msg output
		print @msg, @loginame, @server

	end
	else
	begin
		/*
		**  18318, "Unrecognized flag '%1!'; must be either 'true' or 'false'."  	
		*/
		raiserror 18318, @truefalse
		return(1)
	end


	return (0)
end
go
exec sp_procxmode 'sp_autoconnect', 'anymode'
go
grant execute on sp_autoconnect to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_defaultloc')
begin
	drop procedure sp_defaultloc
end
go
print "Installing sp_defaultloc"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_defaultloc"	 18322
**
** 17240, "'%1!' is not a valid name."
** 17800, "No such server -- run sp_helpserver to list servers."
** 18322, "There is not a database named '%1!'."
** 18323, "There is not an object type named '%1!'."
** 18324, "An RMS filespec for a directory must be specified."
** 18325, "Storage location syntax must end in '.'."
** 18326, "Created default location for database '%1!' at '%2!'."
** 18327, "You cannot remap objects in the master, model, or tempdb databases."
** 18328, "There is no default storage location in effect for database '%1!'."
** 18329, "Default storage location deleted for database '%1!'."
** 18330, "Database '%1!' already has a default location '%2!'."
*/

create procedure sp_defaultloc
	@dbname varchar(30),			/* server name */
	@defaultloc varchar(255),		/* default storage location */
	@defaulttype varchar(30) = "table"	/* default object type */
as
begin
	declare	@dbid		smallint,
		@type		int,
		@last_char	char(1),
		@msg		varchar(1024),
		@oldloc		varchar(255)
	declare	@site		varchar(30),
		@db		varchar(30),
		@own		varchar(30),
		@obj		varchar(30),
		@status		int,
		@isatempdb	int
	declare @tempdb_mask    int	/* All database status bit for a tempdb */

	/*
	** Get the database id.
	*/
	select @dbid = 0
	select @dbid = db_id(@dbname)
	if @dbid is null
	begin
		/* 
		** 18322, "There is not a database named '%1!'."
		*/
		raiserror 18322, @dbname
		return (1)
	end

	/*
	** Determine if we are mapping a temporary database.
	*/
	select @tempdb_mask = number
	from master.dbo.spt_values
	where type = "D3" and name = "TEMPDB STATUS MASK"

	if (@dbid = 2) or exists (select * from master.dbo.sysdatabases
			where dbid = @dbid
			and (status3 & @tempdb_mask) != 0) 
	begin
		select @isatempdb = 1
	end

	/*
	** If the database is master, model or tempdb, disallow this.
	*/
	if @dbname = "master" OR @dbname = "model" OR @isatempdb = 1
	begin
		/* 
		** 18327, "You cannot remap objects in the master, model, or tempdb databases."
		*/
		raiserror 18327
		return (1)
	end

	/*
	** If the database is an IQ catalog database, disallow this.
	*/
	exec @status = sp_iqdbcheck @dbname
	if @status = 1
	begin
		return 1
	end
	
	/*
	** Get a value @type from @objecttype
	*/
	select @type = number from master.dbo.spt_values
		where type = 'Y' and name = lower(@defaulttype)

	if @@rowcount = 0
	begin
		/* 
		** 18323, "There is not an object type named '%1!'."
		*/
		raiserror 18323, @defaulttype
		return (1)
	end

	/*
	** If the defaultloc is NULL, then delete any default location that
	** may exist for this database.
	*/
	if @defaultloc is NULL
	begin
		if exists (select * from master.dbo.sysdatabases
				where dbid = @dbid
				and def_remote_loc is null)
		begin
			/* 
			** 18328, "There is no default storage location in effect for database '%1!'."
			*/
			raiserror 18328, @dbname
			return (1)
		end
		else
		begin
			update master.dbo.sysdatabases
				set def_remote_loc = NULL,
				def_remote_type = NULL
					where dbid = @dbid

			/* 
			** 18329, "Default storage location deleted for database '%1!'."
			*/
			exec sp_getmessage 18329, @msg output
			print @msg, @dbname
			return(0)
		end
	end

	/*
	** If the object type is not a file, the syntax of the location
	** field must be 'server.dbname.owner.', where server must be
	** provided, and dbname and/or owner may be omitted.
	*/
	select @last_char = SUBSTRING(@defaultloc, CHAR_LENGTH(@defaultloc), 1)

	/*
	** If the type is FILE (2), then the last character must be a
	** ']', since the default loc must be an RMS filespec for a 
	** directory.
	*/

	if exists (select * from master.dbo.spt_values where type = 'E' and name = 'vms')
	begin
		if @type = 2
		begin
			if @last_char != ']' AND @last_char != ':'
			begin
				/* 
				** 18324, "An RMS filespec for a directory must be specified."
				*/
				raiserror 18324
				return (1)
			end
		end
	end
	/*
	** If the type is FILE (2), and we are on unix then we allow
	** anything and validate inside the omni code
	*/

	if @type != 2
	begin
		if @last_char != '.'
		begin
			/* 
			** 18325, "Storage location syntax must end in '.'."
			*/
			raiserror 18325
			return (1)
		end

		/*
		** Make sure the format is correct: "SERVER.db.owner.",
		*/
		exec @status = sp_namecrack @defaultloc,
			@site output, @db output, @own output, @obj output

		if @status != 0 OR @obj IS NOT NULL OR @site IS NULL
		begin
			/*
			** 17240, "'%1!' is not a valid name."
        		*/
			raiserror 17240, @defaultloc
			return (1)
		end
		if not exists (select * from master.dbo.sysservers
				where srvname = @site)
		begin
			/*
			** 17800, "No such server -- run sp_helpserver to
			** list servers."
			*/
			raiserror 17800
			return (1)

		end
	end

	if exists (select * from master.dbo.sysdatabases
			where dbid = @dbid and def_remote_loc is not null)
	begin
		select @oldloc = def_remote_loc from master.dbo.sysdatabases
			where dbid = @dbid
		/* 
		** 18330, "Database '%1!' already has a default location '%2!'."
		*/
		raiserror 18330, @dbname, @oldloc
		return (1)
	end
	else
	begin
		update master.dbo.sysdatabases
			set def_remote_loc = @defaultloc,
			def_remote_type = @type
				where dbid = @dbid
		/* 
		** 18326, "Created default location for database '%1!' at '%2!'." 
		*/
		exec sp_getmessage 18326, @msg output
		print @msg, @dbname, @defaultloc
	end

	return(0)
end



go
exec sp_procxmode 'sp_defaultloc', 'anymode'
go
grant execute on sp_defaultloc to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropexternlogin')
begin
	drop procedure sp_dropexternlogin
end
go
print "Installing sp_dropexternlogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_dropexternlogin"	18319
**
** 17260, "Can't run '%1!' from within a transaction."
** 18307, "Server name '%1!' does not exist in sysservers."
** 18319, "There is no external login for server '%1!'."
** 18320, "Only the 'sa' may drop another's external login."
** 18321, "Remote login/alias dropped."
** 17271, "'%1!' is the local server - remote login not applicable."
** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
** 18780, "Synchronization will not occur because server '%1!' is the companion server."
** 18782 "Unable to find a server with name '%1!' and id '%2!'."
*/

/* 
** IMPORTANT: Please read the following instructions before
**   making changes to this stored procedure.
**
**	To make this stored procedure compatible with High Availability (HA),
**	changes to certain system tables must be propagated 
**	to the companion server under some conditions.
**	The tables include (but are not limited to):
**		syslogins, sysservers, sysattributes, systimeranges,
**		sysresourcelimits, sysalternates, sysdatabases,
**		syslanguages, sysremotelogins, sysloginroles,
**		sysalternates (master DB only), systypes (master DB only),
**		sysusers (master DB only), sysprotects (master DB only)
**	please refer to the HA documentation for detail.
**
**	Here is what you need to do: 
**	For each insert/update/delete statement, add three sections to
**	-- start HA transaction prior to the statement
**	-- add the statement
**	-- add HA synchronization code to propagate the change to the companion
**
**	For example, if you are adding 
**		insert master.dbo.syslogins ......
**	the code should look like:
**	1. Before that SQL statement:
**		
**	2. Now, the SQL statement:
**		insert master.dbo.syslogins ......
**	3. Add a HA synchronization section right after the SQL statement:
**		
**
**	You may need to do similar change for each built-in function you
**	want to add.
**
**	Finally, add a separate part at a place where it can not
**	be reached by the normal execution path:
**	clean_all:
**		
**		return (1)
*/

create procedure sp_dropexternlogin
	@server		varchar(255),		/* name of remote server */
	@loginame	varchar(255) = NULL,	/* user's local login */
	@rolename	varchar(255) = NULL	/* role name */
AS
BEGIN

	declare	@msg		varchar(1024),
		@suid		int,
		@srid		int,
		@srvid		smallint,
		@dso_class	smallint,	/* omni's attribute  class */
		@attrib		smallint,	/* attr. id for ext. login */
		@action		smallint,
		@dummy		int,
		@HA_CERTIFIED	tinyint,   /* Is the SP HA certified ? */
		@retstat	int,
		@srvclass	smallint   

select @srid = -1
select @retstat = 0
select @HA_CERTIFIED = 0




/* check to see if we are using HA specific SP for a HA enabled server */
exec @retstat = sp_ha_check_certified 'sp_dropexternlogin', @HA_CERTIFIED
if (@retstat != 0)
        return (1)

/*
**  If we're in a transaction, disallow this since it might make recovery
**  impossible.
*/
	if @@trancount > 0
	BEGIN
		/*
		** 17260 "Can't run '%1!' from within a transaction."
		*/
		raiserror 17260, "sp_dropexternlogin"
		return (1)
	END

/*
** Validate the server name.
*/	


	select	@srvid = srvid,  @srvclass=srvclass
		from	master.dbo.sysservers
		where	srvname = @server
	if @@rowcount != 1
	BEGIN
		/*
		** 18307, "Server name '%1!' does not exist in sysservers."
		*/
		raiserror 18307, @server
		return(1)
	END

/*
**  If @rolename was specified, ignore @loginame
*/
	if @rolename is not NULL
	BEGIN	
		select @loginame = NULL
/*
**  Check that the @rolename is valid.
*/
		select @srid = srid from master.dbo.syssrvroles 
			where name = @rolename
		if @@rowcount != 1
		BEGIN
			/* 
			** 18342, "Invalid name '%1!'. This role or user does 
			** not exist in this SQL Server."  
			*/ 
			raiserror 18342, @rolename
			return (1)
		END
	END

	if @loginame is NULL
	BEGIN
		select @suid = -1
	END
	else
	BEGIN
/*
**  Check that the @loginame is valid.
*/
		select @suid = suid
			from master.dbo.syslogins
			where name = @loginame
		if @@rowcount != 1
		BEGIN
			/*		
			** 18294 "User '%1!' is not a local user -- request denied."
			*/
			raiserror 18294, @loginame
			return (1)
		END
	END
/*
** Only a user with sa_role or sso_role can add extern logins for another
** user or for a role.
*/
	if @suid != suser_id()
	BEGIN
		/*
		** check if user has sa or sso role, proc_role will
		** also do auditing if required. proc_role will also
		** print error message if required.
		*/
		if (charindex("sa_role",show_role()) = 0 and
			charindex("sso_role",show_role()) = 0)
		BEGIN
			select @dummy = proc_role("sa_role")
			select @dummy = proc_role("sso_role")
			return (1)
		END
	END



/*
**  Delete the remote login.
*/

	if ((@srvclass != 12) and (@srvclass != 14) and (@srvclass != 15))
		select @dso_class = 9
	else
		select @dso_class = 21

        select @attrib = 0

	delete	master.dbo.sysattributes
		where	class = @dso_class and attribute = @attrib and
			object_info1 = @srvid and object = @suid and
			(object_info2 = @srid or object_info2 is null)
/*
** Check @@rowcount when it works
*/
	if @@rowcount > 0
	BEGIN
		select @action = 3      /* attribute drop */


		/*
		** 18321, "Remote login/alias dropped"
		*/
		exec sp_getmessage 18321, @msg output
		print @msg

		/*
		** Sync the in-memory RDES with the new values
		** in sysattributes.
		*/
		if attrib_notify(@dso_class, @attrib, "EL", @suid, @srvid,
				@srid, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
				@action) = 0
			return (1)
		else
			return (@retstat)
	
	END ELSE
	BEGIN
		/*
		** 18319, "There is no external login for server '%1!'."
		*/
		raiserror 18319, @server
		goto clean_all
	END
END

clean_all:

	return (1)




go
exec sp_procxmode 'sp_dropexternlogin', 'anymode'
go
grant execute on sp_dropexternlogin to public
go
dump tran master with truncate_only
go
dump tran sybsystemprocs with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_dropobjectdef')
begin
	drop procedure sp_dropobjectdef
end
go
print "Installing sp_dropobjectdef"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_dropobjectdef"  18309
**
** 18300, "A server name is not permitted in the local object_name."
** 18301, "Database name '%1!' is not the current database."
** 18302, "User '%1!' is not a valid user in the '%2!' database."
** 18309, "You must be the System Administrator (sa) or Database Owner (dbo) to drop a definition for another user's table."
** 18310, "Table has not been defined."
** 18311, "You cannot remove a table definition for a table that has been created. Drop the table first."
*/
create procedure sp_dropobjectdef
	@tablename 	varchar(1023)	/* table name */
as begin

declare		@uid		int,
		@dso_class	smallint,
		@attrib		smallint,
		@dot		tinyint,
		@db_name	varchar(255),
		@nodb		varchar(511),
		@user_name	varchar(255),
		@tabname	varchar(255),
		@dummy		int

	set nocount on

	/*
	** The table name cannot contain a server name
	*/
	if @tablename like "%.%.%.%"
	begin
		/*
		** 18300, "A server name is not permitted in the local object_name."     
		*/
		raiserror 18300
		return (1)
	end

	/*
	** Check that @tablename refers to object in current database,
	** and determine correct user id.
	*/
	if @tablename like "%.%.%"
	begin
		select @dot = charindex(".", @tablename)
		select @db_name = substring(@tablename, 1, @dot - 1)

		if @db_name != db_name()
		begin
			/*
			** 18301, "Database name '%1!' is not the current database."
			*/
  			raiserror 18301, @db_name
			return (1)
		end

		select @nodb = substring(@tablename, @dot + 1, 511)
		select @dot = charindex(".", @nodb)
		select @user_name = substring(@nodb, 1, @dot - 1)

		if @user_name is NULL
		begin
			select @uid = user_id()
		end
		else
		begin
			select @uid = user_id(@user_name)
			if @uid is NULL
			begin
				select @db_name = db_name()
				/*
				**  18302, "User '%1!' is not a valid user in the '%2!' database."
				*/
				raiserror 18302, @user_name, @db_name
				return (1)
			end
		end

		select @tabname = substring(@nodb, @dot + 1, 255)
	
	end
	else if @tablename like "%.%"
	begin
		select @dot = charindex(".", @tablename)
		select @user_name = substring(@tablename, 1, @dot - 1)

		if @user_name is NULL
		begin
			select @uid = user_id()
		end
		else
		begin
			select @uid = user_id(@user_name)
			if @uid is NULL
			begin
				select @db_name = db_name()						       /*
				**  18302, "User '%1!' is not a valid user in the '%2!' database."
				*/
  				raiserror 18302, @user_name, @db_name
				return (1)
			end
		end

		select @tabname = substring(@tablename, @dot + 1, 255)

	end
	else
	begin
		select @uid = user_id()
		select @tabname = @tablename
	end

	/*
	** Only sa or dbo can drop a definition for another user's table.
	*/
	if @uid != user_id()
	BEGIN
		/*
		** check if user has sa role, proc_role will
		** also do auditing if required. proc_role will also
		** print error message if required.
		*/
		if (charindex("sa_role",show_role()) = 0)
		BEGIN
			select @dummy = proc_role("sa_role")
			return (1)
		END
	END

	/*
	** Strip out quotes from table name if quoted identifier is
	** on
	*/
	if @tabname like '"%"'
	begin
        	select @tabname = substring(@tabname,2,char_length(@tabname) - 2)
	end


	/*
	** see if the table has already been defined.
	*/
	select @dso_class = 9, @attrib = 1

	if not exists (select * from sysattributes
			where class = @dso_class and attribute = @attrib and
			object_cinfo = @tabname and object_info1 = @uid)
	begin
		/*
		**  18310, "Table has not been defined."
		*/
		raiserror 18310
		return (1)
	end

	/*
	** see if the table has already been created.
	*/
	if exists (select * from sysobjects where name = @tabname
			and uid = @uid and type = 'U')
	begin
		/*
		** 18311, "You cannot remove .... Drop the table first."
		*/
		raiserror 18311
		return (1)
	end

	/*
	** Ok; delete the row from sysattributes.
	*/
	delete sysattributes
		where	class = @dso_class and
			attribute = @attrib and
			object_cinfo = @tabname and
			object_info1 = @uid

	return (0)
end

go
exec sp_procxmode 'sp_dropobjectdef', 'anymode'
go
grant execute on sp_dropobjectdef to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_droptabledef')
begin
	drop procedure sp_droptabledef
end
go
print "Installing sp_droptabledef"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/* 
** Omni only
*/
create procedure sp_droptabledef
	@tablename 	varchar(767)	/* table name */
as begin
	declare	@status		int

	exec @status = sp_dropobjectdef @tablename
	return(@status)
end
go
exec sp_procxmode 'sp_droptabledef', 'anymode'
go
grant execute on sp_droptabledef to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpexternlogin')
begin
	drop procedure sp_helpexternlogin
end
go
print "Installing sp_helpexternlogin"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_helpexternlogin"
**
** 17260, "Can't run '%1!' from within a transaction."
** 17270, "There is not a server named '%1!'."
** 17271, "'%1!' is the local server - remote login not applicable."
** 18294, "User '%1!' is not a local user -- request denied."
** 18295, "Only the 'sa' may update another's external login."
** 18296, "External login updated."
** 18297, "User '%1!' will be known as '%2!' in remote server '%3!'."
** 18342, "Invalid name '%1!'. This role or user does not exist in this SQL Server." 
*/
create procedure sp_helpexternlogin
	@server		varchar(255) = NULL,	/* name of remote server */
	@loginame	varchar(255) = NULL,	/* user's local name */
	@rolename	varchar(255) = NULL	/* role name */
AS
BEGIN

	declare	@srvid	smallint

/*
**  Check that the server name is valid.
*/
	IF @server is not null
	BEGIN
		select @srvid = srvid from master.dbo.sysservers
				where srvname = @server

		if @@rowcount = 0
		BEGIN
			/*		
			** 17270  "There is not a server named %1!"  
			*/
			raiserror 17270, @server
			return (1)
		END

		/*
		**  Check for local server.
		*/
		if @srvid = 0
		BEGIN
			/*		
			** 17271 "'%1!' is the local server - remote login
			** not applicable."
			*/
			raiserror 17271, @server
			return (1)
		END
	END
	ELSE
	BEGIN
		select @server = "%"
	END

/*
**  Check that the @loginame is valid.
*/
	if @loginame is not null
	BEGIN
		if not exists (select * from master.dbo.syslogins
			where name = @loginame)
		BEGIN
			/*		
			** 18294 "User '%1!' is not a local user --
			** request denied."
			*/
			raiserror 18294, @loginame
			return (1)
		END
	END
	ELSE
	BEGIN
		select @loginame = "%"
	END

/*
**  Check that the @rolename is valid.
*/
	if @rolename is not null
	BEGIN
		if not exists (select * from master.dbo.syssrvroles
			where name = @rolename)
		BEGIN
			/*
			** 18342, "Invalid name '%1!'. This role or user does
			** not exist in this SQL Server."
			*/
			raiserror 18342, @rolename
			return (1)
		END
	END
	ELSE
	BEGIN
		select @rolename = "%"
	END

/*
**  If only a @rolename was supplied, don't display @loginame mappings
*/
	if @loginame = "%" and @rolename != "%"
		goto display_roles

/*
**  Display external logins that are mapped to local login names as well as
**  external logins that are mapped to a NULL login name. If a specific
**  local login name was requested, only display its entries.
*/

		SELECT	"Server" = s.srvname, 
			"Login" = l.name, 
			"Externlogin" = a.object_cinfo
		INTO #helpextern1rs
		FROM	master.dbo.sysattributes a,
			master.dbo.sysservers s,
			master.dbo.syslogins l
		WHERE	a.class = 9 AND
			a.object_type = "EL" AND
			a.object_info1 = s.srvid AND
			s.srvname LIKE @server AND
			a.object = l.suid AND
			l.name LIKE @loginame
		UNION
		SELECT	s.srvname, 
			NULL, 
			a.object_cinfo
		FROM	master.dbo.sysattributes a,
			master.dbo.sysservers s
		WHERE	a.class = 9 AND
			a.object_type = "EL" AND
			a.object_info1 = s.srvid AND
			s.srvname LIKE @server AND
			a.object_info2 = -1 AND
			a.object = -1 AND
			@loginame = "%"
	exec sp_autoformat @fulltabname = #helpextern1rs,
		@orderby = "ORDER BY Server, Login"		
	drop table #helpextern1rs

/*
** if a specific @loginame was supplied and @rolename wasn't, don't
** display @rolename mappings.
*/
	if @loginame != "%" and @rolename = "%"
		goto done

display_roles:


/*
**  Display external logins that are mapped to role names.
*/
		SELECT	"Server" = s.srvname, 
			"Roles" = r.name, 
			"Externlogin" = a.object_cinfo
		INTO #helpextern2rs
		FROM	master.dbo.sysattributes a,
			master.dbo.sysservers s,
			master.dbo.syssrvroles r
		WHERE	a.class = 9 AND
			a.object_type = "EL" AND
			a.object_info1 = s.srvid AND
			s.srvname LIKE @server AND
			a.object_info2 = r.srid AND
			r.name LIKE @rolename
		exec sp_autoformat @fulltabname = #helpextern2rs,
			@orderby = "ORDER BY 'Server', 'Roles'"		
		drop table #helpextern2rs

done:

	return(0)
END


go
exec sp_procxmode 'sp_helpexternlogin', 'anymode'
go
grant execute on sp_helpexternlogin to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpobjectdef')
begin
	drop procedure sp_helpobjectdef
end
go
print "Installing sp_helpobjectdef"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Omni only
**
** Messages for "sp_helpobjectdef"
**
** 17240, "'%1!' is not a valid name."
** 17461, "Object does not exist in this database." 
** 18300, "A server name is not permitted in the local object_name." 
** 18301, "Database name '%1!' is not your current database."
** 18302, "User '%1!' is not a valid user in the '%2!' database."
*/
create procedure sp_helpobjectdef
@objname varchar(1023) = NULL			/* object name we're after */
as

declare @retcode	int,
	@len1		int,
	@len2		int
declare @dso_class 	smallint, 
	@attrib 	smallint, 
	@uid 		int,
	@maxlen		int
declare @server 	varchar(255),
	@dbname		varchar(255),
	@owner		varchar(255),
	@object		varchar(255)

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

/*
** Search sysattributes using the DSO class 
** and Object Definition attribute.
*/
select @dso_class = 9, @attrib = 1

/*
**  If no object name is supplied, give info about all Object Definitions
*/
if @objname is NULL
begin
		select  Owner = user_name(a.object_info1),
			Object = a.object_cinfo,
			Type = v.name,
			Definition = a.char_value,
			case
				when a.int_value & 1 > 0 then 'implicit'
				else 'explicit'
			end as Usage,
			case
				when a.int_value & 4 > 0 then 'non transactional'
				when a.int_value & 2 > 0 then 'transactional'
				when a.object_info2 = 3 then 'transactional'
				else NULL
			end as Status
		into #sphelpobjectdef1rs
		from 	sysattributes a, master.dbo.spt_values v 
		where 	a.class = @dso_class and a.attribute = @attrib
			and a.object_info2 = v.number and v.type = 'Y'
			and v.name != 'view'
		exec sp_autoformat @fulltabname = #sphelpobjectdef1rs,
			@orderby = "order by Owner, Object"
		drop table #sphelpobjectdef1rs

	return (0)
end

/*
** Check that @objname refers to object in current database,
** and determine correct user id.
*/
exec @retcode = sp_namecrack @objname, @server output, @dbname output,
		@owner output, @object output
if @retcode != 0
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @objname
	return (1)

end

/*
** Make sure that a server name wasn't supplied
*/
if @server is not null
begin
	/*
	** 18300, "A server name is not permitted in the local object_name." 
	*/
	raiserror 18300
	return (1)
end

/*
** If a database name was supplied, it must be for the current database
*/
if @dbname is not null
begin
	if @dbname != db_name()
	begin
		/*
		** 18301, "Database name '%1!' is not your current database."
		*/
		raiserror 18301, @dbname
		return (1)
	end
end

/*
** If an owner name was supplied, validate it as well
*/
if @owner is NULL
begin
	select @uid = user_id()
end
else
begin
	select @uid = user_id(@owner)
	if @uid is NULL
	begin
		select @dbname = db_name()
		/*
		** 18302, "User '%1!' is not a valid user in the '%2!' database."
		*/
		raiserror 18302, @owner, @dbname
		return (1)
	end
end

/*
** Check that the local object name is valid
*/
select @maxlen = length from syscolumns
	where id = object_id("sysobjects") and name = "name"

if valid_name(@object, @maxlen) = 0
begin
	/*
	** 17240, "'%1!' is not a valid name."
	*/
	raiserror 17240, @object
	return (1)
end

/*
** Strip out quotes from table name if quoted identifier is
** on
*/
if @object like '"%"'
begin
	select @object = substring(@object,2,char_length(@object) - 2)
end

/*
**  Now check to see if the object is in sysattributes
*/
if not exists (select *
	from sysattributes 
		where class = @dso_class and attribute = @attrib and
			object_cinfo = @object and 
			(object_info1 = @uid or @owner is NULL))

begin
	/* 
	** 17461, "Object does not exist in this database." 
	*/
	raiserror 17461
	return  (1)
end

/*
** The object is in sysattributes, so display the information.
*/
begin
	if @owner is NULL
	begin
		select  Owner = user_name(a.object_info1),
			Object = a.object_cinfo,
			Type = v.name,
			Definition = a.char_value,
			case
				when a.int_value & 1 > 0 then 'implicit'
				else 'explicit'
			end as Usage,
			case
				when a.int_value & 4 > 0 then 'non transactional'
				when a.int_value & 2 > 0 then 'transactional'
				when a.object_info2 = 3 then 'transactional'
				else NULL
			end as Status
		into #sphelpobjectdef2rs
		from 	sysattributes a, master.dbo.spt_values v 
		where 	a.class = @dso_class and a.attribute = @attrib
			and a.object_info2 = v.number and v.type = 'Y'
			and v.name != 'view'
			and a.object_cinfo = @object	
		exec sp_autoformat @fulltabname = #sphelpobjectdef2rs,
			@orderby = "order by Owner" 
		drop table #sphelpobjectdef2rs
	end
	else
	begin
		select  Owner = user_name(a.object_info1),
			Object = a.object_cinfo,
			Type = v.name,
			Definition = a.char_value,
			case
				when a.int_value & 1 > 0 then 'implicit'
				else 'explicit'
			end as Usage,
			case
				when a.int_value & 4 > 0 then 'non transactional'
				when a.int_value & 2 > 0 then 'transactional'
				when a.object_info2 = 3 then 'transactional'
				else NULL
			end as Status
		into #sphelpobjectdef3rs
		from 	sysattributes a, master.dbo.spt_values v 
		where 	a.class = @dso_class and a.attribute = @attrib
			and a.object_info2 = v.number and v.type = 'Y'
			and v.name != 'view'
			and a.object_cinfo = @object and a.object_info1 = @uid
		exec sp_autoformat @fulltabname = #sphelpobjectdef3rs
		drop table #sphelpobjectdef3rs
	end
end

return (0)

go
exec sp_procxmode 'sp_helpobjectdef', 'anymode'
go
grant execute on sp_helpobjectdef to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_passthru')
begin
	drop procedure sp_passthru
end
go
print "Installing sp_passthru"
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

/*
** Omni only
*/
create procedure sp_passthru
	@server varchar(255),		/* name of remote server */
	@query varchar(255),		/* language buffer to be executed remotely */
	@errcode int output,		/* error number generated by query */
	@errmsg varchar(1024) output,	/* error message generated by query */
	@rowcount int output		/* number of rows read by the query */

/*
** The caller may supply up to 250 additional output arguments of the
** appropriate datatypes to receive the values of successive columns 
** returned from the query.
*/

as
/*
** All of the processing, including setting of the return status, is
** handled by the internal OmniSQL Server function "passthru()".
**
** A status of 1 is returned if an error is detected during, either
** the remote execution of the language buffer or during the processing
** of the results.  A status of 0 indicates a successful completion.
*/
go
exec sp_procxmode 'sp_passthru', 'anymode'
go
grant execute on sp_passthru to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
/* We have to make sure that the Sybase 2PC stored procedures will be */
/* dropped both from master and sybsystemprocs during the execution of */
/* of installmaster.  installcommit will create them when it is executed */
/*
** raiserror Messages for dropcommit [Total 1]
**
** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
*/

use sybsystemprocs
go

if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_start_xact')
begin
	print "Dropping sp_start_xact from sybsystemprocs."
	drop procedure sp_start_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_commit_xact')
begin
	print "Dropping sp_commit_xact from sybsystemprocs."
	drop procedure sp_commit_xact
end
go

if (select db_id()) > 1
	dump tran sybsystemprocs with truncate_only
else
	dump tran master with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_abort_xact')
begin
	print "Dropping sp_abort_xact from sybsystemprocs."
	drop procedure sp_abort_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_remove_xact')
begin
	print "Dropping sp_remove_xact from sybsystemprocs."
	drop procedure sp_remove_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_stat_xact')
begin
	print "Dropping sp_stat_xact"
	drop procedure sp_stat_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_scan_xact')
begin
	print "Dropping sp_scan_xact from sybsystemprocs."
	drop procedure sp_scan_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_probe_xact')
begin
	print "Dropping sp_probe_xact from sybsystemprocs."
	drop procedure sp_probe_xact
end
go

if (select db_id()) > 1
	dump tran sybsystemprocs with truncate_only
else
	dump tran master with truncate_only
go

use master
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_start_xact')
begin
	print "Dropping sp_start_xact from master."
	drop procedure sp_start_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_commit_xact')
begin
	print "Dropping sp_commit_xact from master."
	drop procedure sp_commit_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_abort_xact')
begin
	print "Dropping sp_abort_xact from master."
	drop procedure sp_abort_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_remove_xact')
begin
	print "Dropping sp_remove_xact from master."
	drop procedure sp_remove_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_stat_xact')
begin
	print "Dropping sp_stat_xact from master."
	drop procedure sp_stat_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_scan_xact')
begin
	print "Dropping sp_scan_xact from master."
	drop procedure sp_scan_xact
end
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_probe_xact')
begin
	print "Dropping sp_probe_xact from master."
	drop procedure sp_probe_xact
end
go

if (select db_id()) > 1
	dump tran sybsystemprocs with truncate_only
else
	dump tran master with truncate_only
go

use sybsystemprocs
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_checknames')
begin
	drop procedure sp_checknames
end
go
print "Installing sp_checknames"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	4.8	1.1	06/14/90	sproc/src/checknames */


create procedure sp_checknames
@mode varchar(20) = NULL		/* mode of operation; e.g. 'silent' */
as

declare @msilent	int		/* set to 1 if 'silent' mode is on */
declare @ret_val	int		/* set to 1 if we find funny char */
declare @codepoint	tinyint
declare @dbname		varchar(30)	/* holds database name */
declare @msg		varchar(255)	/* used for messages to user */
declare @pat		varchar(255)	/* holds the pattern to search for */


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

set nocount on

if (@mode like '%help%')
begin
	print 'sp_checknames is used to search for non 7-bit ASCII characters'
	print 'in several important columns of system tables.  The following'
	print 'columns are searched:'
	print ' '
	print '    In "master":'
	print '        sysdatabases.name'
	print '        sysdevices.name'
	print '        syslogins.name'
	print '        syslogins.dbname'
	print '        syslogins.password'
	print '        sysremotelogins.remoteusername'
	print '        sysservers.srvname'
	print '        sysservers.srvnetname'
	print ' '
	print '    In all databases:'
	print '        syscolumns.name'
	print '        sysindexes.name'
	print '        sysobjects.name'
	print '        syssegments.name'
	print '        systypes.name'
	print '        sysusers.name'
	print ' '

	return (0)
end

/*
**  First, initialize return value, and set up mode variables:
*/
select @ret_val = 0

if (@mode like '%silent%')
	select @msilent = 1
else
	select @msilent = 0


/*
**  Now, initialize the pattern string we will search for:
**	@pat contains the pattern "NOT IN THE RANGE OF all 7-bit ASCII
**	characters, except the right bracket "]".  (As of release 4.9.1,
**	it is not possible to represent the right bracket in the non-
**	inclusive matching pattern.)
*/
select @pat = '%[^- !"#$%&''()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\^_`abcdefghijklmnopqrstuvwxyz{|}~'

select @codepoint = 0
while (@codepoint < 32)
begin
	select @pat = @pat + char(@codepoint)
	select @codepoint = @codepoint + 1
end

select @pat = @pat + char(127) + ']%'


/*
**  Get the database name we are in:
*/
select @dbname = db_name()

if (@msilent = 0)
begin
	print ' '
	select @msg = 'Looking for non 7-bit ASCII characters in the system ' +
			'tables of database:  "' + @dbname + '"'
	print @msg
	print ' '
end


/*
**  Look through these only if in the master database:
*/
if (@dbname = 'master')
begin
    if exists (select name from master.dbo.sysdatabases
		    where name like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "sysdatabases.name"'
	print ' '
	print 'The following database names contain non 7-bit ASCII characters.'
	print 'If you wish to change their names, use "sp_renamedb":'
	print ' '
	select dbid,name from master.dbo.sysdatabases
			where name like @pat
    end

    if exists (select name from master.dbo.sysdevices
		    where name like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "sysdevices.name"'
	print ' '
	print 'The following device names contain non 7-bit ASCII characters.'
	print 'If you wish to change their names, use "UPDATE":'
        print ' '
	select name from master.dbo.sysdevices
			where name like @pat
    end

    if exists (select name from master.dbo.syslogins
		    where name like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "syslogins.name"'
        print ' '
	print 'The following login names contain non 7-bit ASCII characters.'
	print 'If you wish to change these names, use "sp_droplogin" and'
	print '"sp_addlogin":'
        print ' '
	select suid,name from master.dbo.syslogins
			where name like @pat
    end

    if exists (select dbname from master.dbo.syslogins
		    where dbname like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "syslogins.dbname"'
	print ' '
	print 'The following logins have default database names that contain'
	print 'non 7-bit ASCII characters.  If you wish to change them use'
	print '"sp_defaultdb":'
        print ' '
	select suid,name,dbname from master.dbo.syslogins
			where dbname like @pat
    end

/*
**  @pat contains the pattern "NOT IN THE RANGE OF all 7-bit ASCII characters,
**  except the right bracket ("]").  Thus, if a password contains the right
**  bracket character, this non-inclusive matching pattern will not work, and
**  sp_checknames will think the password contains non 7-bit ASCII characters.
*/
    if exists (select password from master.dbo.syslogins
		    where password like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "syslogins.password"'
	print ' '
	print 'The following logins have passwords that contain non 7-bit'
	print 'ASCII characters.  If you wish to change them use "sp_password";'
	print 'Remember, only the sa and the login itself may examine or change'
	print 'the syslogins.password column:'
        print ' '
	select suid,name from master.dbo.syslogins
			where password like @pat
    end

    if exists (select remoteusername from master.dbo.sysremotelogins
		    where remoteusername like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "sysremotelogins.remoteusername"'
        print ' '
	print 'The following remote login names contain non 7-bit ASCII'
	print 'characters.  If you wish to change these names, use'
	print '"sp_dropremotelogin" and "sp_addremotelogin":'
        print ' '
	select remoteserverid,remoteusername from master.dbo.sysremotelogins
			where remoteusername like @pat
    end

    if exists (select srvname from master.dbo.sysservers
		    where srvname like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "sysservers.srvname"'
        print ' '
	print 'The following server names contain non 7-bit ASCII characters.'
	print 'If you wish to change their names, use "sp_dropserver" and'
	print '"sp_addserver":'
        print ' '
	select srvid,srvname from master.dbo.sysservers
			where srvname like @pat
    end

    if exists (select srvnetname from master.dbo.sysservers
		    where srvnetname like @pat)
    begin
	if (@msilent = 1)
	    return (1)

	select @ret_val = 1
	print ' '
	print '==============================================================='
	print 'Table.Column name:  "sysservers.srvnetname"'
        print ' '
	print 'The following servers have "interface file" names that contain'
	print 'non 7-bit ASCII characters.  If you wish to change these names,'
	print 'use "UPDATE":'
        print ' '
	select srvid,srvname,srvnetname from master.dbo.sysservers
			where srvnetname like @pat
    end

end


/*
**  For *ALL* databases, we want to look through these:
*/
if exists (select name from dbo.syscolumns
	    where name like @pat)
begin
    if (@msilent = 1)
	return (1)

    select @ret_val = 1
    print ' '
    print '==============================================================='
    print 'Table.Column name:  "syscolumns.name"'
    print ' '
    print 'The following column and parameter names contain non 7-bit ASCII'
    print 'characters.  If you wish to change these names, use "sp_rename":'
    print ' '
    select objname=o.name,colname=c.name from dbo.syscolumns c, dbo.sysobjects o
		where c.name like @pat and o.id = c.id
end

if exists (select name from dbo.sysindexes
            where name like @pat
                  and indid > 0)
begin
    if (@msilent = 1)
	return (1)

    select @ret_val = 1
    print ' '
    print '==============================================================='
    print 'Table.Column name:  "sysindexes.name"'
    print ' '
    print 'The following index names contain non 7-bit ASCII characters.'
    print 'If you wish to change these names, use "UPDATE":'
    print ' '
    select id,indid,name from dbo.sysindexes
		where name like @pat
end

if exists (select name from dbo.sysobjects
	    where name like @pat)
begin
    if (@msilent = 1)
	return (1)

    select @ret_val = 1
    print ' '
    print '==============================================================='
    print 'Table.Column name:  "sysobjects.name"'
    print ' '
    print 'The following object names contain non 7-bit ASCII characters.'
    print 'If you wish to change these names, use "sp_rename":'
    print ' '
    select owner=u.name,o.name from dbo.sysobjects o,dbo.sysusers u
		where o.name like @pat and o.uid=u.uid
end

if exists (select name from dbo.syssegments
	    where name like @pat)
begin
    if (@msilent = 1)
	return (1)

    select @ret_val = 1
    print ' '
    print '==============================================================='
    print 'Table.Column name:  "syssegments.name"'
    print ' '
    print 'The following segment names contain non 7-bit ASCII characters.'
    print 'If you wish to change these names, use "UPDATE":'
    print ' '
    select segment,name from dbo.syssegments
		where name like @pat
end

if exists (select name from dbo.systypes
	    where name like @pat)
begin
    if (@msilent = 1)
	return (1)

    select @ret_val = 1
    print ' '
    print '==============================================================='
    print 'Table.Column name:  "systypes.name"'
    print ' '
    print 'The following datatype names contain non 7-bit ASCII characters.'
    print 'If you wish to change these names, use "sp_rename":'
    print ' '
    select name from dbo.systypes
		where name like @pat
end

if exists (select name from dbo.sysusers
	    where name like @pat)
begin
    if (@msilent = 1)
	return (1)

    select @ret_val = 1
    print ' '
    print '==============================================================='
    print 'Table.Column name:  "sysusers.name"'
    print ' '
    print 'The following user or group names contain non 7-bit ASCII'
    print 'characters.  If you wish to change these names, use "UPDATE":'
    print ' '
    select suid,uid,name from dbo.sysusers
		where name like @pat
end

if (@ret_val = 0  and  @msilent = 0)
begin
    select @msg = 'Good news!  Database "' + @dbname + '" has no obj/user/etc.'
    print @msg
    print 'names that contain non 7-bit ASCII characters.'
end

return (@ret_val)
go
exec sp_procxmode 'sp_checknames', 'anymode'
go
grant execute on sp_checknames to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_help')
begin
	drop procedure sp_ddlgen_help
end
go
print "Installing sp_ddlgen_help"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:12 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen_help [Total 1]
**
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen_help [Total 1]
**
** 18954, "Usage:"
*/
/*
** End spgenmsgs.pl output.
*/

exec sp_dbxt_recreate_proc sp_ddlgen_help
go

/*
** sp_ddlgen_help
**
**	Generate usage/help information for this sproc interface.
**
** Parameters:
**	@objtype	- Type of object to get more help on using sp_ddlgen.
*/
create procedure sp_ddlgen_help(
			  @objtype		varchar(30)	= NULL
			, @valid_objtypes	varchar(256)	= NULL
) as
begin
	declare @msg	varchar(256)
	      , @usage	varchar(10)

	exec sp_getmessage 18954, @usage output

	-- If user didn't request for a particular object type, generate
	-- basic help information.
	--
	if (@objtype IS NULL)
	begin
		select @msg = @usage + " sp_ddlgen [ 'help' ]"
		print @msg

		-- Show basic help usage info.
		select @msg = @usage + " sp_ddlgen 'help' [, %1! ]"
		print @msg, @valid_objtypes

		-- Show basic ddl gen usage for all object types.
		select @msg = @usage + " sp_ddlgen {" + @valid_objtypes + '}'
				     + ", @objname"
		print @msg

		return 0
	end

	-- Generate usage information for each object type.
	--
	if (@objtype = 'database')
	begin
		select @msg = @usage + " sp_ddlgen 'database' [, @dbname ]"
		print @msg

		-- Show individual examples...
		select @msg = @usage + " sp_ddlgen 'database'"
		print @msg

		select @msg = @usage + " sp_ddlgen 'database', 'master'"
		print @msg

		select @msg = @usage + " sp_ddlgen 'database', 'mydb%%'"
		print @msg

		select @msg = @usage + " sp_ddlgen 'database', '%%'"
		print @msg
	end
	else
	begin
		raiserror 19194, @objtype, @valid_objtypes
		return 1
	end


	return 0
end
go

if (@@error != 0) select syb_quit()
go


go
exec sp_procxmode 'sp_ddlgen_help', 'anymode'
go
grant execute on sp_ddlgen_help to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_permissions')
begin
	drop procedure sp_ddlgen_permissions
end
go
print "Installing sp_ddlgen_permissions"
go

/*
** Generated by spgenmsgs.pl on Sun Feb 15 23:50:07 2009 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen_permissions [Total 1]
**
** 17230, "You must be the System Administrator (SA) or the Database Owner (dbo) to execute this procedure."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen_permissions [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

exec sp_dbxt_recreate_proc sp_ddlgen_permissions
go

/*
** sp_ddlgen_permissions
**
**	Common sproc to implement permissions checking for all DDL gen commands.
**	For now we implement a simple rule that user has to have 'sa_role' to
**	generate DDL. In future if/when object-level DDL generation is allowed,
**	we have to make this permission checking more flexible by pushing it
**	into each @objtype-DDL-generating sproc.
**
** Object-type specific permission checks:
**
**  database:
**	. If wild-cards are used for @objname, need sa_role privilege.
**	  (This can probably be improved in the future to allow DBO of a
**	   set of dbs named 'mydb%' to run this sproc w/o sa_role.)
**	. If a single-db name is provided, you need either sa_role or DBO.
**
** Parameters:
**	@objtype	- Type of object for which DDL is being generated.
**	@objname	- Name of the object.
**
** Returns:
**	0		- Permissions failed.
**	Non-zero	- Otherwise.
*/
create procedure sp_ddlgen_permissions(
			  @objtype		varchar(30)
			, @objname		varchar(30)
) as
begin
	declare @is_dbo			int
	      , @procname		varchar(45)
	      , @lcl_sarole		int
	      , @status3		int
	      , @stat3_tempdb 		int	    
	      , @suid			int
	      , @dummy			int
	      , @sdc_local_temp_db	int

	select @is_dbo = 0
	select @sdc_local_temp_db = 0

 	select @stat3_tempdb = number
        from master.dbo.spt_values
        where  type = "D3"
          and  name = "TEMPDB STATUS MASK"

	-- Find whether the user has sa_role or not. --
	/*
	** Why do not we use proc_role("sa_role") to achieve this?
	** The function proc_role(), when executed by a user with
	** no sa_role/sso_role prints error message which is
	** not desired in our case. Fortunately show_role() doesn't
	** do such mischief. Hence, this not-so-straightforward
	** way of finding it.
	*/
	select @lcl_sarole = charindex("sa_role", show_role())

	if (@objtype = 'database')
	begin
		-- If dbname w/o patterns was specified, check if user is
		-- DBO. This DBO check has to be carefully done in case of
		-- local user/system temp db in sdc, which can be followed
		-- from the pseudo code flow shown here.
		--
		-- if (single-database)
		-- {
		--	/* Special handling for local-temp-db */
		--	if (sdc-mode and local-temp-db)
		--	{
		--		if (user_has_sa_role)
		--			pass permission;
		--
		--		else if (current user is dbo of this db)
		--			pass permission;
		--
		--		else
		--		{
		--			call sp_is_dbo;
		--			/* 
		--			** The above call is multi-purpose
		--			** call. What it does
		--			** if (database_is_inaccessible)
		--			** {
		--			**	Error out.
		--			** }
		--			** else 
		--			** {
		--			**	Check whether the user is 
		--			**	dbo taking into consideration,
		--			**	the aliased dbo too.			
		--			** }
		--			*/
		--
		--			if (not dbo)
		--				raise the error 17230
		--		}
		--	}
		--	else /* Normal handling*/
		--	{
		--		/* check if the user is_dbo */
		--		call sp_is_dbo;
		--
		--		if (not dbo)
		--			raise the error 17230
		--	}
		-- }
		-- else /* multiple databases specified with wild-card */
		-- {
		--	/* It can be executed only by sa_role-user */
		--
		-- 	if (user_has_sa_role)
		--		pass permission;
		--
		--	else
		--		do not pass permission;
		--		raise the error 567
		-- }
		--
		-- Thus, the procedure ends.
		--
		if (@lcl_sarole > 0)
		begin
			return 1		
		end

		if (charindex('%', @objname) = 0)
		begin
			select @status3 = status3,
			       @suid = suid
			from master.dbo.sysdatabases
			where name = @objname
			
			select @sdc_local_temp_db = 1
			where ((@@clustermode = 'shared disk cluster')
		                and ((@status3 & @stat3_tempdb) in 
				     (select number 
				      from master.dbo.spt_values
  				      where name in ( "local user temp db",
						      "local system temp db"))))

			if ((@sdc_local_temp_db = 1) and (@suid = suser_id()))
			begin
				return 1
			end
			else
			begin
				select @procname = 
						@objname + "..sp_is_dbo"
				exec @is_dbo = @procname @objname

				-- Return an error/failure if the sub-proc 
				-- were not to be found.
				-- 
				if (@@error!= 0)
					return 0
				
				if (@is_dbo != 1)
				begin 
					raiserror 17230
					return 0
				end
			end
		end
		else
		begin
			-- In case of multiple database, only the user having
			-- "sa_role" can execute sp_ddlgen. However, if the 
			-- user had sa_role, the procedure must have already 
			-- returned by now.
			-- This means user doesn't have sa_role. Hence, raise 
			-- server error message 567. 
                        -- "You must have the following role(s) to execute this
                        -- command/procedure: '%.*s'. Please contact a user
                        -- with the appropriate role for help."
			-- This can be achieved by calling the builtin function
			-- proc_role("sa_role"). Basically, this builtin when
			-- executed by non-sa_role gives the error message 567.
                        --
			select @dummy = proc_role("sa_role")
			return 0
		end
	end
end
go

if (@@error != 0) select syb_quit()
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_db_print_with_clause')
begin
	drop procedure sp_ddlgen_db_print_with_clause
end
go
print "Installing sp_ddlgen_db_print_with_clause"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_db_print_alterdb')
begin
	drop procedure sp_ddlgen_db_print_alterdb
end
go
print "Installing sp_ddlgen_db_print_alterdb"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_database')
begin
	drop procedure sp_ddlgen_database
end
go
print "Installing sp_ddlgen_database"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:11 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen_database [Total 2]
**
** 18322, "There is not a database named '%1!'."
** 19475, "%1! not supported for archive databases. One or more of the databases named in this operation is an archive database."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen_database [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

-- *************************************************************************** 
exec sp_dbxt_recreate_proc sp_ddlgen_db_print_with_clause
go

/*
** sp_ddlgen_db_print_with_clause
**
**	Print the WITH clauses as required, depending on whether override
**	has been specified, and if the other options like durability or
**	dml_logging need to be printed.
**
** Parameters:
**	@with_override	- Boolean; whether WITH OVERRIDE should be generated.
**	@with_dur_and_dmllog
**			- Boolean; whether WITH DURABILITY AND DML_LOGGING
**			  should be generated.
**	@durability	- DURABILITY setting of db
**	@dmllogging	- DML_LOGGING setting of db
**	@archivedb	- Boolean; whether it's an archive db.
**
** Returns:	0 always.
{
*/
create procedure sp_ddlgen_db_print_with_clause(
			  @with_override	tinyint		output
			, @with_dur_and_dmllog	tinyint		output
			, @durability	 	varchar(13)	= NULL
			, @dmllogging		varchar(9)	= NULL
			, @archivedb		tinyint
) as
begin
	declare @newline	char(1)
	      , @tabchar	char(1)
	      , @override_sql	varchar(13)
	      , @printfmt	varchar(10)	-- Check its length before use.
	      , @withopt_sep	varchar(10)	-- indentation for starting
	      					-- new clause on a new line.
	      , @nextopt_sep	varchar(10)	-- indentation for the next 
	      					-- WITH option.

	select @newline		= char(10)
	     , @tabchar		= char(9)
	     , @override_sql    = "WITH OVERRIDE"
	     , @withopt_sep	= "WITH "
	     , @nextopt_sep	= "   , "

	-- If any disk piece in the current block of rows
	-- had a WITH OVERRIDE setting, then generate that
	-- clause here.
	--
	if (@with_override = 1)
	begin
		select @printfmt = case @archivedb
					when 1 then "%1!-- %2!"
					else        "%1!%2!"
				   end
		print @printfmt, @tabchar, @override_sql

		-- Now that WITH OVERRIDE has been printed, re-set the
		-- indentation string for the remaining WITH options on the
		-- next line.
		--
		select @withopt_sep	= @nextopt_sep
		     , @with_override 	= 0
	end

	-- Print remaining WITH options, using the appropriate indentation
	-- separator.
	--
	if (@with_dur_and_dmllog = 1)
	begin
		if (@durability IS NOT NULL)
		begin
			print "%1!%2!DURABILITY = %3!"
				, @tabchar, @withopt_sep, @durability
		end
		else
		begin
			-- Reset the indentation separation for the next line,
			-- in case both WITH OVERRIDE and WITH DURABILITY
			-- phrases are "missing".
			--
			select @nextopt_sep = @withopt_sep
		end

		print "%1!%2!DML_LOGGING = %3!"
			, @tabchar, @nextopt_sep, @dmllogging

		select @with_dur_and_dmllog = 0
	end
	
	print "go%1!%2!", @newline, @newline

	return 0

end
go

-- *************************************************************************** 
exec sp_dbxt_recreate_proc sp_ddlgen_db_print_alterdb
go

/*
** sp_ddlgen_db_print_alterdb
**
**	Print the ALTER DATABASE clause, with the given parameters. The caller
** 	has already decided that there is a change in disk pieces that needs
**	a new ALTER DATABASE to be issued.
**	This procedure is called to print the start of a new ALTER DATABASE SQL
**	block. It will first terminate a previously generated ALTER DATABASE 
**	block with any required WITH OVERRIDE clause, and then will start a 
**	fresh SQL command.
**
** Parameters:
**	@dbname		- Name of db for which DDL is being generated.
**	@archivedb	- Boolean; whether it's an archive db.
**	@alterdb_sql	- SQL for 'ALTER DATABASE'
**	@segment	- Segment's characteristics
**	@durability	- DURABILITY setting of db
**	@dmllogging	- DML_LOGGING setting of db
**	@with_override	- Boolean; whether WITH OVERRIDE should be generated.
**	@with_dur_and_dmllog
**			- Boolean; whether WITH DURABILITY AND DML_LOGGING
**			  should be generated.
**	@prefix		- Prefix string, for formatting.
**
** Returns:	0, always.
{
*/
create procedure sp_ddlgen_db_print_alterdb(
			  @dbname		varchar(30)
			, @archivedb		tinyint
			, @alterdb_sql		varchar(15)
			, @segment		varchar(12)
			, @durability	 	varchar(13)
			, @dmllogging		varchar(9)
			, @trace		int
			, @reason		varchar(30)
			, @with_override	tinyint		output
			, @with_dur_and_dmllog	tinyint		output
			, @prefix		varchar(10)	output
) as
begin -- {
	declare @newline	char(1)
	      , @tabchar	char(1)
	      , @comment	char(3)
	      , @retval		int
	      , @indent		varchar(10)

	select @newline		= char(10)
	     , @tabchar		= char(9)
	     , @comment		= "-- "
	     , @indent		= space(@@nestlevel * 2)


	exec @retval = sp_ddlgen_db_print_with_clause @with_override
						   , @with_dur_and_dmllog
						   , @durability
						   , @dmllogging
						   , @archivedb

	if (@trace = 2)
	begin
		print " "
		print "%1!---- Trace sp_ddlgen_db_print_alterdb ----", @indent
		print "%1!Generate '%2! %3!' because %4!. @archivedb=%5! @segment='%6!'"
			, @indent
			, @alterdb_sql, @dbname, @reason
			, @archivedb, @segment
		print "@with_override=%1! @with_dur_and_dmllog=%2!"
			, @with_override, @with_dur_and_dmllog
		print "%1!---- End Trace sp_ddlgen_db_print_alterdb ----"
			, @indent
		print " "
	end

	-- print: ALTER DATABASE <dbname>
	print "%1! %2!", @alterdb_sql, @dbname

	-- We are restarting a newblock of disk pieces that
	-- will be investigated. Reset 'prev' variables,
	-- and other variables.
	--
	select @with_override = 0
	     , @with_dur_and_dmllog = 0

	select @prefix = @tabchar + case @segment when "log only"
						  then "LOG ON "
						  else "    ON "
				    end
	return 0
end -- }
go

if (@@error != 0) select syb_quit()
go

-- *************************************************************************** 
exec sp_dbxt_recreate_proc sp_ddlgen_database
go

/*
** sp_ddlgen_database
**
**	Entry-point for generating DDL for a database. Currently all we support
**	is the basic create/alter database syntax. Subsequent sp_dboption etc.
**	are not [ to be ] supported. The expectation is that the DDLGen tool
**	will provide those value-adds.
**
** Parameters:
**	@dbname		- Name of db to generate DDL for. Supports wild-cards.
**	@trace		- Trace options (internal use.)
**
** Trace Levels:
** ------------
**	1	- Basic tracing of code flow.
**	2	- Trace alter db SQL generation.
**	1192	- Pretend that this is a 119x server, and ignore the code/data
**		  pieces that exist in 12.5.x, or later, but not in 11.9.x.
**	120	- Pretend that this is a 120.x server, and ignore the code/data
**		  pieces that exist in 12.5.x, or later, but not in 12.0.x.
**		  [ By running in this older-server mode, you can test that
**		    this sproc will correctly collapse multiple alter dbs into
**		    one when possible (ignoring 'crdate'), and will generate
**		    the syntax corectly without unit-specifiers. ]
{
*/
create procedure sp_ddlgen_database(
			  @dbname	varchar(255)	= NULL
			, @trace	int		= 0
) as
begin -- {
	declare @newline	char(1)
	      , @tabchar	char(1)
	      , @retval		int
	      , @objtype	varchar(10)
	      , @objtype_lower	varchar(10)
	      , @prev_dbname	varchar(30)
	      , @devname	varchar(255)
	      , @segment	varchar(12)	-- of current disk piece
	      , @prev_segment	varchar(20)	-- of previous disk piece
	      , @lstart		int
	      , @size_pages	int
	      , @status3	int		-- sysdatabases.status3
	      , @devstat	int		-- sysdevices.status
	      , @devstat2  	int		-- sysdevices.status2
	      , @size_str	varchar(20)	-- size as a string.
	      , @size_comments	varchar(255)	-- size in comments (and other
	      					-- diag info if tracing is ON).
	      , @size_mb	varchar(10)
	      , @prefix		varchar(10)

	      , @create_sql	varchar(6)              
	      , @alterdb_sql	varchar(15)        
	      , @override_sql	varchar(13)         
	      , @local_systempdb_ph	varchar(18)     
	      , @local_usrtempdb_ph	varchar(11)     
	      , @global_usrtempdb_ph	varchar(18) 
	      , @tempdb_ph	varchar(30)	-- used to point to these above.
	      , @imdb_sql	varchar(9)               
	      , @imdb_ph	varchar(30)
	      , @archive_sql	varchar(30)         
	      , @durability_no_recovery_sql	varchar(13)
	      , @durability_at_shutdown_sql	varchar(13)
	      , @durability_full_sql	varchar(6)
	      , @dmllogging_minimal_sql	varchar(7)
	      , @dmllogging_full_sql	varchar(4)
	      
         
	      , @archivedb	tinyint
	      , @usertempdb	tinyint		-- is it a user-created tempdb.
	      , @templatedbname	varchar(30) -- print the template database name
	      , @durability	varchar(13)
	      , @dmllogging	varchar(9)
	      , @instancename	varchar(30)	-- used to print the instance
						-- of which the current database
						-- is local system temporary 
						-- database.
	      , @durability_status	int	--sysdatabases.durability
	      , @dmllogging_status	int	--sysdatabases.status4
	      , @durability_no_recovery_status	int 
	      , @durability_at_shutdown_status	int
	      , @durability_full_status			int
	      , @dmllogging_minimal_status		int   

	      -- # of dbids for which we didn't generate the right #s of rows 
	      -- in the #temp table when compared to the # of rows that exist
	      -- for that db in sysusages.
	      --
	      , @count_failed_dbids	int	

	      -- To account for >2k logical page sizes
	      , @numpgsmb	float


		-- Various status bits in catalogs for re-use.
	      , @stat3_tempdb		int
	      , @stat3_archivedb	int
	      , @stat4_inmem_db		int
	      , @stat4_explicit_no_rec	int

	      , @inmem_db		tinyint
	      , @explicit_no_rec	tinyint
		
	        -- Version sub-string to check against running server.
	      , @ase_1192_str	varchar(30)
	      , @ase_120x_str	varchar(30)
	      , @ase_150x_str	varchar(30)
	      , @ase_155x_str   varchar(30)

	       -- Are we runningin a 12.5x or later server?
	      , @ase_125x_or_gt	tinyint
	      , @ase_150x_or_gt	tinyint
	      , @ase_155x_or_gt tinyint

	      , @sqlstmt	varchar(255)
	      , @indent		varchar(32)
	      , @archivedb_comm	varchar(255)

	      , @comment	char(3)
	      , @pages		char(6)
	      , @crdate		datetime
	      , @prev_crdate	datetime	-- of previous disk piece
	      , @use_crdate	tinyint		-- whether server supports this
	      , @override	tinyint		-- setting of current disk piece
	      , @with_override	tinyint		-- whether we need to set this
	      					-- for this set of disk pieces.
	      , @with_dur_and_dmllog tinyint
	      					-- whether we need to set this
	      					-- for the database.
	      , @units_ok	tinyint		-- does server support
	      					-- unit specifiers.

	select @newline		= char(10)
	     , @tabchar		= char(9)
	     , @comment		= "-- "
	     , @pages		= " pages"
	     , @objtype		= "DATABASE"
	     , @indent		= space(@@nestlevel * 2)
	     , @retval		= 0

	select @objtype_lower	= lower(@objtype)

	     -- SQL fragments that we will reuse.
	     , @create_sql	= "CREATE"
	     , @alterdb_sql	= "ALTER DATABASE"
	     , @override_sql	= "WITH OVERRIDE"
	     , @imdb_sql	= " INMEMORY"
	     , @local_systempdb_ph
				= " SYSTEM TEMPORARY "
	     , @local_usrtempdb_ph
				= " TEMPORARY "
	     , @global_usrtempdb_ph
				= " GLOBAL TEMPORARY "
	     , @archive_sql	= " TEMPLATE SQL FOR ARCHIVE "

	     -- Version parsing related variables.
	     , @ase_1192_str 	= "%Enterprise/11.9%"
	     , @ase_120x_str	= "%Enterprise/12.0%"
	     , @ase_150x_str	= "%Enterprise/15.0%"
	     , @ase_155x_str	= "%Enterprise/15.5%"

	     -- Build special-use comment for archive dbs.
	     --
	     , @archivedb_comm = @newline + 
+ "-- This is a template DDL for an archive database. Fill in the logical"
+ @newline
+ "-- device names based on the devices existing in your installation,"
+ @newline
+ "-- and uncomment the WITH OVERRIDE clause, as necessary."

	     , @ase_125x_or_gt	= 1	-- Assume it's 12.5.x or later till
	     				-- we find out otherwise.

	     , @ase_150x_or_gt	= 0	-- Assume it's *not* 15.0.x or later
	     				-- till we find out otherwise.
	     				
	     , @ase_155x_or_gt	= 0	-- Assume it's *not* 15.5.x or later
	     				-- till we find out otherwise.

	       -- Initialize 'prev' values that are used later for comparing
	       -- whether disk piece info changed across rows.
	       --
	     , @prev_dbname	= NULL
	     , @prev_segment	= NULL
	     , @prev_crdate	= NULL

	     -- Assume server does have this column. (We can't do matching
	     -- based on 'sysusages.crdate', till we are at 12.5x. or later.)
	     , @use_crdate	= 0
	     				

	     , @override	= 0		-- Assume no WITH OVERRIDE
	     , @usertempdb	= 0		-- Assume it's not a user tempdb
	     , @with_override	= 0
	     , @with_dur_and_dmllog = 0

	       --From 15.5 or later, the following variables are introduced
	       --Initialize the following variables
	       --
	     , @templatedbname = NULL
	     , @durability = NULL
	     , @dmllogging = NULL
	     , @durability_no_recovery_sql = "NO_RECOVERY"
	     , @durability_at_shutdown_sql = "AT_SHUTDOWN"
	     , @durability_full_sql = "FULL"
	     , @dmllogging_minimal_sql = "MINIMAL"
	     , @dmllogging_full_sql = "FULL"
	     
         
	     -- Initialize various system catalog status bits
	     , @stat3_archivedb	= 4194304
	     , @durability_no_recovery_status = 6
	     , @durability_at_shutdown_status = 5
	     , @durability_full_status = 1
	     , @dmllogging_minimal_status = 256
	     , @stat4_inmem_db = 4096		-- It is an 'inmemory' db
	     , @stat4_explicit_no_rec = 8192	-- Tempdb was created with
	     					-- explicit NO_RECOVERY clause.
	     , @inmem_db = 0
	     , @explicit_no_rec = 0		-- Assume all tempdbs were not
	     					-- created / altered with 
						-- explicit NO_RECOVERY option.


	select @stat3_tempdb = number 
	from master.dbo.spt_values
	where  type = "D3"
	  and  name = "TEMPDB STATUS MASK"
	     
	select @numpgsmb = (1048576. / v.low)
	from master.dbo.spt_values v
	where v.number = 1
	  and v.type = "E"

	if (@objtype IS NULL)
		select @objtype = "DATABASE"

	-- Validate that the db exists, first, if only one was requested.
	if (charindex("%", @dbname) = 0) and (db_id(@dbname) IS NULL)
	begin
		raiserror 18322, @dbname
		return 1
	end

	-- Identify the server version we are running on.
	--
	if (@@version like @ase_1192_str) or (@@version like @ase_120x_str)
	begin
		select @ase_125x_or_gt 	= 0
	end
	else if (@@version like @ase_150x_str)
	begin
		select @ase_150x_or_gt 	= 1
	end
	else if (@@version like @ase_155x_str)
	begin
		select @ase_155x_or_gt 	= 1
	end

	-- Support masquerading as an older server.
	--
	if (@trace in (1192, 120))
	begin
		select @ase_125x_or_gt	= 0
		     , @ase_150x_or_gt	= 1
	end

	-- Some features are only usable 12.5.x onwards:
	-- 	. unit-specifiers 
	--	. 'sysusages.crdate'
	--
	select @units_ok 	= @ase_125x_or_gt
	     , @use_crdate	= @ase_125x_or_gt

	-- ###################################################################
	-- Stash away the segment info into a #temp table for processing.
	--
	select 	  u.dbid
		, dbname = d.name

		-- Remember whether this usages entry is for an archivedb.
		, archivedb = 0
		, d.status3
		, u.lstart
		, u.segmap
		, segment = case 
				WHEN ((u.segmap & 4) = 0) then 'data only'
				WHEN (u.segmap = 4) then 'log only'
				ELSE 'data and log'
			    end
		, size = convert(int, u.size)
		-- , sizeMb = ltrim(rtrim(str(u.size/512.0))) + 'M'
		, sizeMb = ltrim(rtrim(str(u.size/@numpgsmb ))) + 'M'
		, vdevno = u.vdevno	-- use this directly in 15.0 onwards.
		, override = 0 		-- whether this is a shared device that
					-- needs WITH OVERRIDE clause to be
					-- generated.
		, devname = v.name
		, devstat = v.status
		, devstat2 = v.status2

		-- The sysusages entries fabricated from the dump for an
		-- archive db don't have the original 'crdate' (if exists)
		-- from the db dump. Fabricate current date, as a placeholder.
		--
		, crdate = getdate()	
	into #seginfo
	from 	  master.dbo.sysusages u
		, master.dbo.sysdevices v
		, master.dbo.sysdatabases d
	where 1 = 1
	  and d.name like @dbname		-- support for '%mydb%'
	  and d.dbid = u.dbid
	  and ((d.status3 & @stat3_archivedb) != @stat3_archivedb)
	  					-- skip archive dbs for now
	  					-- We'll get them a bit later.

	  and u.vdevno = v.vdevno		-- Use this for 15.0 onwards.

	  and (   ((v.status & 2) = 2) 		-- for physical devices
	       or ((v.status2 & 8) = 8))   	-- for cache devices

	-- ###################################################################
	-- Validate that the above SQL captured exactly one row for each
	-- sysusages entry for a db. If not, we will be generating wrong
	-- data, as there is some cross-product join happening.
	-- If the validation fails, error out. [ This came about as during
	-- testing some wrong WHERE clause was used in 15.0.x from a version
	-- of this sproc meant for 12.5.x. Add this validation to trap
	-- future errors.]
	--
	select @count_failed_dbids = (select count(1)
	from (	select dbid, numrows = count(*)
		from #seginfo group by dbid) 			V1
	   , (	select dbid, numrows = count(*)
	   	from master.dbo.sysusages group by dbid)	V2
	where V1.dbid = V2.dbid
	  and V1.numrows != V2.numrows
	  )

	if (@count_failed_dbids != 0)
	begin
		print "Found %1! dbids with wrong number of rows cached in '%2!' v/s the rows in '%3!'"
			, @count_failed_dbids
			, '#seginfo'
			, 'master.dbo.sysusages'

		-- Display the dbids for which we failed, if tracing is ON.
		-- RESOLVE: This code will probably not work in 12.0, or
		-- 11.9.x. Need to maintain a different version of this
		-- sproc for those codelines.
		--
		if (@trace = 1)
		begin
			select    V1.dbid
				, dbname = db_name(V1.dbid)
				, expected_in_sysusages = V2.numrows
				, actual_in_#seginfo = V1.numrows
				, status = case V1.numrows
						when V2.numrows
						then "ok"
						else "not ok"
					   end
			into #failed_dbids
			from (	select dbid, numrows = count(*)
				from #seginfo group by dbid) 		 V1
			   , (	select dbid, numrows = count(*)
				from master.dbo.sysusages group by dbid) V2
				where V1.dbid = V2.dbid

			  -- Skip this clause, so that we can see all rows.
			  -- and V1.numrows != V2.numrows

			-- See the 'not ok' rows at the top.
			exec sp_autoformat @fulltabname = #failed_dbids
					 , @orderby = "order by status asc"
		end

		return @count_failed_dbids
	end

	-- exec sp_autoformat #seginfo

	-- ###################################################################
	-- Of the dbs named by the user by the @dbname argument, if there is
	-- even one archive db, fork off control to a sub-proc that knows how
	-- to gather and process sysusages entries for archive dbs.
	--
	if exists (select 1 from master.dbo.sysdatabases d
		   where d.name like @dbname
		     and ((d.status3 & @stat3_archivedb) = @stat3_archivedb) )
	begin
		-- Reuse @devname to raise an error message.
		select @devname = """sp_ddlgen 'database', " + @dbname + '"'
		raiserror 19475, @devname
		return 1
	end


	-- ###################################################################
	-- Depending on the version of ASE, we might / not have 'crdate'
	-- column in sysusages. If we do, copy that into the #temp table,
	-- using execute immediate. Seems straightforward, but there is an
	-- issue here if archive dbs are involved. In that case, master..
	-- sysusages has only a 'stub' entry for the db, whereas the #temp
	-- table would have been populated with possibly multiple rows from
	-- <scratchdb>..sysaltusages. In that case, we can't do a row-to-row
	-- update from master..sysusages.crdate to #seginfo.crdate as there
	-- won't be matching rows in master..sysusages.
	--
	if (@ase_125x_or_gt = 1)
	begin
		if (@trace = 1)
		begin
			-- The UPDATE below sometimes fails. Run the query
			-- to see what the actual results are like, using
			-- data from the temp table.
			--
			select u.dbid, u.crdate
			from master.dbo.sysusages u,
			     #seginfo t
			where u.dbid = t.dbid
			  and u.lstart = t.lstart

			print "%1!---- End Trace update ----%2!"
				, @indent , @newline
			if (@retval != 0)
				return @retval
		end

		-- First only update for non-archive db rows.
		--
		update #seginfo
		set crdate = (select u.crdate
			      from master.dbo.sysusages u
			      where u.dbid = t.dbid
			        and u.lstart = t.lstart)
		from #seginfo t
		where t.archivedb = 0

		select @retval = @@error

		if (@retval != 0)
		begin
			if (@trace = 1)
				print "Error updating #seginfo.crdate using sysusages.crdate"

			return @retval
		end
	end

	-- ###################################################################
	-- Go back and check each disk piece to see 
	-- 1) if it has data fragment created on the device when the device was 
        --    a log-only device.
	--				OR
	-- 2) if it has log fragment created on the device when the device was
	--    a data-only device.
	-- If so, the user would have had to create this with WITH OVERRIDE
	-- clause. Note that here, we will re-gen the DDL accordingly.
        -- --
	-- [ NOTE: This will update 'override' to 1 for all usages entries
	-- for an archive db, as the 'vdevno' is the same for all entries.
	-- That is ok, here as then we comment out the WITH OVERRIDE clause for
	-- the DDL for an archive db.
	-- #####################################################################
        -- The condition in the following update query  to set @override bit 
	-- for the current disk piece to 1, is based on the fact that  
        -- 'with override'clause is needed only when
	-- 1) The current disk piece is of either 'data only' or 'log only' 
	--    types.
	--				AND
	-- 2) There exists at least one disk piece on the same device as that 
	--    of the current disk piece such that the other disk piece was 
	--    created before the current disk piece.
	--    (We need this condition to ensure that we do *not* generate the
	--    WITH OVERRIDE clause for the first piece of a db on any device.)
	--				AND
	-- 3) There exists no disk piece preceding the current one such that the
	--    preceding one is of either 'data and log' type or of the same type
	--    as that of the current diskpiece.
	--
	-- . If there exists a prior piece on the same device of type
	--   "data and log", it means all its subsequent pieces would not
	--    have needed the WITH OVERRIDE clause.
	--
	-- . If there exists a prior piecce on the same device of the
	--   same type as the current one, it means that prior piece
	--   would have been created with WITH OVERRIDE clause. Hence,
	--   all its subsequent pieces of the same segment type will
	--   not have needed the WITH OVERRIDE clause; hence, we can
	--   skip generating it here.

	update #seginfo
	set override = 1
	from #seginfo o				-- outer table
	where segment IN ("data only", "log only")
	and exists (select 1 from #seginfo i1   -- inner table
			where i1.lstart < o.lstart
			  and i1.dbid = o.dbid
			  and i1.vdevno = o.vdevno)
	and not exists (select 1 from #seginfo i2	-- inner table

		         -- ignore this very disk piece from the outer table,
			 -- and search for other disk pieces with a lower
			 -- lstart (i.e. the ones that were created -before-
			 -- the outer disk piece.
			 --
		    where i2.lstart < o.lstart
		      and i2.dbid = o.dbid
		      and i2.vdevno = o.vdevno
		      and (i2.segment = "data and log"
		      or i2.segment = o.segment) )
         
	declare diskcur cursor for
	select	  dbname, devname, segment, size, sizeMb, override, crdate
		, status3
		, devstat
		, devstat2
		, lstart
		, archivedb
	from #seginfo
	order by dbid, lstart asc
	for read only

	select @retval = @@error
	if (@retval != 0)
		return @retval

	open diskcur
	select @retval = @@error
	if (@retval != 0)
		return @retval

	while (1 = 1)
	begin	-- {
		fetch diskcur into @dbname
				  , @devname
				  , @segment
				  , @size_pages
				  , @size_mb
				  , @override
				  , @crdate
				  , @status3
				  , @devstat
				  , @devstat2
				  , @lstart
				  , @archivedb

		select @retval = @@error
		if (@@sqlstatus != 0) OR (@retval != 0)
			break

		-- We are beginning the processing for sysusages entries
		-- for a new database. Initialize the SQL fragments...
		--
		if (@prev_dbname != @dbname)
		begin	-- {

			-- If a database previous to the current one existed 
			-- (That is, in case of  multiple database input to 
			-- ddlgen using wild card)
			--
			if (@prev_dbname IS NOT NULL)
			begin
				-- Handle the case that the very last disk 
				-- piece of previous database might need this 
				-- clause.
				--
				exec sp_ddlgen_db_print_with_clause
						  @with_override output
						, @with_dur_and_dmllog output
						, @durability
						, @dmllogging
						, @archivedb 
			end

			else if (@prev_dbname IS NULL)
			begin
				print "USE master%1!go%2!", @newline, @newline
			end

			-- Reset for every db that we'll process in a loop.
			/*
			** If it is a temporary database other than 'tempdb'
			** add the keywords that reflect the type of the
			** database accordingly ([system | global] temporary).
			*/
			if ((@status3 & @stat3_tempdb) != 0)
			begin
				-- The database is a temporary database; start 
				-- with the default phrase (with the TEMPORARY 
				-- keyword)
				--
		 		select @tempdb_ph = @local_usrtempdb_ph

				if (@@clustermode = 'shared disk cluster')
                                begin
					-- In case of sdc, there are a few
					-- variations as shown in the switch
					-- case.
					--
					select @tempdb_ph = 
					case (@status3 & @stat3_tempdb)
						when (select number 
						      from master.dbo.spt_values
						      where name = 
							'local system temp db')
                                             	then @local_systempdb_ph
						when (select number
						      from master.dbo.spt_values
						      where name = 
							'global user temp db')
                                               	then @global_usrtempdb_ph
						else @local_usrtempdb_ph
					end
					
				end
			end

			else if ((@status3 & @stat3_archivedb) = @stat3_archivedb)
			begin
				select @tempdb_ph = @archive_sql
			end

			else
				select @tempdb_ph = ""

			/*
			** If it is a inmemory database,
			** add the keywords that reflect the type of the
			** database accordingly (inmemory).
			*/
			if (@ase_155x_or_gt = 1)
			begin
				select @with_dur_and_dmllog = 1
				
				-- Extract the durability from catalogs:
				-- First find the durability as we see it in
				-- the catalogs. Also note if it's a user
				-- created tempdb.
				--
				select @durability_status = durability 

				     -- Is it a user-created temp db?
				     , @usertempdb = case (status3
				     			     & @stat3_tempdb)
							when @stat3_tempdb
							then 1
							else 0
						     end

				     -- Is it a tempdb created with explicit
				     -- NO_RECOVERY durability?
				     --
				     , @explicit_no_rec
			     	       = case (status4 & @stat4_explicit_no_rec)
					    when @stat4_explicit_no_rec
					    then 1
					    else 0
					 end

				     -- Is it an in-memory db?
				     , @inmem_db
				       = case (status4 & @stat4_inmem_db)
					    when @stat4_inmem_db
					    then 1
					    else 0
					 end
				       	
				from master.dbo.sysdatabases 
				where name = @dbname

				select @durability = 
					case (@durability_status)
						when @durability_no_recovery_status
                                             	then @durability_no_recovery_sql
						when @durability_at_shutdown_status
                                               	then @durability_at_shutdown_sql
						else @durability_full_sql
					end
	

				-- Next, for the system tempdb, or for any
				-- user-created tempdb, check if the db was
				-- created / altered with the explicit
				-- NO_RECOVERY durability. If not, reset the
				-- durability to NULL. (Do not do this for 
				-- in-memory dbs which *need* to be always
				-- created with the NO_RECOVERY clause.)
				-- This will eventually suppress generating
				-- the WITH DURABILITY clause in the DDL.
				--
				if (   (   (@dbname = 'tempdb')
				        or (@usertempdb = 1) )
				    and (@explicit_no_rec = 0)
				    and (@inmem_db = 0)
				    )
				begin
					select @durability = NULL
				end
				  
				select @dmllogging_status = status4 
				from master.dbo.sysdatabases 
				where name = @dbname
				
				select @dmllogging = 
					case (@dmllogging_status
						& @dmllogging_minimal_status)
						when @dmllogging_minimal_status
                                             	then @dmllogging_minimal_sql
						else @dmllogging_full_sql
					end
			
				if(@devstat2 & 8 = 8)
				begin
					select @imdb_ph = @imdb_sql
					
					-- Don't forget to add:
					--	'USE dbname AS TEMPLATE'
					-- clause for the database if it is an
					-- IMDB db. Currently, we don't support
					-- template clause
					-- for inmemory temp DB
					-- 
					if ((@status3 & @stat3_tempdb) = 0)
					begin
						select @templatedbname = def_remote_loc
						from master.dbo.sysdatabases 
						where name = @dbname
					end
				end

				if(@devstat2 & 8 != 8)
					select @imdb_ph = NULL 

				if((@devstat & 2 = 2) and 
					(@durability_status & @durability_no_recovery_status = 
					@durability_no_recovery_status))
				begin
					select @templatedbname = def_remote_loc
					from master.dbo.sysdatabases
					where name = @dbname			
				end
			end


			-- Generate the DROP syntax first.
			--
			print "%1!PRINT ""<<<< %2!%3!%4!%5! %6!>>>>""%7!go%8!%9!"
				, @newline
				, @create_sql
				, @imdb_ph
				, @tempdb_ph
				, @objtype
				, @dbname
				, @newline, @newline, @newline

			print "IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases"
			print "	   WHERE name = '%1!')", @dbname
			print "	DROP %1! %2!", @objtype, @dbname
			print "go%1!%2!", @newline, @newline

			print "IF (@@error != 0)%1!BEGIN", @newline
			print "	PRINT ""Error dropping %1! '%2!'"""
				, @objtype_lower, @dbname
			print "	SELECT syb_quit()%1!END%2!go%3!%4!"
				, @newline, @newline, @newline, @newline

			-- Reset loop variables that are only to be used for
			-- rows for one db.
			--
			select @prev_segment 	= NULL
			     , @prev_crdate 	= NULL

			-- We don't want to generate CREATE ARCHIVE DATABASE,
			-- so reset the phrase, in a way to suppress that.
			--
			if (@tempdb_ph = @archive_sql)
				select @tempdb_ph = " "

			-- Display special-case comments for archive db's DDL.
			if (@archivedb = 1)
			begin
				print @archivedb_comm
			end

			print "%1!%2!%3!%4! %5!"
				, @create_sql, @imdb_ph, @tempdb_ph
				, @objtype, @dbname

	


			-- Don't forget to add 'USE dbname AS TEMPLATE' clause 
			-- for the database if it is a inmemory db.
			--
			if (@templatedbname IS NOT NULL)
			begin
				print "%1!    USE %2! AS TEMPLATE"
					, @tabchar
					, @templatedbname   
			end
			select @templatedbname = NULL
			
		end	-- }
		
		
        
		if (@prev_segment IS NULL)
		begin
			select @prefix = @tabchar + "    ON "
		end
		else if (@use_crdate = 1) and (@prev_crdate != @crdate)
		begin	-- {
			-- State change in segment defn. Move to ALTER DB SQL
			exec sp_ddlgen_db_print_alterdb
					  @dbname
					, @archivedb
					, @alterdb_sql
					, @segment
					, @durability
					, @dmllogging
					, @trace
					, 'dates are different'
					, @with_override output
					, @with_dur_and_dmllog output
					, @prefix 	 output
		end	-- }

		else if (@prev_segment = @segment)
		begin
			select @prefix = @tabchar + "     , "
		end

		else if (    (@prev_segment != "data and log")
			and (@segment = "log only"))
		begin
			select @prefix = @tabchar + "LOG ON "
		end
		else
		begin	-- {
			-- State change in segment defn. Move to ALTER DB SQL
			exec sp_ddlgen_db_print_alterdb
					  @dbname
					, @archivedb
					, @alterdb_sql
					, @segment
					, @durability
					, @dmllogging
					, @trace
					, 'segments are different'
					, @with_override output
					, @with_dur_and_dmllog output
					, @prefix 	 output
		end	-- }

		-- Depending on whether the server supports unit-specifiers,
		-- pick the way 'size' is printed. If the server supports
		-- unit-specifiers, report using units, and report the # of
		-- pages in comments. Otherwise, do the opposite.
		--
		if (@units_ok = 1)
		begin
			select @size_str = "'" + @size_mb + "'"
			     , @size_comments = @comment
			     		      + convert(varchar, @size_pages)
					      + @pages
		end
		else
		begin
			select @size_str = convert(varchar, @size_pages)
			     , @size_comments = @comment + @size_mb
		end

		if (@trace = 1)
		begin
			select @size_comments = @size_comments
					      +  " ["
					      + @segment

					      + ",lstart="
					      + convert(varchar, @lstart)

					      + ",override="
					      + convert(varchar, @override)

					      + ","
					      + convert(varchar, @crdate)
					      +  "]"
		end

		-- In this cursor loop we could be generating the syntax
		-- for more than one disk piece, followed by more than
		-- one disk piece for the LOG ON phrase. Here, we remember
		-- if any one of these would have needed a WITH OVERRIDE
		-- clause, which should only be generated at the very end
		-- of the block of SQL for all the disk pieces being
		-- printed under one ALTER DATABASE statement. Then, we
		-- will pass this @with_override to the print routine which
		-- will terminate the current ALTER DATABASE SQL chunk with
		-- any required WITH OVERRIDE clause, and start a new block
		-- of SQL.

		if (@override = 1)
			select @with_override = 1
			
		print "%1!%2! = %3! %4!"
			, @prefix, @devname, @size_str
			, @size_comments
		
		-- Store this disk piece's values, for comparison with those
		-- of the next piece.
		select @prev_segment = @segment
			, @prev_crdate	= @crdate
			, @prev_dbname	= @dbname

	end	-- }
	close diskcur
	deallocate cursor diskcur

	if (@retval != 0)
		return @retval

	-- Handle the case that the very last disk piece might need this clause.
	--
	exec sp_ddlgen_db_print_with_clause @with_override output
					  , @with_dur_and_dmllog output
					  , @durability
					  , @dmllogging
					  , @archivedb

	return @retval
end -- }
go


go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen')
begin
	drop procedure sp_ddlgen
end
go
print "Installing sp_ddlgen"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:10 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen [Total 1]
**
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

exec sp_dbxt_recreate_proc sp_ddlgen
go

/*
** sp_ddlgen
**
**
**	Minimalist shell sproc to drive DDL generation for base object types.
**	This is currently only supporting DDL generation for databases.
**
** Parameter:
**	@objtype	- Type of object ('database', 'table' etc.)
**	@objname	- Name of the object
**	@trace		- Trace leve; for internal use only.
{
*/
create procedure sp_ddlgen(
			  @objtype	varchar(30)	= NULL
			, @objname	varchar(255)	= NULL
			, @trace	int		= NULL
) as
begin
	declare @retval		int
	      , @baseprocname	varchar(60)
	      , @procname	varchar(60)

	      , @obj_db		varchar(8)
	      , @valid_objtypes	varchar(255)

	select @baseprocname = 'sybsystemprocs.dbo.sp_ddlgen_'

	     -- Start listing the names of entities that we support.
	     , @obj_db	= 'database'
	     , @retval	= 0

	select @valid_objtypes = "'" + @obj_db + "'"

	if (@objtype IS NULL) or (@objtype = 'help')
	begin
		select @procname = @baseprocname + 'help'
		exec @retval = @procname @objname, @valid_objtypes
		return @retval
	end

	-- Validate object type, to avoid junk error-checking downstream.
	if (@objtype NOT IN (  @obj_db
			    ) )

	begin
		raiserror 19194, "@objtype", @valid_objtypes
		return 1
	end

	-- Handle NULL objname input:
	--  . For databases, generate DDL for the current db of user.
	--
	if ((@objtype = @obj_db) and (@objname IS NULL))
		select @objname = db_name()

	-- Name the permission checking sub-proc for generating the DDL.
	select @procname = @baseprocname + 'permissions'
	exec @retval = @procname @objtype, @objname
	if (@retval = 0)	-- Check for failure in permissions checks
		return 1

	-- Name the sub-proc generating the DDL.
	select @procname = @baseprocname + @objtype

	-- Fork off control to the sub-proc, if we got the right objtype.
	if (@objtype IN (  'database'
			  --, add a new entry here in the future.
	   		) )
	begin
		exec @retval = @procname @objname, @trace
	end


	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_ddlgen', 'anymode'
go
grant execute on sp_ddlgen to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_addlogin_rep')
begin
	drop procedure sp_addlogin_rep
end
go
print "Installing sp_addlogin_rep"
go


/*
** WARNING: This system procedure is an un-documented system procedure
** reserved for the exclusive use of Replication Server.  Do *NOT* use this
** system procedure to add a login.  Use the system procedure
** 'sp_addlogin()' instead.
**
** This system procedure is a wrapper for the command 'create login' and
** must have the same call signature as the system procedure
** 'sp_addlogin()'.
*/

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:14 2006 
*/
/*
** raiserror Messages for addlogin_rep [Total 2]
**
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
*/
/*
** sp_getmessage Messages for addlogin_rep [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_addlogin_rep
@loginame varchar(255),			/* login name of the new user */

@passwd varbinary(256) = NULL,		/* password of the new user */

@defdb varchar(255) = "master",		/* default db for the new user */
@deflanguage varchar(255) = NULL,	/* default language for the new user */
@fullname varchar(255) = NULL,		/* account owner's full name */
@passwdexp int = NULL,			/* value of password expiration */
@minpwdlen int = NULL,			/* value of minimum password 
					** length 
					*/
@maxfailedlogins int = NULL,		/* value of maximum failed 
					** logins
					*/
@auth_mech varchar(30) = "ANY"		/* Authentication mechanism */
as

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_addlogin_rep"
	return (1)
end
set chained off
set transaction isolation level 1

create login
	@loginame
with

	encrypted passwd @passwd,

	default database @defdb,
	default language @deflanguage,
	fullname @fullname,
	passwd expiration @passwdexp,
	min passwd length @minpwdlen,
	max failed_logins @maxfailedlogins,
	authenticate with @auth_mech

/*
** If the 'master' database is marked for replication, the T-SQL built-in
** 'logexec()' will log for replication the execution instance of this
** system procedure.  Otherwise, the T-SQL built-in 'logexec()' is a no-op.
*/
if (logexec(1) != 1)
begin
	raiserror 17756, "sp_addlogin_rep", "master"
	return (1)
end

return (0)
go
exec sp_procxmode 'sp_addlogin_rep', 'anymode'
go
grant execute on sp_addlogin_rep to public
go
exec sp_procxmode 'sp_addlogin_rep', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_password_rep')
begin
	drop procedure sp_password_rep
end
go
print "Installing sp_password_rep"
go


/*
** WARNING: This system procedure is an un-documented system procedure
** reserved for the exclusive use of Replication Server.  Do *NOT* use this
** system procedure to change a password.  Use the system procedure
** 'sp_password()' instead.
**
** This system procedure is a wrapper for the built-in 'set_enc_password()'
** and must have the same call signature as the system procedure
** 'sp_password()'.
*/

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:19 2006 
*/
/*
** raiserror Messages for password_rep [Total 2]
**
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
*/
/*
** sp_getmessage Messages for password_rep [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_password_rep
@caller_password varchar(255) = NULL,	/* the current password of caller */
@new_password    varbinary(256) = NULL,	/* the new password of the target acct*/
					/* a length of 256 is required to test if
					** user entered a passwd > 255 chars.
					*/
@loginame        varchar(255) = NULL,	/* user to change password on */
@immediate	 int = 0		/* if not 0, change the password in
					** all running processes for loginame.
					*/
as

declare @retcode int

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_password_rep"
	return (1)
end
set chained off
set transaction isolation level 1

select @retcode = set_enc_password(@new_password, @loginame)
if (@retcode = 0)
        return (1)

/*
** If the 'master' database is marked for replication, the T-SQL built-in
** 'logexec()' will log for replication the execution instance of this
** system procedure.  Otherwise, the T-SQL built-in 'logexec()' is a no-op.
*/
if (logexec(1) != 1)
begin
	raiserror 17756, "sp_password_rep", "master"
	return (1)
end

return (0)
go
exec sp_procxmode 'sp_password_rep', 'anymode'
go
grant execute on sp_password_rep to public
go
exec sp_procxmode 'sp_password_rep', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_set_password_rep')
begin
	drop procedure sp_set_password_rep
end
go
print "Installing sp_set_password_rep"
go


/*
** WARNING: This system procedure is an un-reserved system procedure
** reserved for the exclusive use of Replication Server.  Do *NOT* use this
** system procedure to change a password.  Use the system procedure
** 'sp_password()' instead.
**
** This system procedure is a wrapper for the built-in 'set_enc_password()'
** and must have the same call signature as the system procedure
** 'sp_set_password()'.
*/

/*
** Generated by spgenmsgs.pl on Thu Feb  2 00:39:20 2006 
*/
/*
** raiserror Messages for set_password_rep [Total 2]
**
** 17260, "Can't run %1! from within a transaction."
** 17756, "The execution of the stored procedure '%1!' in database '%2!' was aborted because there was an error in writing the replication log record."
*/
/*
** sp_getmessage Messages for set_password_rep [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

create procedure sp_set_password_rep
@caller_password varchar(255) = NULL,	/* the current password of caller */
@new_password    varbinary(256) = NULL,	/* the new password of the target acct*/
					/* a length of 256 is required to test if
					** user entered a passwd > 255 chars.
					*/
@loginame        varchar(255) = NULL,	/* user to change password on */
@immediate	 int = 0		/* if not 0, change the password in
					** all running processes for loginame.
					*/
as

declare @retcode int

/*
** Do not allow this system procedure to be run from within a transaction
** to avoid creating a multi-database transaction where the 'master'
** database is not the co-ordinating database.
*/
if @@trancount > 0
begin
	raiserror 17260, "sp_set_password_rep"
	return (1)
end
set chained off
set transaction isolation level 1

select @retcode = set_enc_password(@new_password, @loginame)
if (@retcode = 0)
        return (1)

/*
** If the 'master' database is marked for replication, the T-SQL built-in
** 'logexec()' will log for replication the execution instance of this
** system procedure.  Otherwise, the T-SQL built-in 'logexec()' is a no-op.
*/
if (logexec(1) != 1)
begin
	raiserror 17756, "sp_set_password_rep", "master"
	return (1)
end

return (0)
go
exec sp_procxmode 'sp_set_password_rep', 'anymode'
go
grant execute on sp_set_password_rep to public
go
exec sp_procxmode 'sp_set_password_rep', 'rep_master'
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
declare @retval int
exec @retval = sp_version 'montables',NULL,'15.5/17340/P/x86_64/Enterprise Linux/ase155/2391/64-bit/OPT/Mon Nov 09 13:55:05 2009', 'start'
if (@retval != 0) select syb_quit()
go

use master
go

/*
** monTables definition
*/
if (exists (select * from sysobjects 
	where name = 'monTables' 
	  and type = 'U')) 
	drop table monTables
go
print "Creating monTables"
go
create existing table monTables ( 
	TableID                         int,
	Columns                         tinyint,
	Parameters                      tinyint,
	Indicators                      int,
	Size                            int,
	TableName                       varchar(30) NULL,
	Description                     varchar(368) NULL,
) 
materialized 
at "$monTables"
go
grant select on monTables to mon_role
go

/*
** monTableParameters definition
*/
if (exists (select * from sysobjects 
	where name = 'monTableParameters' 
	  and type = 'U')) 
	drop table monTableParameters
go
print "Creating monTableParameters"
go
create existing table monTableParameters ( 
	TableID                         int,
	ParameterID                     int,
	TypeID                          int,
	Precision                       tinyint,
	Scale                           tinyint,
	Length                          smallint,
	TableName                       varchar(30) NULL,
	ParameterName                   varchar(30) NULL,
	TypeName                        varchar(20) NULL,
	Description                     varchar(255) NULL,
) 
materialized 
at "$monTableParameters"
go
grant select on monTableParameters to mon_role
go

/*
** monTableColumns definition
*/
if (exists (select * from sysobjects 
	where name = 'monTableColumns' 
	  and type = 'U')) 
	drop table monTableColumns
go
print "Creating monTableColumns"
go
create existing table monTableColumns ( 
	TableID                         int,
	ColumnID                        int,
	TypeID                          int,
	Precision                       tinyint,
	Scale                           tinyint,
	Length                          smallint,
	Indicators                      int,
	TableName                       varchar(30) NULL,
	ColumnName                      varchar(30) NULL,
	TypeName                        varchar(20) NULL,
	Description                     varchar(255) NULL,
) 
materialized 
at "$monTableColumns"
go
grant select on monTableColumns to mon_role
go

/*
** monState definition
*/
if (exists (select * from sysobjects 
	where name = 'monState' 
	  and type = 'U')) 
	drop table monState
go
print "Creating monState"
go
create existing table monState ( 
	InstanceID                      tinyint,
	LockWaitThreshold               int,
	LockWaits                       int,
	DaysRunning                     int,
	CheckPoints                     int,
	NumDeadlocks                    int,
	DiagnosticDumps                 int,
	Connections                     int,
	MaxRecovery                     int,
	Transactions                    int,
	StartDate                       datetime NULL,
	CountersCleared                 datetime NULL,
) 
materialized 
at "$monState"
go
grant select on monState to mon_role
go

/*
** monEngine definition
*/
if (exists (select * from sysobjects 
	where name = 'monEngine' 
	  and type = 'U')) 
	drop table monEngine
go
print "Creating monEngine"
go
create existing table monEngine ( 
	EngineNumber                    smallint,
	InstanceID                      tinyint,
	CurrentKPID                     int,
	PreviousKPID                    int,
	CPUTime                         int,
	SystemCPUTime                   int,
	UserCPUTime                     int,
	IOCPUTime                       int,
	IdleCPUTime                     int,
	Yields                          int,
	Connections                     int,
	DiskIOChecks                    int,
	DiskIOPolled                    int,
	DiskIOCompleted                 int,
	MaxOutstandingIOs               int,
	ProcessesAffinitied             int,
	ContextSwitches                 int,
	HkgcMaxQSize                    int,
	HkgcPendingItems                int,
	HkgcHWMItems                    int,
	HkgcOverflows                   int,
	Status                          varchar(20) NULL,
	StartTime                       datetime NULL,
	StopTime                        datetime NULL,
	AffinitiedToCPU                 int NULL,
	OSPID                           int NULL,
) 
materialized 
at "$monEngine"
go
grant select on monEngine to mon_role
go

/*
** monDataCache definition
*/
if (exists (select * from sysobjects 
	where name = 'monDataCache' 
	  and type = 'U')) 
	drop table monDataCache
go
print "Creating monDataCache"
go
create existing table monDataCache ( 
	CacheID                         int,
	InstanceID                      tinyint,
	RelaxedReplacement              int,
	BufferPools                     int,
	CacheSearches                   int,
	PhysicalReads                   int,
	LogicalReads                    int,
	PhysicalWrites                  int,
	Stalls                          int,
	CachePartitions                 smallint,
	CacheName                       varchar(30) NULL,
) 
materialized 
at "$monDataCache"
go
grant select on monDataCache to mon_role
go

/*
** monProcedureCache definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcedureCache' 
	  and type = 'U')) 
	drop table monProcedureCache
go
print "Creating monProcedureCache"
go
create existing table monProcedureCache ( 
	Requests                        int,
	Loads                           int,
	Writes                          int,
	Stalls                          int,
	InstanceID                      tinyint,
) 
materialized 
at "$monProcedureCache"
go
grant select on monProcedureCache to mon_role
go

/*
** monProcedureCacheMemoryUsage definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcedureCacheMemoryUsage' 
	  and type = 'U')) 
	drop table monProcedureCacheMemoryUsage
go
print "Creating monProcedureCacheMemoryUsage"
go
create existing table monProcedureCacheMemoryUsage ( 
	InstanceID                      tinyint,
	AllocatorID                     int,
	ModuleID                        int,
	Active                          int,
	HWM                             int,
	ChunkHWM                        int,
	NumReuseCaused                  int,
	AllocatorName                   varchar(30) NULL,
) 
materialized 
at "$monProcedureCacheMemoryUsage"
go
grant select on monProcedureCacheMemoryUsage to mon_role
go

/*
** monProcedureCacheModuleUsage definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcedureCacheModuleUsage' 
	  and type = 'U')) 
	drop table monProcedureCacheModuleUsage
go
print "Creating monProcedureCacheModuleUsage"
go
create existing table monProcedureCacheModuleUsage ( 
	InstanceID                      tinyint,
	ModuleID                        int,
	Active                          int,
	HWM                             int,
	NumPagesReused                  int,
	ModuleName                      varchar(30) NULL,
) 
materialized 
at "$monProcedureCacheModuleUsage"
go
grant select on monProcedureCacheModuleUsage to mon_role
go

/*
** monOpenDatabases definition
*/
if (exists (select * from sysobjects 
	where name = 'monOpenDatabases' 
	  and type = 'U')) 
	drop table monOpenDatabases
go
print "Creating monOpenDatabases"
go
create existing table monOpenDatabases ( 
	DBID                            int,
	InstanceID                      tinyint,
	BackupInProgress                int,
	LastBackupFailed                int,
	TransactionLogFull              int,
	SuspendedProcesses              int,
	AppendLogRequests               int,
	AppendLogWaits                  int,
	DBName                          varchar(30) NULL,
	BackupStartTime                 datetime NULL,
	LastCheckpointTime              datetime NULL,
	LastTranLogDumpTime             datetime NULL,
	QuiesceTag                      varchar(30) NULL,
) 
materialized 
at "$monOpenDatabases"
go
grant select on monOpenDatabases to mon_role
go

/*
** monSysWorkerThread definition
*/
if (exists (select * from sysobjects 
	where name = 'monSysWorkerThread' 
	  and type = 'U')) 
	drop table monSysWorkerThread
go
print "Creating monSysWorkerThread"
go
create existing table monSysWorkerThread ( 
	InstanceID                      tinyint,
	ThreadsActive                   int,
	TotalWorkerThreads              int,
	HighWater                       int,
	ParallelQueries                 int,
	PlansAltered                    int,
	WorkerMemory                    int,
	TotalWorkerMemory               int,
	WorkerMemoryHWM                 int,
	MaxParallelDegree               int,
	MaxScanParallelDegree           int,
) 
materialized 
at "$monSysWorkerThread"
go
grant select on monSysWorkerThread to mon_role
go

/*
** monNetworkIO definition
*/
if (exists (select * from sysobjects 
	where name = 'monNetworkIO' 
	  and type = 'U')) 
	drop table monNetworkIO
go
print "Creating monNetworkIO"
go
create existing table monNetworkIO ( 
	InstanceID                      tinyint,
	PacketsSent                     int,
	PacketsReceived                 int,
	BytesSent                       int,
	BytesReceived                   int,
) 
materialized 
at "$monNetworkIO"
go
grant select on monNetworkIO to mon_role
go

/*
** monErrorLog definition
*/
if (exists (select * from sysobjects 
	where name = 'monErrorLog' 
	  and type = 'U')) 
	drop table monErrorLog
go
print "Creating monErrorLog"
go
create existing table monErrorLog ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	FamilyID                        int,
	EngineNumber                    smallint,
	ErrorNumber                     int,
	Severity                        int,
	State                           int,
	Time                            datetime,
	ErrorMessage                    varchar(512) NULL,
) 
materialized 
at "$monErrorLog"
go
grant select on monErrorLog to mon_role
go

/*
** monLocks definition
*/
if (exists (select * from sysobjects 
	where name = 'monLocks' 
	  and type = 'U')) 
	drop table monLocks
go
print "Creating monLocks"
go
create existing table monLocks ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	DBID                            int,
	ParentSPID                      int,
	LockID                          int,
	Context                         int,
	DBName                          varchar(30) NULL,
	ObjectID                        int NULL,
	LockState                       varchar(20) NULL,
	LockType                        varchar(20) NULL,
	LockLevel                       varchar(30) NULL,
	WaitTime                        int NULL,
	PageNumber                      int NULL,
	RowNumber                       int NULL,
	BlockedState                    varchar(64) NULL,
	BlockedBy                       int NULL,
	SourceCodeID                    varchar(30) NULL,
) 
materialized 
at "$monLocks"
go
grant select on monLocks to mon_role
go

/*
** monDeadLock definition
*/
if (exists (select * from sysobjects 
	where name = 'monDeadLock' 
	  and type = 'U')) 
	drop table monDeadLock
go
print "Creating monDeadLock"
go
create existing table monDeadLock ( 
	DeadlockID                      int,
	VictimKPID                      int,
	InstanceID                      tinyint,
	ResolveTime                     datetime,
	ObjectDBID                      int,
	PageNumber                      int,
	RowNumber                       int,
	HeldFamilyID                    int,
	HeldSPID                        int,
	HeldKPID                        int,
	HeldProcDBID                    int,
	HeldProcedureID                 int,
	HeldBatchID                     int,
	HeldContextID                   int,
	HeldLineNumber                  int,
	WaitFamilyID                    int,
	WaitSPID                        int,
	WaitKPID                        int,
	WaitTime                        int,
	ObjectName                      varchar(30) NULL,
	HeldUserName                    varchar(30) NULL,
	HeldApplName                    varchar(30) NULL,
	HeldTranName                    varchar(255) NULL,
	HeldLockType                    varchar(20) NULL,
	HeldCommand                     varchar(30) NULL,
	WaitUserName                    varchar(30) NULL,
	WaitLockType                    varchar(20) NULL,
	HeldSourceCodeID                varchar(30) NULL,
	WaitSourceCodeID                varchar(30) NULL,
) 
materialized 
at "$monDeadLock"
go
grant select on monDeadLock to mon_role
go

/*
** monWaitClassInfo definition
*/
if (exists (select * from sysobjects 
	where name = 'monWaitClassInfo' 
	  and type = 'U')) 
	drop table monWaitClassInfo
go
print "Creating monWaitClassInfo"
go
create existing table monWaitClassInfo ( 
	WaitClassID                     smallint,
	Description                     varchar(55) NULL,
) 
materialized 
at "$monWaitClassInfo"
go
grant select on monWaitClassInfo to mon_role
go

/*
** monWaitEventInfo definition
*/
if (exists (select * from sysobjects 
	where name = 'monWaitEventInfo' 
	  and type = 'U')) 
	drop table monWaitEventInfo
go
print "Creating monWaitEventInfo"
go
create existing table monWaitEventInfo ( 
	WaitEventID                     smallint,
	WaitClassID                     smallint,
	Description                     varchar(55) NULL,
) 
materialized 
at "$monWaitEventInfo"
go
grant select on monWaitEventInfo to mon_role
go

/*
** monCachedObject definition
*/
if (exists (select * from sysobjects 
	where name = 'monCachedObject' 
	  and type = 'U')) 
	drop table monCachedObject
go
print "Creating monCachedObject"
go
create existing table monCachedObject ( 
	CacheID                         int,
	InstanceID                      tinyint,
	DBID                            int,
	IndexID                         int,
	PartitionID                     int,
	CachedKB                        int,
	CacheName                       varchar(30) NULL,
	ObjectID                        int NULL,
	DBName                          varchar(30) NULL,
	OwnerUserID                     int NULL,
	OwnerName                       varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	PartitionName                   varchar(30) NULL,
	ObjectType                      varchar(30) NULL,
	TotalSizeKB                     int NULL,
	ProcessesAccessing              int NULL,
) 
materialized 
at "$monCachedObject"
go
grant select on monCachedObject to mon_role
go

/*
** monCachePool definition
*/
if (exists (select * from sysobjects 
	where name = 'monCachePool' 
	  and type = 'U')) 
	drop table monCachePool
go
print "Creating monCachePool"
go
create existing table monCachePool ( 
	CacheID                         int,
	InstanceID                      tinyint,
	IOBufferSize                    int,
	AllocatedKB                     int,
	PhysicalReads                   int,
	Stalls                          int,
	PagesTouched                    int,
	PagesRead                       int,
	BuffersToMRU                    int,
	BuffersToLRU                    int,
	CacheName                       varchar(30) NULL,
) 
materialized 
at "$monCachePool"
go
grant select on monCachePool to mon_role
go

/*
** monDBRecovery definition
*/
if (exists (select * from sysobjects 
	where name = 'monDBRecovery' 
	  and type = 'U')) 
	drop table monDBRecovery
go
print "Creating monDBRecovery"
go
create existing table monDBRecovery ( 
	DBID                            int,
	InstanceID                      tinyint,
	MaxOpenXacts                    int,
	MaxPFTSEntries                  int,
	Buckets                         int,
	LogBTotPages                    int,
	LogBTotAPFWaited                int,
	LogBTotIO                       int,
	AnlTotRec                       int,
	AnlPhase1Recs                   int,
	AnlPhase1RedoRecs               int,
	AnlPhase2Recs                   int,
	AnlPhase2RedoRecs               int,
	AnlTotPages                     int,
	AnlTotAPFWaited                 int,
	AnlTotIO                        int,
	RedoOps                         int,
	RedoOpsNotRedonePFTS            int,
	RedoOpsRedonePFTS               int,
	RedoOpsRedoneTS                 int,
	RedoOpsNotRedoneTS              int,
	RedoLogTotPages                 int,
	RedoLogTotAPFWaited             int,
	RedoLogTotIO                    int,
	RedoRecTotPages                 int,
	RedoRecTotAPFWaited             int,
	RedoRecTotIO                    int,
	UndoRecsUndone                  int,
	UndoLogTotPages                 int,
	UndoLogTotAPFWaited             int,
	UndoLogTotIO                    int,
	UndoRecTotPages                 int,
	UndoRecTotAPFWaited             int,
	UndoRecTotIO                    int,
	DBName                          varchar(30) NULL,
	FailedInstances                 varchar(96) NULL,
	Command                         varchar(30) NULL,
	RecType                         varchar(30) NULL,
	LogBStartTime                   datetime NULL,
	LogBEndTime                     datetime NULL,
	AnlStartTime                    datetime NULL,
	AnlEndTime                      datetime NULL,
	RedoStartTime                   datetime NULL,
	RedoEndTime                     datetime NULL,
	UndoStartTime                   datetime NULL,
	UndoEndTime                     datetime NULL,
) 
materialized 
at "$monDBRecovery"
go
grant select on monDBRecovery to mon_role
go

/*
** monDBRecoveryLRTypes definition
*/
if (exists (select * from sysobjects 
	where name = 'monDBRecoveryLRTypes' 
	  and type = 'U')) 
	drop table monDBRecoveryLRTypes
go
print "Creating monDBRecoveryLRTypes"
go
create existing table monDBRecoveryLRTypes ( 
	DBID                            int,
	InstanceID                      tinyint,
	NumRecs                         int,
	LogrecType                      varchar(30) NULL,
) 
materialized 
at "$monDBRecoveryLRTypes"
go
grant select on monDBRecoveryLRTypes to mon_role
go

/*
** monFailoverRecovery definition
*/
if (exists (select * from sysobjects 
	where name = 'monFailoverRecovery' 
	  and type = 'U')) 
	drop table monFailoverRecovery
go
print "Creating monFailoverRecovery"
go
create existing table monFailoverRecovery ( 
	InstanceID                      tinyint,
	ModuleName                      varchar(30) NULL,
	FailedInstances                 varchar(96) NULL,
	StartTime                       datetime NULL,
	EndTime                         datetime NULL,
) 
materialized 
at "$monFailoverRecovery"
go
grant select on monFailoverRecovery to mon_role
go

/*
** monOpenObjectActivity definition
*/
if (exists (select * from sysobjects 
	where name = 'monOpenObjectActivity' 
	  and type = 'U')) 
	drop table monOpenObjectActivity
go
print "Creating monOpenObjectActivity"
go
create existing table monOpenObjectActivity ( 
	DBID                            int,
	ObjectID                        int,
	IndexID                         int,
	InstanceID                      tinyint,
	DBName                          varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	LogicalReads                    int NULL,
	PhysicalReads                   int NULL,
	APFReads                        int NULL,
	PagesRead                       int NULL,
	PhysicalWrites                  int NULL,
	PagesWritten                    int NULL,
	RowsInserted                    int NULL,
	RowsDeleted                     int NULL,
	RowsUpdated                     int NULL,
	Operations                      int NULL,
	LockRequests                    int NULL,
	LockWaits                       int NULL,
	OptSelectCount                  int NULL,
	LastOptSelectDate               datetime NULL,
	UsedCount                       int NULL,
	LastUsedDate                    datetime NULL,
	HkgcRequests                    int NULL,
	HkgcPending                     int NULL,
	HkgcOverflows                   int NULL,
	PhysicalLocks                   int NULL,
	PhysicalLocksRetained           int NULL,
	PhysicalLocksRetainWaited       int NULL,
	PhysicalLocksDeadlocks          int NULL,
	PhysicalLocksWaited             int NULL,
	PhysicalLocksPageTransfer       int NULL,
	TransferReqWaited               int NULL,
	AvgPhysicalLockWaitTime         real NULL,
	AvgTransferReqWaitTime          real NULL,
	TotalServiceRequests            int NULL,
	PhysicalLocksDowngraded         int NULL,
	PagesTransferred                int NULL,
	ClusterPageWrites               int NULL,
	AvgServiceTime                  real NULL,
	AvgTimeWaitedOnLocalUsers       real NULL,
	AvgTransferSendWaitTime         real NULL,
	AvgIOServiceTime                real NULL,
	AvgDowngradeServiceTime         real NULL,
) 
materialized 
at "$monOpenObjectActivity"
go
grant select on monOpenObjectActivity to mon_role
go

/*
** monIOQueue definition
*/
if (exists (select * from sysobjects 
	where name = 'monIOQueue' 
	  and type = 'U')) 
	drop table monIOQueue
go
print "Creating monIOQueue"
go
create existing table monIOQueue ( 
	InstanceID                      tinyint,
	IOs                             int,
	IOTime                          int,
	LogicalName                     varchar(30) NULL,
	IOType                          varchar(12) NULL,
) 
materialized 
at "$monIOQueue"
go
grant select on monIOQueue to mon_role
go

/*
** monDeviceIO definition
*/
if (exists (select * from sysobjects 
	where name = 'monDeviceIO' 
	  and type = 'U')) 
	drop table monDeviceIO
go
print "Creating monDeviceIO"
go
create existing table monDeviceIO ( 
	InstanceID                      tinyint,
	Reads                           int,
	APFReads                        int,
	Writes                          int,
	DevSemaphoreRequests            int,
	DevSemaphoreWaits               int,
	IOTime                          int,
	LogicalName                     varchar(30) NULL,
	PhysicalName                    varchar(128) NULL,
) 
materialized 
at "$monDeviceIO"
go
grant select on monDeviceIO to mon_role
go

/*
** monSysWaits definition
*/
if (exists (select * from sysobjects 
	where name = 'monSysWaits' 
	  and type = 'U')) 
	drop table monSysWaits
go
print "Creating monSysWaits"
go
create existing table monSysWaits ( 
	InstanceID                      tinyint,
	WaitEventID                     smallint,
	WaitTime                        int,
	Waits                           int,
) 
materialized 
at "$monSysWaits"
go
grant select on monSysWaits to mon_role
go

/*
** monProcess definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcess' 
	  and type = 'U')) 
	drop table monProcess
go
print "Creating monProcess"
go
create existing table monProcess ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	ServerUserID                    int,
	BatchID                         int,
	ContextID                       int,
	LineNumber                      int,
	SecondsConnected                int,
	DBID                            int,
	EngineNumber                    smallint,
	Priority                        int,
	FamilyID                        int NULL,
	Login                           varchar(30) NULL,
	Application                     varchar(30) NULL,
	Command                         varchar(30) NULL,
	NumChildren                     int NULL,
	SecondsWaiting                  int NULL,
	WaitEventID                     smallint NULL,
	BlockingSPID                    int NULL,
	BlockingXLOID                   int NULL,
	DBName                          varchar(30) NULL,
	EngineGroupName                 varchar(30) NULL,
	ExecutionClass                  varchar(30) NULL,
	MasterTransactionID             varchar(255) NULL,
) 
materialized 
at "$monProcess"
go
grant select on monProcess to mon_role
go

/*
** monProcessLookup definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessLookup' 
	  and type = 'U')) 
	drop table monProcessLookup
go
print "Creating monProcessLookup"
go
create existing table monProcessLookup ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	Login                           varchar(30) NULL,
	Application                     varchar(30) NULL,
	ClientHost                      varchar(30) NULL,
	ClientIP                        varchar(64) NULL,
	ClientOSPID                     varchar(30) NULL,
) 
materialized 
at "$monProcessLookup"
go
grant select on monProcessLookup to mon_role
go

/*
** monProcessActivity definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessActivity' 
	  and type = 'U')) 
	drop table monProcessActivity
go
print "Creating monProcessActivity"
go
create existing table monProcessActivity ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	ServerUserID                    int,
	CPUTime                         int,
	WaitTime                        int,
	PhysicalReads                   int,
	LogicalReads                    int,
	PagesRead                       int,
	PhysicalWrites                  int,
	PagesWritten                    int,
	MemUsageKB                      int,
	LocksHeld                       int,
	TableAccesses                   int,
	IndexAccesses                   int,
	TempDbObjects                   int,
	WorkTables                      int,
	ULCBytesWritten                 int,
	ULCFlushes                      int,
	ULCFlushFull                    int,
	ULCMaxUsage                     int,
	ULCCurrentUsage                 int,
	Transactions                    int,
	Commits                         int,
	Rollbacks                       int,
) 
materialized 
at "$monProcessActivity"
go
grant select on monProcessActivity to mon_role
go

/*
** monProcessWorkerThread definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessWorkerThread' 
	  and type = 'U')) 
	drop table monProcessWorkerThread
go
print "Creating monProcessWorkerThread"
go
create existing table monProcessWorkerThread ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	ThreadsActive                   int,
	MaxParallelDegree               smallint,
	MaxScanParallelDegree           smallint,
	ParallelQueries                 int,
	PlansAltered                    int,
	FamilyID                        int NULL,
) 
materialized 
at "$monProcessWorkerThread"
go
grant select on monProcessWorkerThread to mon_role
go

/*
** monProcessNetIO definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessNetIO' 
	  and type = 'U')) 
	drop table monProcessNetIO
go
print "Creating monProcessNetIO"
go
create existing table monProcessNetIO ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	NetworkPacketSize               int,
	PacketsSent                     int,
	PacketsReceived                 int,
	BytesSent                       int,
	BytesReceived                   int,
	NetworkEngineNumber             smallint NULL,
) 
materialized 
at "$monProcessNetIO"
go
grant select on monProcessNetIO to mon_role
go

/*
** monProcessObject definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessObject' 
	  and type = 'U')) 
	drop table monProcessObject
go
print "Creating monProcessObject"
go
create existing table monProcessObject ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	DBID                            int,
	ObjectID                        int,
	PartitionID                     int,
	IndexID                         int,
	OwnerUserID                     int,
	LogicalReads                    int,
	PhysicalReads                   int,
	PhysicalAPFReads                int,
	DBName                          varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	PartitionName                   varchar(30) NULL,
	ObjectType                      varchar(30) NULL,
	PartitionSize                   int NULL,
) 
materialized 
at "$monProcessObject"
go
grant select on monProcessObject to mon_role
go

/*
** monProcessWaits definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessWaits' 
	  and type = 'U')) 
	drop table monProcessWaits
go
print "Creating monProcessWaits"
go
create existing table monProcessWaits ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	ServerUserID                    int,
	WaitEventID                     smallint,
	Waits                           int,
	WaitTime                        int,
) 
materialized 
at "$monProcessWaits"
go
grant select on monProcessWaits to mon_role
go

/*
** monProcessStatement definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessStatement' 
	  and type = 'U')) 
	drop table monProcessStatement
go
print "Creating monProcessStatement"
go
create existing table monProcessStatement ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	DBID                            int,
	ProcedureID                     int,
	PlanID                          int,
	BatchID                         int,
	ContextID                       int,
	LineNumber                      int,
	CpuTime                         int,
	WaitTime                        int,
	MemUsageKB                      int,
	PhysicalReads                   int,
	LogicalReads                    int,
	PagesModified                   int,
	PacketsSent                     int,
	PacketsReceived                 int,
	NetworkPacketSize               int,
	PlansAltered                    int,
	RowsAffected                    int,
	DBName                          varchar(30) NULL,
	StartTime                       datetime NULL,
) 
materialized 
at "$monProcessStatement"
go
grant select on monProcessStatement to mon_role
go

/*
** monSysStatement definition
*/
if (exists (select * from sysobjects 
	where name = 'monSysStatement' 
	  and type = 'U')) 
	drop table monSysStatement
go
print "Creating monSysStatement"
go
create existing table monSysStatement ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	DBID                            int,
	ProcedureID                     int,
	PlanID                          int,
	BatchID                         int,
	ContextID                       int,
	LineNumber                      int,
	CpuTime                         int,
	WaitTime                        int,
	MemUsageKB                      int,
	PhysicalReads                   int,
	LogicalReads                    int,
	PagesModified                   int,
	PacketsSent                     int,
	PacketsReceived                 int,
	NetworkPacketSize               int,
	PlansAltered                    int,
	RowsAffected                    int,
	ErrorStatus                     int,
	HashKey                         int,
	SsqlId                          int,
	ProcNestLevel                   int,
	StatementNumber                 int,
	DBName                          varchar(30) NULL,
	StartTime                       datetime NULL,
	EndTime                         datetime NULL,
) 
materialized 
at "$monSysStatement"
go
grant select on monSysStatement to mon_role
go

/*
** monProcessSQLText definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessSQLText' 
	  and type = 'U')) 
	drop table monProcessSQLText
go
print "Creating monProcessSQLText"
go
create existing table monProcessSQLText ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	ServerUserID                    int,
	BatchID                         int,
	LineNumber                      int,
	SequenceInLine                  int,
	SQLText                         varchar(255) NULL,
) 
materialized 
at "$monProcessSQLText"
go
grant select on monProcessSQLText to mon_role
go

/*
** monSysSQLText definition
*/
if (exists (select * from sysobjects 
	where name = 'monSysSQLText' 
	  and type = 'U')) 
	drop table monSysSQLText
go
print "Creating monSysSQLText"
go
create existing table monSysSQLText ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	ServerUserID                    int,
	BatchID                         int,
	SequenceInBatch                 int,
	SQLText                         varchar(255) NULL,
) 
materialized 
at "$monSysSQLText"
go
grant select on monSysSQLText to mon_role
go

/*
** monCachedProcedures definition
*/
if (exists (select * from sysobjects 
	where name = 'monCachedProcedures' 
	  and type = 'U')) 
	drop table monCachedProcedures
go
print "Creating monCachedProcedures"
go
create existing table monCachedProcedures ( 
	ObjectID                        int,
	InstanceID                      tinyint,
	OwnerUID                        int,
	DBID                            int,
	PlanID                          int,
	MemUsageKB                      int,
	CompileDate                     datetime,
	ObjectName                      varchar(30) NULL,
	ObjectType                      varchar(32) NULL,
	OwnerName                       varchar(30) NULL,
	DBName                          varchar(30) NULL,
	RequestCnt                      int NULL,
	TempdbRemapCnt                  int NULL,
	AvgTempdbRemapTime              int NULL,
) 
materialized 
at "$monCachedProcedures"
go
grant select on monCachedProcedures to mon_role
go

/*
** monProcessProcedures definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessProcedures' 
	  and type = 'U')) 
	drop table monProcessProcedures
go
print "Creating monProcessProcedures"
go
create existing table monProcessProcedures ( 
	SPID                            int,
	InstanceID                      tinyint,
	KPID                            int,
	DBID                            int,
	OwnerUID                        int,
	ObjectID                        int,
	PlanID                          int,
	MemUsageKB                      int,
	CompileDate                     datetime,
	ContextID                       int,
	LineNumber                      int,
	StatementNumber                 int,
	DBName                          varchar(30) NULL,
	OwnerName                       varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	ObjectType                      varchar(32) NULL,
) 
materialized 
at "$monProcessProcedures"
go
grant select on monProcessProcedures to mon_role
go

/*
** monSysPlanText definition
*/
if (exists (select * from sysobjects 
	where name = 'monSysPlanText' 
	  and type = 'U')) 
	drop table monSysPlanText
go
print "Creating monSysPlanText"
go
create existing table monSysPlanText ( 
	PlanID                          int,
	InstanceID                      tinyint,
	SPID                            int,
	KPID                            int,
	BatchID                         int,
	ContextID                       int,
	SequenceNumber                  int,
	DBID                            int,
	ProcedureID                     int,
	DBName                          varchar(30) NULL,
	PlanText                        varchar(160) NULL,
) 
materialized 
at "$monSysPlanText"
go
grant select on monSysPlanText to mon_role
go

/*
** monOpenPartitionActivity definition
*/
if (exists (select * from sysobjects 
	where name = 'monOpenPartitionActivity' 
	  and type = 'U')) 
	drop table monOpenPartitionActivity
go
print "Creating monOpenPartitionActivity"
go
create existing table monOpenPartitionActivity ( 
	DBID                            int,
	ObjectID                        int,
	IndexID                         int,
	PartitionID                     int,
	InstanceID                      tinyint,
	DBName                          varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	PartitionName                   varchar(30) NULL,
	LogicalReads                    int NULL,
	PhysicalReads                   int NULL,
	APFReads                        int NULL,
	PagesRead                       int NULL,
	PhysicalWrites                  int NULL,
	PagesWritten                    int NULL,
	RowsInserted                    int NULL,
	RowsDeleted                     int NULL,
	RowsUpdated                     int NULL,
	OptSelectCount                  int NULL,
	LastOptSelectDate               datetime NULL,
	UsedCount                       int NULL,
	LastUsedDate                    datetime NULL,
	HkgcRequests                    int NULL,
	HkgcPending                     int NULL,
	HkgcOverflows                   int NULL,
	PhysicalLocks                   int NULL,
	PhysicalLocksRetained           int NULL,
	PhysicalLocksRetainWaited       int NULL,
	PhysicalLocksDeadlocks          int NULL,
	PhysicalLocksWaited             int NULL,
	PhysicalLocksPageTransfer       int NULL,
	TransferReqWaited               int NULL,
	AvgPhysicalLockWaitTime         real NULL,
	AvgTransferReqWaitTime          real NULL,
	TotalServiceRequests            int NULL,
	PhysicalLocksDowngraded         int NULL,
	PagesTransferred                int NULL,
	ClusterPageWrites               int NULL,
	AvgServiceTime                  real NULL,
	AvgTimeWaitedOnLocalUsers       real NULL,
	AvgTransferSendWaitTime         real NULL,
	AvgIOServiceTime                real NULL,
	AvgDowngradeServiceTime         real NULL,
) 
materialized 
at "$monOpenPartitionActivity"
go
grant select on monOpenPartitionActivity to mon_role
go

/*
** monLicense definition
*/
if (exists (select * from sysobjects 
	where name = 'monLicense' 
	  and type = 'U')) 
	drop table monLicense
go
print "Creating monLicense"
go
create existing table monLicense ( 
	InstanceID                      tinyint,
	Quantity                        int,
	Name                            varchar(30) NULL,
	Edition                         varchar(30) NULL,
	Type                            varchar(64) NULL,
	Version                         varchar(16) NULL,
	Status                          varchar(30) NULL,
	LicenseExpiry                   datetime NULL,
	GraceExpiry                     datetime NULL,
	LicenseID                       varchar(150) NULL,
	Filter                          varchar(14) NULL,
	Attributes                      varchar(64) NULL,
) 
materialized 
at "$monLicense"
go
grant select on monLicense to public
go

/*
** monLogicalCluster definition
*/
if (exists (select * from sysobjects 
	where name = 'monLogicalCluster' 
	  and type = 'U')) 
	drop table monLogicalCluster
go
print "Creating monLogicalCluster"
go
create existing table monLogicalCluster ( 
	LCID                            int,
	Attributes                      int,
	ActiveConnections               int,
	BaseInstances                   tinyint,
	ActiveBaseInstances             tinyint,
	FailoverInstances               tinyint,
	ActiveFailoverInstances         tinyint,
	Name                            varchar(30) NULL,
	State                           varchar(20) NULL,
	DownRoutingMode                 varchar(20) NULL,
	FailoverMode                    varchar(30) NULL,
	FailoverRecovery                varchar(30) NULL,
	StartupMode                     varchar(20) NULL,
	SystemView                      varchar(20) NULL,
	Roles                           varchar(30) NULL,
	LoadProfile                     varchar(30) NULL,
	ActionRelease                   varchar(20) NULL,
	Gather                          varchar(30) NULL,
) 
materialized 
at "$monLogicalCluster"
go
grant select on monLogicalCluster to public
go

/*
** monLogicalClusterAction definition
*/
if (exists (select * from sysobjects 
	where name = 'monLogicalClusterAction' 
	  and type = 'U')) 
	drop table monLogicalClusterAction
go
print "Creating monLogicalClusterAction"
go
create existing table monLogicalClusterAction ( 
	Handle                          int,
	LCID                            int,
	InstancesWaiting                int,
	StartTime                       datetime,
	ConnectionsRemaining            int,
	NonMigConnections               int,
	NonHAConnections                int,
	State                           varchar(20) NULL,
	LogicalClusterName              varchar(30) NULL,
	Action                          varchar(30) NULL,
	FromInstances                   varchar(96) NULL,
	ToInstances                     varchar(96) NULL,
	WaitType                        varchar(20) NULL,
	Deadline                        datetime NULL,
	CompleteTime                    datetime NULL,
) 
materialized 
at "$monLogicalClusterAction"
go
grant select on monLogicalClusterAction to public
go

/*
** monLogicalClusterInstance definition
*/
if (exists (select * from sysobjects 
	where name = 'monLogicalClusterInstance' 
	  and type = 'U')) 
	drop table monLogicalClusterInstance
go
print "Creating monLogicalClusterInstance"
go
create existing table monLogicalClusterInstance ( 
	LCID                            int,
	InstanceID                      tinyint,
	ActiveConnections               int,
	NonMigConnections               int,
	NonHAConnections                int,
	LoadScore                       real,
	LogicalClusterName              varchar(30) NULL,
	InstanceName                    varchar(30) NULL,
	Type                            varchar(20) NULL,
	FailoverGroup                   tinyint NULL,
	State                           varchar(20) NULL,
) 
materialized 
at "$monLogicalClusterInstance"
go
grant select on monLogicalClusterInstance to public
go

/*
** monLogicalClusterRoute definition
*/
if (exists (select * from sysobjects 
	where name = 'monLogicalClusterRoute' 
	  and type = 'U')) 
	drop table monLogicalClusterRoute
go
print "Creating monLogicalClusterRoute"
go
create existing table monLogicalClusterRoute ( 
	LCID                            int,
	LogicalClusterName              varchar(30) NULL,
	RouteType                       varchar(20) NULL,
	RouteKey                        varchar(30) NULL,
) 
materialized 
at "$monLogicalClusterRoute"
go
grant select on monLogicalClusterRoute to public
go

/*
** monWorkload definition
*/
if (exists (select * from sysobjects 
	where name = 'monWorkload' 
	  and type = 'U')) 
	drop table monWorkload
go
print "Creating monWorkload"
go
create existing table monWorkload ( 
	LCID                            int,
	InstanceID                      tinyint,
	LoadProfileID                   tinyint,
	LoadScore                       real,
	ConnectionsScore                real,
	CpuScore                        real,
	RunQueueScore                   real,
	IoLoadScore                     real,
	EngineScore                     real,
	UserScore                       real,
	LogicalClusterName              varchar(30) NULL,
	InstanceName                    varchar(30) NULL,
	LoadProfileName                 varchar(30) NULL,
) 
materialized 
at "$monWorkload"
go
grant select on monWorkload to public
go

/*
** monWorkloadPreview definition
*/
if (exists (select * from sysobjects 
	where name = 'monWorkloadPreview' 
	  and type = 'U')) 
	drop table monWorkloadPreview
go
print "Creating monWorkloadPreview"
go
create existing table monWorkloadPreview ( 
	InstanceID                      tinyint,
	LoadProfileID                   tinyint,
	LoadScore                       real,
	ConnectionsScore                real,
	CpuScore                        real,
	RunQueueScore                   real,
	IoLoadScore                     real,
	EngineScore                     real,
	UserScore                       real,
	InstanceName                    varchar(30) NULL,
	LoadProfileName                 varchar(30) NULL,
) 
materialized 
at "$monWorkloadPreview"
go
grant select on monWorkloadPreview to public
go

/*
** monWorkloadProfile definition
*/
if (exists (select * from sysobjects 
	where name = 'monWorkloadProfile' 
	  and type = 'U')) 
	drop table monWorkloadProfile
go
print "Creating monWorkloadProfile"
go
create existing table monWorkloadProfile ( 
	ProfileID                       int,
	ConnectionsWeight               tinyint,
	CpuWeight                       tinyint,
	RunQueueWeight                  tinyint,
	IoLoadWeight                    tinyint,
	EngineWeight                    tinyint,
	UserWeight                      tinyint,
	LoginThreshold                  tinyint,
	DynamicThreshold                tinyint,
	Hysteresis                      tinyint,
	Name                            varchar(30) NULL,
	Type                            varchar(20) NULL,
) 
materialized 
at "$monWorkloadProfile"
go
grant select on monWorkloadProfile to public
go

/*
** monWorkloadRaw definition
*/
if (exists (select * from sysobjects 
	where name = 'monWorkloadRaw' 
	  and type = 'U')) 
	drop table monWorkloadRaw
go
print "Creating monWorkloadRaw"
go
create existing table monWorkloadRaw ( 
	InstanceID                      tinyint,
	ConnectionsRaw                  real,
	CpuRaw                          real,
	RunQueueRaw                     real,
	IoLoadRaw                       real,
	EngineRaw                       real,
	UserRaw                         real,
	InstanceName                    varchar(30) NULL,
) 
materialized 
at "$monWorkloadRaw"
go
grant select on monWorkloadRaw to public
go

/*
** monSysLoad definition
*/
if (exists (select * from sysobjects 
	where name = 'monSysLoad' 
	  and type = 'U')) 
	drop table monSysLoad
go
print "Creating monSysLoad"
go
create existing table monSysLoad ( 
	StatisticID                     smallint,
	InstanceID                      tinyint,
	EngineNumber                    smallint,
	Sample                          real,
	SteadyState                     real,
	Avg_1min                        real,
	Avg_5min                        real,
	Avg_15min                       real,
	Peak                            real,
	Max_1min                        real,
	Max_5min                        real,
	Max_15min                       real,
	Peak_Time                       datetime,
	Max_1min_Time                   datetime,
	Max_5min_Time                   datetime,
	Max_15min_Time                  datetime,
	Statistic                       varchar(30) NULL,
) 
materialized 
at "$monSysLoad"
go
grant select on monSysLoad to public
go

/*
** monCIPC definition
*/
if (exists (select * from sysobjects 
	where name = 'monCIPC' 
	  and type = 'U')) 
	drop table monCIPC
go
print "Creating monCIPC"
go
create existing table monCIPC ( 
	InstanceID                      tinyint,
	ReceiveCount                    int,
	TransmitCount                   int,
	Multicast                       int,
	Synchronous                     int,
	ReceiveSoftError                int,
	ReceiveHardError                int,
	TransmitSoftError               int,
	TransmitHardError               int,
	Retransmits                     int,
	Switches                        int,
	FailedSwitches                  int,
	RegularBuffersInUse             int,
	FreeRegularBuffers              int,
	MaxRegularBuffersInUse          int,
	LargeBuffersInUse               int,
	FreeLargeBuffers                int,
	MaxLargeBuffersInUse            int,
) 
materialized 
at "$monCIPC"
go
grant select on monCIPC to mon_role
go

/*
** monCIPCEndpoints definition
*/
if (exists (select * from sysobjects 
	where name = 'monCIPCEndpoints' 
	  and type = 'U')) 
	drop table monCIPCEndpoints
go
print "Creating monCIPCEndpoints"
go
create existing table monCIPCEndpoints ( 
	InstanceID                      tinyint,
	ReceiveCount                    int,
	TransmitCount                   int,
	ReceiveBytes                    int,
	TransmitBytes                   int,
	ReceiveQ                        int,
	MaxReceiveQ                     int,
	DoneQ                           int,
	MaxDoneQ                        int,
	MaxRecvQTime                    real,
	AvgRecvQTime                    real,
	EndPoint                        varchar(30) NULL,
) 
materialized 
at "$monCIPCEndpoints"
go
grant select on monCIPCEndpoints to mon_role
go

/*
** monCIPCMesh definition
*/
if (exists (select * from sysobjects 
	where name = 'monCIPCMesh' 
	  and type = 'U')) 
	drop table monCIPCMesh
go
print "Creating monCIPCMesh"
go
create existing table monCIPCMesh ( 
	InstanceID                      tinyint,
	FarInstanceID                   tinyint,
	Received                        int,
	Dropped                         int,
	Transmitted                     int,
	Resent                          int,
	Retry                           int,
	ControlRx                       int,
	ControlTx                       int,
	SendQ                           int,
	MaxSendQ                        int,
	SentQ                           int,
	MaxSentQ                        int,
	MaxSendQTime                    real,
	AvgSendQTime                    real,
	Mesh                            varchar(30) NULL,
	MinRTT                          int NULL,
	MaxRTT                          int NULL,
	AverageRTT                      int NULL,
) 
materialized 
at "$monCIPCMesh"
go
grant select on monCIPCMesh to mon_role
go

/*
** monClusterCacheManager definition
*/
if (exists (select * from sysobjects 
	where name = 'monClusterCacheManager' 
	  and type = 'U')) 
	drop table monClusterCacheManager
go
print "Creating monClusterCacheManager"
go
create existing table monClusterCacheManager ( 
	InstanceID                      tinyint,
	RequestsQueued                  int,
	RequestsRequeued                int,
	RequestsServiced                int,
	DiskWrites                      int,
	SleepCount                      int,
	DaemonName                      varchar(30) NULL,
	TransfersInitiated              int NULL,
	Downgrades                      int NULL,
	Releases                        int NULL,
	AvgServiceTime                  real NULL,
	MaxQSize                        int NULL,
) 
materialized 
at "$monClusterCacheManager"
go
grant select on monClusterCacheManager to mon_role
go

/*
** monCMSFailover definition
*/
if (exists (select * from sysobjects 
	where name = 'monCMSFailover' 
	  and type = 'U')) 
	drop table monCMSFailover
go
print "Creating monCMSFailover"
go
create existing table monCMSFailover ( 
	InstanceID                      tinyint,
	FailedInstanceID                varchar(96) NULL,
	FailDetectTime                  datetime NULL,
	InitViewTime                    datetime NULL,
	FinalViewTime                   datetime NULL,
	ResyncHBTime                    datetime NULL,
	NotifyFailTime                  datetime NULL,
	EventdoneTime                   datetime NULL,
) 
materialized 
at "$monCMSFailover"
go
grant select on monCMSFailover to mon_role
go

/*
** monTempdbActivity definition
*/
if (exists (select * from sysobjects 
	where name = 'monTempdbActivity' 
	  and type = 'U')) 
	drop table monTempdbActivity
go
print "Creating monTempdbActivity"
go
create existing table monTempdbActivity ( 
	DBID                            int,
	InstanceID                      tinyint,
	AppendLogRequests               int,
	AppendLogWaits                  int,
	DBName                          varchar(30) NULL,
	LogicalReads                    int NULL,
	PhysicalReads                   int NULL,
	APFReads                        int NULL,
	PagesRead                       int NULL,
	PhysicalWrites                  int NULL,
	PagesWritten                    int NULL,
	LockRequests                    int NULL,
	LockWaits                       int NULL,
	CatLockRequests                 int NULL,
	CatLockWaits                    int NULL,
	AssignedCnt                     int NULL,
	SharableTabCnt                  int NULL,
) 
materialized 
at "$monTempdbActivity"
go
grant select on monTempdbActivity to mon_role
go

/*
** monCIPCLinks definition
*/
if (exists (select * from sysobjects 
	where name = 'monCIPCLinks' 
	  and type = 'U')) 
	drop table monCIPCLinks
go
print "Creating monCIPCLinks"
go
create existing table monCIPCLinks ( 
	InstanceID                      tinyint,
	LocalInterface                  varchar(30),
	RemoteInterface                 varchar(30),
	PassiveState                    varchar(10),
	PassiveStateAge                 int,
	ActiveState                     varchar(10),
	ActiveStateAge                  int,
) 
materialized 
at "$monCIPCLinks"
go
grant select on monCIPCLinks to mon_role
go

/*
** monProcessMigration definition
*/
if (exists (select * from sysobjects 
	where name = 'monProcessMigration' 
	  and type = 'U')) 
	drop table monProcessMigration
go
print "Creating monProcessMigration"
go
create existing table monProcessMigration ( 
	SPID                            int,
	KPID                            int,
	LogicalCluster                  varchar(30) NULL,
	Instance                        varchar(30) NULL,
	MigrationLogicalCluster         varchar(30) NULL,
	MigrationInstance               varchar(30) NULL,
	Command                         varchar(30) NULL,
) 
materialized 
at "$monProcessMigration"
go
grant select on monProcessMigration to public
go

/*
** monStatementCache definition
*/
if (exists (select * from sysobjects 
	where name = 'monStatementCache' 
	  and type = 'U')) 
	drop table monStatementCache
go
print "Creating monStatementCache"
go
create existing table monStatementCache ( 
	InstanceID                      tinyint,
	TotalSizeKB                     int,
	UsedSizeKB                      int,
	NumStatements                   int,
	NumSearches                     int,
	HitCount                        int,
	NumInserts                      int,
	NumRemovals                     int,
	NumRecompilesSchemaChanges      int,
	NumRecompilesPlanFlushes        int,
) 
materialized 
at "$monStatementCache"
go
grant select on monStatementCache to mon_role
go

/*
** monCachedStatement definition
*/
if (exists (select * from sysobjects 
	where name = 'monCachedStatement' 
	  and type = 'U')) 
	drop table monCachedStatement
go
print "Creating monCachedStatement"
go
create existing table monCachedStatement ( 
	InstanceID                      tinyint,
	SSQLID                          int,
	Hashkey                         int,
	UserID                          int,
	SUserID                         int,
	DBID                            smallint,
	UseCount                        int,
	StatementSize                   int,
	MinPlanSizeKB                   int,
	MaxPlanSizeKB                   int,
	CurrentUsageCount               int,
	MaxUsageCount                   int,
	NumRecompilesSchemaChanges      int,
	NumRecompilesPlanFlushes        int,
	HasAutoParams                   tinyint,
	ParallelDegree                  tinyint,
	QuotedIdentifier                tinyint,
	TransactionIsolationLevel       tinyint,
	TransactionMode                 tinyint,
	SAAuthorization                 tinyint,
	SystemCatalogUpdate             tinyint,
	MetricsCount                    int,
	MinPIO                          int,
	MaxPIO                          int,
	AvgPIO                          int,
	MinLIO                          int,
	MaxLIO                          int,
	AvgLIO                          int,
	MinCpuTime                      int,
	MaxCpuTime                      int,
	AvgCpuTime                      int,
	MinElapsedTime                  int,
	MaxElapsedTime                  int,
	AvgElapsedTime                  int,
	DBName                          varchar(30) NULL,
	CachedDate                      datetime NULL,
	LastUsedDate                    datetime NULL,
	LastRecompiledDate              datetime NULL,
) 
materialized 
at "$monCachedStatement"
go
grant select on monCachedStatement to mon_role
go

/*
** monPCIBridge definition
*/
if (exists (select * from sysobjects 
	where name = 'monPCIBridge' 
	  and type = 'U')) 
	drop table monPCIBridge
go
print "Creating monPCIBridge"
go
create existing table monPCIBridge ( 
	InstanceID                      tinyint,
	Status                          char(10),
	ConfiguredSlots                 int,
	ActiveSlots                     int,
	ConfiguredPCIMemoryKB           int,
	UsedPCIMemoryKB                 int,
) 
materialized 
at "$monPCIBridge"
go
grant select on monPCIBridge to mon_role
go

/*
** monPCISlots definition
*/
if (exists (select * from sysobjects 
	where name = 'monPCISlots' 
	  and type = 'U')) 
	drop table monPCISlots
go
print "Creating monPCISlots"
go
create existing table monPCISlots ( 
	InstanceID                      tinyint,
	Slot                            int,
	Status                          char(10),
	Modulename                      varchar(30),
	engine                          int,
) 
materialized 
at "$monPCISlots"
go
grant select on monPCISlots to mon_role
go

/*
** monPCIEngine definition
*/
if (exists (select * from sysobjects 
	where name = 'monPCIEngine' 
	  and type = 'U')) 
	drop table monPCIEngine
go
print "Creating monPCIEngine"
go
create existing table monPCIEngine ( 
	InstanceID                      tinyint,
	engine                          int,
	Status                          char(10),
	PLBStatus                       char(10),
	NumberofActiveThreads           int,
	PLBRequests                     int,
	PLBwakeupRequests               int,
) 
materialized 
at "$monPCIEngine"
go
grant select on monPCIEngine to mon_role
go

/*
** monSQLRepActivity definition
*/
if (exists (select * from sysobjects 
	where name = 'monSQLRepActivity' 
	  and type = 'U')) 
	drop table monSQLRepActivity
go
print "Creating monSQLRepActivity"
go
create existing table monSQLRepActivity ( 
	DBID                            int,
	ObjectID                        int,
	InstanceID                      tinyint,
	DBName                          varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	UpdateStmts                     int NULL,
	InsertSelectStmts               int NULL,
	DeleteStmts                     int NULL,
	SelectIntoStmts                 int NULL,
	RowsThreshold                   int NULL,
) 
materialized 
at "$monSQLRepActivity"
go
grant select on monSQLRepActivity to mon_role
go

/*
** monSQLRepMisses definition
*/
if (exists (select * from sysobjects 
	where name = 'monSQLRepMisses' 
	  and type = 'U')) 
	drop table monSQLRepMisses
go
print "Creating monSQLRepMisses"
go
create existing table monSQLRepMisses ( 
	DBID                            int,
	ObjectID                        int,
	InstanceID                      tinyint,
	DBName                          varchar(30) NULL,
	ObjectName                      varchar(30) NULL,
	Threshold                       int NULL,
	QueryLimitation                 int NULL,
	Configuration                   int NULL,
) 
materialized 
at "$monSQLRepMisses"
go
grant select on monSQLRepMisses to mon_role
go

/*
** monPCM definition
*/
if (exists (select * from sysobjects 
	where name = 'monPCM' 
	  and type = 'U')) 
	drop table monPCM
go
print "Creating monPCM"
go
create existing table monPCM ( 
	InstanceId                      tinyint,
	Sent                            int,
	Fragments_sent                  int,
	Fragments_received              int,
	Received                        int,
	Reply                           int,
	Unicast                         int,
	Multicast                       int,
	Sync                            int,
	Async                           int,
	MinBytes                        int,
	AvgBytes                        int,
	MaxBytes                        int,
	MinDialog                       int,
	AvgDialog                       int,
	MaxDialog                       int,
	Dialog                          int,
	MinTimeSyncApi                  real,
	AvgTimeSyncApi                  real,
	MaxTimeSyncApi                  real,
	MinTimeAsyncApi                 real,
	AvgTimeAsyncApi                 real,
	MaxTimeAsyncApi                 real,
	MinTimeCIPCMsgAlloc             real,
	AvgTimeCIPCMsgAlloc             real,
	MaxTimeCIPCMsgAlloc             real,
	MinTimeCIPCSendCB               real,
	AvgTimeCIPCSendCB               real,
	MaxTimeCIPCSendCB               real,
	MinTimeCIPCUnicastsmsg          real,
	AvgTimeCIPCUnicastsmsg          real,
	MaxTimeCIPCUnicastsmsg          real,
	MinTimeCIPCMulticastsmsg        real,
	AvgTimeCIPCMulticastsmsg        real,
	MaxTimeCIPCMulticastsmsg        real,
	MinTimeClientRecvCB             real,
	AvgTimeClientRecvCB             real,
	MaxTimeClientRecvCB             real,
	ModuleName                      varchar(32) NULL,
) 
materialized 
at "$monPCM"
go
grant select on monPCM to mon_role
go

/*
** monCLMObjectActivity definition
*/
if (exists (select * from sysobjects 
	where name = 'monCLMObjectActivity' 
	  and type = 'U')) 
	drop table monCLMObjectActivity
go
print "Creating monCLMObjectActivity"
go
create existing table monCLMObjectActivity ( 
	InstanceID                      tinyint,
	DBID                            int,
	Object_PartitionID              int,
	LockRequests                    int,
	LocalMaster                     int,
	Waited                          int,
	Granted                         int,
	RWConflictWaited                int,
	AvgRWConflictWaitTime           real,
	MaxRWConflictWaitTime           real,
	WWConflictWaited                int,
	AvgWWConflictWaitTime           real,
	MaxWWConflictWaitTime           real,
	ClusterMsgWaits                 int,
	AvgClusterMsgWaitTime           real,
	MaxClusterMsgWaitTime           real,
	DowngradeReqRecv                int,
	DowngradeReqRecvWithNoBlocker   int,
	ClusterDeadlock                 int,
	LockType                        varchar(20) NULL,
) 
materialized 
at "$monCLMObjectActivity"
go
grant select on monCLMObjectActivity to mon_role
go

/*
** monTableTransfer definition
*/
if (exists (select * from sysobjects 
	where name = 'monTableTransfer' 
	  and type = 'U')) 
	drop table monTableTransfer
go
print "Creating monTableTransfer"
go
create existing table monTableTransfer ( 
	InstanceID                      tinyint,
	DBID                            smallint,
	TableID                         int,
	SequenceID                      int,
	PercentDone                     smallint,
	BeginTime                       datetime,
	TransferFloor                   bigint,
	TransferCeiling                 bigint,
	RowsSent                        bigint,
	BytesSent                       bigint,
	TableName                       varchar(255) NULL,
	TrackingID                      int NULL,
	EndTime                         datetime NULL,
	EndCode                         smallint NULL,
	Format                          varchar(8) NULL,
) 
materialized 
at "$monTableTransfer"
go
grant select on monTableTransfer to public
go

/*
** monInmemoryStorage definition
*/
if (exists (select * from sysobjects 
	where name = 'monInmemoryStorage' 
	  and type = 'U')) 
	drop table monInmemoryStorage
go
print "Creating monInmemoryStorage"
go
create existing table monInmemoryStorage ( 
	InstanceID                      tinyint,
	ID                              int,
	DeviceNum                       int,
	StartPage                       int,
	NumPages                        int,
	SizeKB                          int,
	Name                            varchar(30) NULL,
	DeviceName                      varchar(30) NULL,
	Type                            varchar(30) NULL,
	Status                          varchar(30) NULL,
) 
materialized 
at "$monInmemoryStorage"
go
grant select on monInmemoryStorage to public
go

declare @retval int
exec @retval = sp_version 'montables',NULL,'15.5/17340/P/x86_64/Enterprise Linux/ase155/2391/64-bit/OPT/Mon Nov 09 13:55:05 2009', 'end'
if (@retval != 0) select syb_quit()
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_dcachestats')
begin
	drop procedure sp_sysmon_dcachestats
end
go
print "Installing sp_sysmon_dcachestats"
go


if exists(select 1 from tempdb.dbo.sysobjects where
			name = 'tempcachestats' and uid = 1)
begin
	drop table tempdb.dbo.tempcachestats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where
				name = 'tempbufpoolstats' and uid = 1)
begin
	drop table tempdb.dbo.tempbufpoolstats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where
				name = 'tempobjstats' and uid = 1)
begin
	drop table tempdb.dbo.tempobjstats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where
				name = 'tempcachedobjstats' and uid = 1)
begin
	drop table tempdb.dbo.tempcachedobjstats
end
go

if object_id("#tempmonitors") is not null
begin
	drop table #tempmonitors
end

if object_id("#obj_details") is not null
begin
	drop table #obj_details
end
set nocount on
go

select 	getdate() as InsertTime,
	0 as MdaStatus,
	CacheID, RelaxedReplacement,
	PhysicalReads, LogicalReads, CachePartitions, CacheName
into	tempdb.dbo.tempcachestats
from	master.dbo.monDataCache
where	1=2
go

select 	getdate() as InsertTime,
	CacheID, IOBufferSize,
	AllocatedKB,
	PagesTouched,
	PhysicalReads,
	CacheName
into	tempdb.dbo.tempbufpoolstats
from	master.dbo.monCachePool
where	1=2
go

select 	getdate() as InsertTime,
	LogicalReads, PhysicalReads,
	DBID, ObjectID, IndexID
into	tempdb.dbo.tempobjstats
from	master.dbo.monOpenObjectActivity
where	1=2
go

select 	getdate() as InsertTime,
	CachedKB, CacheName, DBID,
	ObjectID, IndexID
into	tempdb.dbo.tempcachedobjstats
from	master.dbo.monCachedObject
where	1=2
go

select * into #tempmonitors from master.dbo.sysmonitors where 1=2
go

use sybsystemprocs
go

if ((select object_id("#obj_details")) is not NULL)
begin
	drop table #obj_details
end
go

if exists(select 1 from sybsystemprocs.dbo.sysobjects where
		sysstat & 7 = 4	and name = 'sp_sysmon_dcachestats')
begin
	drop procedure sp_sysmon_dcachestats
end
go

create procedure sp_sysmon_dcachestats
  @top_n_objs 	varchar(14),		/* top 'n' objects to report on */
  @cachename	varchar(255),		/* cache name */
  @seconds	int,
  @Reco_option	char(1)			/* print recommendations */
as

declare	@blankline		char(80)
declare	@separator_line		char(80)
declare	@rpt_line		char(80)	/* formatted line for print */
declare	@exec_str		char(1250)	/* used in exec immediate */
declare	@ldspc			char(1)
declare	@col_sep		char(1)
declare	@psign			char(1)		/* percent sign */
declare	@ret			int
declare	@cache_size_in_KB	int
declare	@top_n			int		/* int value of top_n_objs */

declare	@cache_sz_str		varchar(13)
declare	@cache_hit_per		varchar(6)
declare	@cache_usage_per	varchar(6)
declare	@cache_sz_used		real
declare	@logical_reads		int
declare	@physical_reads		int
declare	@spinlock_contention	float
declare	@cache_partitions	int
declare	@cache_id		int

declare	@db_name		varchar(255)
declare	@obj_dbid		int
declare	@tab_id			int
declare	@obj_ind_id		int
declare	@obj_size		int
declare	@obj_lreads		int
declare	@obj_preads		int
declare	@obj_cached_KB		int	
declare	@cache_occp_by_obj_per	varchar(6)
declare	@obj_hit_per		varchar(6)
declare @display_order		int		/* 1 - desc, 0 - asc */
declare	@begin_time		datetime	/* values were cleared */
declare	@end_time		datetime	/* values are reported */
declare	@cut_off_lreads		int		/* value that decides rows
						** selection */
declare @max_objname_len	int		/* auto format object name */
declare	@tmpval			int
declare	@reco			varchar(255)	/* recommendation string */
declare	@max_reco_len		int
declare	@num_engines		int
declare	@numKBperpg		int
declare	@tmp_int		int
declare	@iter_cnt		int
declare	@tmp_cntr		varchar(35)
declare	@tmp_grp		varchar(18)	/* group id in sysmonitors */

declare @LReads_col		varchar(6)
declare @PReads_col		varchar(6)
declare @LReads_rename_col	varchar(6)
declare @PReads_rename_col	varchar(6)
declare	@Usage_Per_col		varchar(6)
declare @Run_Size_col		varchar(8)
declare @Cache_Partitions_col	varchar(16)
declare	@Spin_Contention_col	varchar(20)
declare	@Hit_Per_col		varchar(5)
declare @IO_Size_col		varchar(7)
declare	@Wash_col		varchar(9)
declare	@APF_Per_col		varchar(5)
declare	@APF_Eff_Per_col	varchar(9)
declare	@Object_col		varchar(6)
declare	@Obj_Size_col		varchar(8)
declare	@Size_In_Cache_col	varchar(13)
declare	@Obj_Cached_Per_col	varchar(12)
declare	@Cache_Occupied_Per_col	varchar(12)

declare @tempdbname		varchar(30)	/* assigned tempdb */

select	@blankline	= " "
select	@rpt_line	= " "
select	@separator_line = replicate("-", 80)
select	@ldspc	= " "
select	@col_sep = ":"
select	@psign = "%"
select	@numKBperpg = @@maxpagesize/1024

select @LReads_col = "LReads"
select @PReads_col = "PReads"
select @LReads_rename_col = "LR/sec"
select @PReads_rename_col = "PR/sec"
select @Usage_Per_col = "Usage%"
select @Run_Size_col = "Run Size"
select @Cache_Partitions_col = "Cache Partitions"
select @Spin_Contention_col = "Spinlock Contention%"
select @Hit_Per_col = "Hit%"
select @IO_Size_col = "IO Size"
select @Wash_col = "Wash Size"
select @APF_Per_col = "APF%"
select @APF_Eff_Per_col = "APF-Eff%"
select @Object_col = "Object"
select @Obj_Size_col = "Obj Size"
select @Size_In_Cache_col = "Size in Cache"
select @Obj_Cached_Per_col = "Obj_Cached%"
select @Cache_Occupied_Per_col = "Cache_Occp%"

create table #obj_details(dbid int, owner varchar(30), objid int,
				indid int, index_name varchar(30),
				size_KB int)

create table #recommendations_tab(reco_col varchar(255))

select 	co.config, parent, convert(char(30), co.name) name,
	convert(char(30),co.comment) comment, cu.value run_size,
	memory_used wash_size, apf_percent apf_value
into 	#syscacheconfig
from 	master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
where 	parent = 19
and 	co.config = cu.config
and 	co.name = cu.comment
order by name, config

select	@begin_time = min(InsertTime),
	@end_time = max(InsertTime)
from	tempdb.dbo.tempcachestats

select @top_n = convert(int, @top_n_objs)
select @display_order = sign(@top_n)
if @display_order = 0
begin
	select @display_order = 1
end
select @top_n = abs(@top_n)

set nocount on

/* Create the diff tables */
select 1 as "PrintOrder", cs2.CacheName, cs2.CachePartitions, cs2.CacheID,
	cs2.LogicalReads - cs1.LogicalReads as LogicalReads,
	cs2.PhysicalReads - cs1.PhysicalReads as PhysicalReads
into	#tempcachestats
from	tempdb.dbo.tempcachestats cs1,
	tempdb.dbo.tempcachestats cs2
where	cs2.CacheName = cs1.CacheName
and	cs2.InsertTime = @end_time
and	cs1.InsertTime = @begin_time

update	#tempcachestats
set	PrintOrder = 0
where	CacheName = 'default data cache'

select	bs2.CacheName,
	bs2.IOBufferSize,
	bs2.AllocatedKB,
	bs2.PagesTouched * (@@maxpagesize / 1024) as PoolUsed,
	bs2.PhysicalReads - bs1.PhysicalReads as PhysicalReads,
	tm1.value + tm2.value as LReads,
	tm2.value as PReads,
	tm3.value as APFs_Used
into	#tempbufpoolstats
from	tempdb.dbo.tempbufpoolstats bs2,
	tempdb.dbo.tempbufpoolstats bs1,
	#tempmonitors tm1,
	#tempmonitors tm2,
	#tempmonitors tm3
where	bs2.InsertTime = @end_time
and	bs1.InsertTime = @begin_time
and	bs2.CacheName = bs1.CacheName
and	bs2.IOBufferSize = bs1.IOBufferSize
and	tm1.group_name = "buffer_"
		+ convert(varchar(4), bs2.CacheID) 
and	tm2.group_name = tm1.group_name
and	tm3.group_name = tm1.group_name
and	tm1.field_name = "bufsearch_finds_"
			+ convert(varchar(3), bs2.IOBufferSize / 1024) + "k"
and	tm2.field_name = "bufread_"
			+ convert(varchar(3), bs2.IOBufferSize / 1024) + "k"
and	tm3.field_name = "apf_ios_used_"
			+ convert(varchar(3), bs2.IOBufferSize / 1024) + "k"


select InsertTime, sum(CachedKB) as CachedKB, CacheName, 
	DBID, ObjectID, IndexID
into #tempcachedobjstats 
from tempdb.dbo.tempcachedobjstats
group by InsertTime,ObjectID,IndexID

select	co1.CacheName,
	os2.LogicalReads - os1.LogicalReads as LogicalReads,
	os2.PhysicalReads - os1.PhysicalReads as PhysicalReads,
	os2.DBID, os2.ObjectID, os2.IndexID,
	0 as CachedKB
into	#tempobjstats
from	tempdb.dbo.tempobjstats os1,
	tempdb.dbo.tempobjstats os2,
	#tempcachedobjstats co1
where	os1.DBID *= co1.DBID
and	os1.ObjectID *= co1.ObjectID
and	os1.IndexID *= co1.IndexID
and	os2.DBID = os1.DBID
and	os2.ObjectID = os1.ObjectID
and	os2.IndexID = os1.IndexID
and	os2.InsertTime = @end_time
and	os1.InsertTime = @begin_time
and	co1.InsertTime = @end_time
union
select	co.CacheName,
	os.LogicalReads,
	os.PhysicalReads,
	os.DBID, os.ObjectID, os.IndexID,
	co.CachedKB
from	tempdb.dbo.tempobjstats os,
	#tempcachedobjstats co
where	os.DBID = co.DBID
and	os.ObjectID = co.ObjectID
and	os.IndexID = co.IndexID
and	os.InsertTime = @end_time
and	co.InsertTime = @end_time
and	not exists
			(select ObjectID from tempdb.dbo.tempobjstats
			where	ObjectID = os.ObjectID
			and	ObjectID = co.ObjectID
			and	DBID = os.DBID
			and	IndexID = os.IndexID
			and	InsertTime = @begin_time)

/* Objects that have 0 as LogicalReads are removed */
delete	#tempobjstats
where	LogicalReads = 0

update	#tempobjstats
set	os.CachedKB = co.CachedKB,
	os.CacheName = co.CacheName
from	#tempobjstats os,
	#tempcachedobjstats co
where	os.DBID = co.DBID
and	os.ObjectID = co.ObjectID
and	os.IndexID = co.IndexID
and	co.InsertTime = @end_time

/*
** create cursor to process cache rows
*/
if (@cachename = "NULL")
begin
	select @cachename = "%"
end

declare named_cache_cursor cursor for
	select 	CacheName,
		CachePartitions,
		CacheID,
		LogicalReads,
		PhysicalReads
	from 	#tempcachestats
	where CacheName like @cachename
	order by PrintOrder, CacheName
	for read only

/*
** Declare cursor for storing sampled object stats
*/
declare objstats_cursor cursor for
	select 	LogicalReads, PhysicalReads,
		DBID, ObjectID, IndexID , CachedKB
	from #tempobjstats
	where CacheName like @cachename
	and 
	(	(@display_order = 1 and LogicalReads >= @cut_off_lreads)
					or
		(@display_order = -1 and LogicalReads <= @cut_off_lreads)
	)
	order by PhysicalReads desc, (LogicalReads * @display_order) desc
for read only

open named_cache_cursor
fetch named_cache_cursor into @cachename, @cache_partitions, @cache_id,
	@logical_reads, @physical_reads

dump tran tempdb with truncate_only

/*
** If assigned temporary database is different than system tempdb, then
** dump that one as well.
*/
select @tempdbname = db_name(@@tempdbid)
if (@tempdbname != "tempdb")
begin
	dump tran @tempdbname with truncate_only
end

select @num_engines = count(*) from #tempmonitors
	where field_name="clock_ticks"
	and group_name like "engine_%"
	and value > 0

/*
** Print Report Header
*/
select @rpt_line= replicate("=", 80)
print @rpt_line

select @rpt_line = space(34) + "Cache Wizard" + space(34)
print @rpt_line

select @rpt_line= replicate("=", 80)
print @rpt_line

while (@@sqlstatus = 0)
begin
	print @blankline
	select @cachename = ltrim(rtrim(@cachename))
	select @rpt_line = replicate('-', datalength(@cachename))
	print @rpt_line
	
	print @cachename
	
	print @rpt_line
	
	select @cache_size_in_KB = run_size from #syscacheconfig
	where 	config=19
	and 	parent=19
	and	name=@cachename

	select @cache_sz_str = str(@cache_size_in_KB * 1.0 / 1024, 9, 2) + " Mb"
	
	select 	@cache_sz_used = sum(PoolUsed),
		@logical_reads = sum(LReads),
		@physical_reads = sum(PReads)
	from #tempbufpoolstats
	where CacheName like @cachename
	
	if (@logical_reads = 0)
	begin
		select @cache_hit_per = "   n/a"
	end
	else
	begin
		select @cache_hit_per = str(((@logical_reads - @physical_reads)
						* 100.0
						/ @logical_reads), 6, 2)
	end

	select @cache_usage_per = str(@cache_sz_used * 100.0
						/ @cache_size_in_KB, 6, 2)
	
	/* P.value is grabs and W.value is waits */
	select @spinlock_contention = isnull(avg(100.0*W.value/P.value), 0)
			from #tempmonitors P,
			     #tempmonitors W
			where P.field_name = @cachename
			and P.group_name = "spinlock_p_0"
			and W.group_name = "spinlock_w_0"
			and P.field_id = W.field_id
			and P.value > 0
	
	select @rpt_line = @Run_Size_col + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc + @ldspc + @ldspc
			+ @ldspc + @col_sep
			+ @cache_sz_str + @ldspc + @ldspc + @ldspc
			+ @Usage_Per_col + @psign + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc + @ldspc + @ldspc
			 + @ldspc + @ldspc + @ldspc + @ldspc 
			+ @ldspc + @ldspc + @ldspc
		 	+ @col_sep + @ldspc + @ldspc + @ldspc + @ldspc
			+ @cache_usage_per
	print @rpt_line

	/* If the sampled period is less than 1 sec then @seconds will be '0'.*/
	/* Round @seconds to '1' if it is '0' to avoid devide by zero problems */

	if (@seconds = 0) select @seconds = 1
	
	select @rpt_line = @LReads_rename_col + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc
			+ @col_sep
			+ str(@logical_reads * 1.0 / @seconds, 9, 2)
			+ @ldspc + @ldspc + @ldspc + @ldspc
			+ @ldspc + @ldspc
			+ @PReads_rename_col + @ldspc + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc
			+ @ldspc + @ldspc + @ldspc
			+ @col_sep + @ldspc
			+ str(@physical_reads * 1.0 / @seconds, 9, 2)
			+ @ldspc + @ldspc
			+ @ldspc + @Hit_Per_col + @psign + @col_sep + @ldspc
			+ @cache_hit_per
	print @rpt_line

	select @rpt_line = @Cache_Partitions_col + @col_sep
			+ str(@cache_partitions, 9) + @ldspc  + @ldspc
			+ @ldspc + @ldspc + @ldspc + @ldspc
			+ @Spin_Contention_col + @psign
			+ @col_sep + @ldspc + @ldspc + @ldspc + @ldspc
			+ str(@spinlock_contention, 6, 2)
	print @rpt_line

	print @blankline
	
	/*
	** Print the Buffer Pool Stats
	*/
	select @rpt_line = "Buffer Pool Information"
	print @rpt_line
	
	print @separator_line

	select @exec_str = "select str(IOBufferSize / 1024, 3) + ' Kb' as '"
			+ @IO_Size_col
			+ "', str(wash_size, 7) + ' Kb' as '"
			+ @Wash_col
			+ "', str(AllocatedKB * 1.0 / 1024, 8, 2) + ' Mb' as '"
			+ @Run_Size_col
			+ "', str(apf_value, 6, 2) as '"
			+ @APF_Per_col
			+ "', str(" + @LReads_col + " * 1.0 / "
				+ convert(varchar(6), @seconds)
			+  ", 8, 2) as '" + @LReads_rename_col
			+ "', str(" + @PReads_col + " * 1.0 / "
				+ convert(varchar(6), @seconds)
			+ ", 8, 2) as '" + @PReads_rename_col
			+ "', case when ("
				+ @LReads_col 
				+ " = 0) then '   n/a' else str(("
				+ @LReads_col + " - " + @PReads_col
				+ ") * 100.0 / ("
				+ @LReads_col
				+ "), 6, 2) end as '" + @Hit_Per_col
			+ "', case when (PhysicalReads - "
				+ @PReads_col + " <= 0) then '   n/a' else str("
				+ "APFs_Used * 100.0 / (PhysicalReads - "
				+ @PReads_col + "), 6, 2) end as '"
				+ @APF_Eff_Per_col
			+ "', str(PoolUsed * 100.0 / AllocatedKB, 6, 2) as '"
			+ @Usage_Per_col
			+ "' from #syscacheconfig, #tempbufpoolstats "
			+ "where config = (19 + floor(1.45 * "
				+ "log(IOBufferSize / 1024))) and parent=19 "
				+ " and name='" + @cachename
				+ "' and CacheName like '" + @cachename
				+ "' order by IOBufferSize desc" 
	exec(@exec_str)
	print @blankline
	
	if @Reco_option = 'Y'
	begin
		if (@cache_sz_used * 100.0 / @cache_size_in_KB < 5.0)
		begin
			select @reco = @Usage_Per_col + " for '"
					+ @cachename + "'"
					+ " is low (< 5%)"
			insert into #recommendations_tab(reco_col)
				values(@reco)
		end
	
		select @exec_str = "insert into #recommendations_tab "
				+ " select '" + @Usage_Per_col + "'"
				+ " + ' for '"
				+ " + str(IOBufferSize/1024, 2) "
				+ " + 'k buffer pool in cache:' + CacheName"
				+ " + ' is low (< 5%)' "
				+ "from #tempbufpoolstats "
				+ "where PoolUsed * 100.0 / AllocatedKB < 5.0"
				+ " and CacheName like '" + @cachename + "'"
				+ " order by IOBufferSize desc"
		exec(@exec_str)
	
		select @tmp_grp = "buffer_"
				+ convert(varchar(4), @cache_id)

		if (@num_engines > 1 and (@spinlock_contention >= 10 or @spinlock_contention < 0))
		begin /* { */
			select @reco = "Consider using Named Caches or creating more cache partitions for '" +  @cachename + "' or both."
			insert into #recommendations_tab(reco_col)
							values(@reco)
		end /* } */

		/* recommendations for pool wash size */
		select @tmp_int = SUM(value)
			from #tempmonitors
			where group_name = @tmp_grp
			and field_name like "bufgrab_dirty_%"

		if (@tmp_int is not null)
		begin /* { */
			select @iter_cnt = @numKBperpg
			while (@iter_cnt <= 8*@numKBperpg)
			begin    /* { */
				/*
				**  build pool specific counter name,
				**  bufgrab_Nk (ie bufgrab_16k)
				*/
				select @tmp_cntr = "bufgrab_dirty_"
					+ convert(varchar(3), @iter_cnt) + "k"

				select @tmp_int = value
					from #tempmonitors
					where group_name = @tmp_grp and
					field_name = @tmp_cntr

				if @tmp_int != 0
				begin /* { */
					/*
					** If We grabbed a buffer that was
					** dirty from this pool consider
					** increasing the wash size for
					** this buffer pool
					*/
					select @reco =
						"Consider increasing the 'wash size' of the "+ ltrim(str(@iter_cnt,3)) + "k pool for '" + @cachename + "'"
					insert into #recommendations_tab(reco_col) values(@reco)

				end /* } */
				/* get next pool size (power of 2) */
				select @iter_cnt = @iter_cnt * 2
			end /* } */

		end /* } */
			
		/* recommendations for pool addition */
		if (select value from #tempmonitors
			where group_name = @tmp_grp
			and field_name like "bufopt_lrgmass_reqd") > 0
		begin /* { */
			select @reco =
				"Consider adding a large I/O pool for '"
							+ @cachename + "'"
			insert into #recommendations_tab(reco_col)
							values(@reco)
		end /* } */

		insert into #recommendations_tab(reco_col) values(@blankline)
	end
	print @blankline

	/*
	** We want to order the objects by LogicalReads and then while printing
	** order them by PhysicalReads. The ordering being 'desc' or 'ascending'
	** is decided by @display_order. To achieve this, we will select the
	** cut-off
	** value from the ordered table, which will be the value at row position
	** @top_n when @top_n > 0. In case of 'asc', we will delete all values
	** greater than this value and in case of 'desc', delete all values
	** lesser than this value.
	*/
	set rowcount @top_n
	select 	@cut_off_lreads = LogicalReads,
		@tmpval = LogicalReads * @display_order
	from #tempobjstats
	where CacheName = @cachename
	order by 2 desc

	set rowcount 0
	
	open objstats_cursor
	fetch objstats_cursor into @obj_lreads,
				@obj_preads, @obj_dbid,
				@tab_id, @obj_ind_id,
				@obj_cached_KB
	/*
	** Printing object stats
	*/
	select @rpt_line = "Object Statistics"
	print @rpt_line
	
	print @separator_line
	print @blankline

	while(@@sqlstatus = 0)
	begin
		select @db_name = db_name(@obj_dbid)

		select @exec_str = "exec " + @db_name +
				"..sp_dcachestats_obj_details "
				+ str(@tab_id)
				+ ", "
				+ str(@obj_ind_id)
		exec(@exec_str)
		
		fetch objstats_cursor into @obj_lreads,
				@obj_preads, @obj_dbid,
				@tab_id, @obj_ind_id,
				@obj_cached_KB

	end
	
	close objstats_cursor
	
	select	@max_objname_len = max(datalength(db_name(dbid))
					+ datalength(owner)
					+ datalength(object_name(objid, dbid))
					+ datalength(index_name))
					+ 3
	from	#obj_details
	
	/* Print only when objects are present */
	if @max_objname_len is not NULL
	begin
		select @exec_str = " select convert(varchar("
			+ convert(varchar(3), @max_objname_len)
			+ "), db_name(o.dbid) + '.' + owner + '.' + "
			+ "isnull(object_name(o.objid, o.dbid),"
			+ "convert(varchar(10), o.objid)) + case when "
			+ " o.indid != 0 then '.' + o.index_name end) as "
			+ @Object_col
			+ ", str(LogicalReads * 1.0 / "
				+ convert(varchar(6), @seconds)
			+ ", 7, 2) as '" + @LReads_rename_col
			+ "', str(PhysicalReads * 1.0 / "
				+ convert(varchar(6), @seconds)
			+ ", 7, 2) as '" + @PReads_rename_col
			+ "', case when LogicalReads = 0 then '   n/a' else "
				+ " str(100.0 * (LogicalReads - PhysicalReads)"
					+ " / LogicalReads, 6, 2) end as '"
			+ @Hit_Per_col
			+ "', case when size_KB = 0 then '        n/a' else "
				+ "str(CachedKB * 100.0 / size_KB, 11, 2) end "
			+ "as '" + @Obj_Cached_Per_col
			+ "', str(CachedKB * 100.0 / "
			+ convert(varchar(8), @cache_size_in_KB)
			+ ", 11, 2) as '"
			+ @Cache_Occupied_Per_col
			+ "' from #tempobjstats t, #obj_details o "
			+ " where t.DBID = o.dbid and t.ObjectID = o.objid "
			+ " and t.IndexID = o.indid "
			+ " order by PhysicalReads desc, (LogicalReads * "
			+ convert(varchar(2), @display_order)
			+ ") desc"

		exec(@exec_str)

		print @blankline

		select @exec_str = " select convert(varchar("
			+ convert(varchar(3), @max_objname_len)
			+ "), db_name(o.dbid) + '.' + owner + '.' + "
			+ " isnull(object_name(o.objid, o.dbid),"
			+ "convert(varchar(10), objid)) + case when "
			+ " o.indid != 0 then '.' + index_name end) as "
			+ @Object_col
			+ ", str(size_KB, 8) + ' Kb' as '"
			+ @Obj_Size_col
			+ "', str(CachedKB, 8) + ' Kb' as '"
			+ @Size_In_Cache_col
			+ "' from #tempobjstats t, #obj_details o "
			+ " where t.DBID = o.dbid and t.ObjectID = o.objid "
			+ " and t.IndexID = o.indid"
			+ " order by PhysicalReads desc, (LogicalReads * "
			+ convert(varchar(2), @display_order)
			+ ") desc"
		exec(@exec_str)
	
		/* 
		** truncate #obj_details so that the output is not repeated
		** for the previous cache' objects
		*/
		truncate table #obj_details
	end
	else
	begin
		print "No Activity for objects in this interval"
	end

	fetch named_cache_cursor into @cachename, @cache_partitions, @cache_id,
			@logical_reads, @physical_reads
end
print @blankline
select @max_reco_len = isnull(max(datalength(reco_col)), 1)
					from #recommendations_tab
select @exec_str = "if (select count(*) from #recommendations_tab "
		+ "where reco_col != '" + @blankline
		+ "' ) > 0 " + " begin select convert(varchar("
		+ convert(varchar(3), @max_reco_len)
		+ "), reco_col) as 'TUNING RECOMMENDATIONS' "
		+ "from #recommendations_tab end"
exec(@exec_str)

print @blankline
print "LEGEND"
select @rpt_line = replicate('-', 6)
print @rpt_line
print "%1!		- number of logical reads per second, i.e. sum of cache & disk reads",
							@LReads_rename_col
print "%1!		- number of physical reads per second i.e. disk reads",
							@PReads_rename_col
print "%1!	- size of cache or buffer pool in Kilobytes",
							@Run_Size_col
print "%1!	- number of cache partitions", @Cache_Partitions_col
print "%1!	- Percentage spinlock contention for the cache", @Spin_Contention_col
print "%1!		- ratio of hits to total searches", @Hit_Per_col
print "%1!		- ratio of pages referenced to Run Size", @Usage_Per_col
print @blankline
print "%1!	- wash size of buffer pool in Kilobytes", @Wash_col
print "%1!		- asynchronous prefetch %% for this buffer pool",
								@APF_Per_col
print "%1!	- Ratio of buffers found in cache and brought in because",
								@APF_Eff_Per_col
print "			  of APF to the number of APF disk reads performed"
print @blankline
print "%1!		- combination of db, owner, object and index name",
								@Object_col
print "%1!	- size of the object in Kilobytes", @Obj_Size_col
print "%1!	- size occupied in cache in Kilobytes at the end of sample",
								@Size_In_Cache_col
print "%1!	- Ratio of 'Size in Cache' to 'Obj Size'", @Obj_Cached_Per_col
print "%1!	- Ratio of 'Size in Cache' to 'Run Size' of cache",
							@Cache_Occupied_Per_col
close named_cache_cursor
deallocate cursor named_cache_cursor
deallocate cursor objstats_cursor
return 0
go
go
exec sp_procxmode 'sp_sysmon_dcachestats', 'anymode'
go
grant execute on sp_sysmon_dcachestats to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_collect_mda')
begin
	drop procedure sp_sysmon_collect_mda
end
go
print "Installing sp_sysmon_collect_mda"
go


if exists(select 1 from tempdb.dbo.sysobjects where
			name = 'tempcachestats' and uid = 1)
begin
	drop table tempdb.dbo.tempcachestats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where
				name = 'tempbufpoolstats' and uid = 1)
begin
	drop table tempdb.dbo.tempbufpoolstats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where
				name = 'tempobjstats' and uid = 1)
begin
	drop table tempdb.dbo.tempobjstats
end
go

if exists(select 1 from tempdb.dbo.sysobjects where
				name = 'tempcachedobjstats' and uid = 1)
begin
	drop table tempdb.dbo.tempcachedobjstats
end
go

use sybsystemprocs
go

if (db_name() != "sybsystemprocs")
begin
	/*
	** 19529, "Cannot open database '%1!'. Check the availability of this database and retry the installation."
	*/
	raiserror 19529, "sybsystemprocs"
	select syb_quit()
end
go

if exists(select 1 from sybsystemprocs.dbo.sysobjects where 
		sysstat & 7 = 4 and name = 'sp_sysmon_collect_mda')
begin
	drop procedure sp_sysmon_collect_mda
end
go

/*
** This sproc is installed as a part of installmontables
** The caller is responsible for checking if this stored procedure
** exists or not.
*/

create procedure sp_sysmon_collect_mda
 @interval_or_option char(12),	/* Time interval string, option
				** "begin_sample" or "end_sample" */
 @mda_status int output		/* used in remembering mda enable
				** status */
as

/* ----------- declare local variables ------------ */
declare @msg varchar(250)	/* error msg output */
declare @snapshot_time datetime	/* time recorded in row */

select @snapshot_time = getdate()

if (@interval_or_option != "end_sample")
begin
	if exists (select 1 from tempdb.dbo.sysobjects
			where name like 'tempcachestats' and uid = 1)
	begin
		drop table tempdb.dbo.tempcachestats
	end

	if exists (select 1 from tempdb.dbo.sysobjects
			where name like 'tempbufpoolstats' and uid = 1)
	begin
		drop table tempdb.dbo.tempbufpoolstats
	end

	if exists (select 1 from tempdb.dbo.sysobjects
			where name like 'tempobjstats' and uid = 1)
	begin
		drop table tempdb.dbo.tempobjstats
	end
	
	if exists (select 1 from tempdb.dbo.sysobjects
			where name like 'tempcachedobjstats' and uid = 1)
	begin
		drop table tempdb.dbo.tempcachedobjstats
	end

	/* Create the schema */
	select 	@snapshot_time as "InsertTime",
		@mda_status as "MdaStatus",
		CacheID, RelaxedReplacement,
		PhysicalReads,
		LogicalReads, CachePartitions, CacheName
	into	tempdb.dbo.tempcachestats
	from	master.dbo.monDataCache

	select 	@snapshot_time as "InsertTime",
		CacheID, IOBufferSize,
		AllocatedKB, PagesTouched, PhysicalReads,
		CacheName
	into	tempdb.dbo.tempbufpoolstats
	from	master.dbo.monCachePool

	select 	@snapshot_time as "InsertTime",
		LogicalReads, PhysicalReads,
		DBID, ObjectID, IndexID
	into	tempdb.dbo.tempobjstats
	from	master.dbo.monOpenObjectActivity

	select	@snapshot_time as "InsertTime",
		CachedKB, CacheName, DBID,
		ObjectID, IndexID
	into	tempdb.dbo.tempcachedobjstats
	from	master.dbo.monCachedObject
end
else
begin
	/* raise an error if table does not exist */
	if not exists(select 1 from tempdb.dbo.sysobjects where
					name = 'tempcachestats')
	begin
		/* If we only wanted to know if config values were changed
		** just return 0.
		*/
		if (@mda_status = 99)
		begin
			return(0)
		end
		raiserror 17733, 'tempdb..tempcachestats'
		return (1)
	end
				
	/* 
	** Get the Value of MDA status stored at begin sample 
	** If @mda_status was passed as 99 we should return from here.
	*/
	if (@mda_status = 99) 
	begin
		select @mda_status = MdaStatus from tempdb.dbo.tempcachestats
		return(0)
	end
	select @mda_status = MdaStatus from tempdb.dbo.tempcachestats

	if not exists(select 1 from tempdb.dbo.sysobjects where
					name = 'tempbufpoolstats')
	begin
		raiserror 17733, 'tempdb..tempbufpoolstats'
		return (1)
	end
				
	if not exists(select 1 from tempdb.dbo.sysobjects where
					name = 'tempobjstats')
	begin
		raiserror 17733, 'tempdb..tempobjstats'
		return (1)
	end
				
	if not exists(select 1 from tempdb.dbo.sysobjects where
					name = 'tempcachedobjstats')
	begin
		raiserror 17733, 'tempdb..tempcachedobjstats'
		return (1)
	end
				
	/* Store the snapshot with time stamp for MDA tables */
	insert	into tempdb.dbo.tempcachestats
	select	@snapshot_time as "InsertTime",
		@mda_status as "MdaStatus",
		CacheID, RelaxedReplacement,
		PhysicalReads, LogicalReads, CachePartitions, CacheName
	from	master.dbo.monDataCache

	insert	into tempdb.dbo.tempbufpoolstats
	select 	@snapshot_time as "InsertTime",
		CacheID, IOBufferSize,
		AllocatedKB, PagesTouched, PhysicalReads,
		CacheName
	from	master.dbo.monCachePool

	insert	into tempdb.dbo.tempobjstats
	select	@snapshot_time as "InsertTime",
		LogicalReads, PhysicalReads,
		DBID, ObjectID, IndexID
	from	master.dbo.monOpenObjectActivity

	insert	into tempdb.dbo.tempcachedobjstats
	select 	@snapshot_time as "InsertTime",
		CachedKB, CacheName, DBID,
		ObjectID, IndexID
	from	master.dbo.monCachedObject
end
return 0
go
go
exec sp_procxmode 'sp_sysmon_collect_mda', 'anymode'
go
grant execute on sp_sysmon_collect_mda to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sysmon_analyze_mda')
begin
	drop procedure sp_sysmon_analyze_mda
end
go
print "Installing sp_sysmon_analyze_mda"
go


use sybsystemprocs
go

if exists(select 1 from sybsystemprocs.dbo.sysobjects where 
		sysstat & 7 = 4 and name = 'sp_sysmon_analyze_mda')
begin
	drop procedure sp_sysmon_analyze_mda
end
go

/*
** This sproc will be installed as a part of installmontables and is invoked
** from sp_sysom
**
**	Messages for sp_sysmon_analyze_mda
**
** 18291, "The parameter value '%1!' is invalid."
*/

create procedure sp_sysmon_analyze_mda
	@seconds int,
	@Reco char(1),
	@section char(80),
	@top_n	varchar(14),
	@filter varchar(255)
as

/* ----------- declare local variables ---------- */
declare @status		int		/* hold sproc status codes */
declare @top_n_substr varchar(13)	/* temporary sub string */
declare @first_char	char(1)		/* first character in 'top_n' */

select @top_n_substr = substring(@top_n, 2, datalength(@top_n) -1)
select @first_char = substring(@top_n, 1, 1)

/*
** There should be no non-numerals in the sub string consisting of
** the input except the first character. First character must be a
** numberal or a negative sign
*/
if ((patindex("%[^0-9]%", @top_n_substr) > 0) or 
		(patindex("[-0-9]", @first_char) = 0))
begin
	/*
	** 18291, "The parameter value '%1!' is invalid."
	*/
	raiserror 18291, @top_n
	return 1
end

if @section = "cache wizard"
begin
	exec @status = sp_sysmon_dcachestats @top_n, @filter, @seconds, @Reco
	return @status
end
return 0
go
go
exec sp_procxmode 'sp_sysmon_analyze_mda', 'anymode'
go
grant execute on sp_sysmon_analyze_mda to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_crt_mon_config')
begin
	drop procedure sp_monitor_crt_mon_config
end
go
print "Installing sp_monitor_crt_mon_config"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_getcfgval')
begin
	drop procedure sp_monitor_getcfgval
end
go
print "Installing sp_monitor_getcfgval"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_getcfgnum')
begin
	drop procedure sp_monitor_getcfgnum
end
go
print "Installing sp_monitor_getcfgnum"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_verify_setup')
begin
	drop procedure sp_monitor_verify_setup
end
go
print "Installing sp_monitor_verify_setup"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_verify_cfgval')
begin
	drop procedure sp_monitor_verify_cfgval
end
go
print "Installing sp_monitor_verify_cfgval"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:41 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_utils [Total 5]
**
** 18307, "Server name '%1!' does not exist in sysservers."
** 19122, "%1! is not installed. Please run '%2!' script with appropriate role %3!"
** 19261, "Executing option '%1!' '%2!' requires the '%3!' '%4!' option to be executed first."
** 19262, "%1!' '%2!' requires the parameter '%3!' to be set to at least '%4!' bytes. Set the configuration parameter to '%5!' bytes and restart Adaptive Server"
** 19480, "%1! '%2!' requires the parameter '%3!' to be set, for example, to %4!. Set the configuration parameter using: %5!."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_utils [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go
-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc sp_monitor_crt_mon_config
go

/* Drop this control table if it exists, so that the sproc can be recreated */
if exists(select 1 from tempdb.dbo.sysobjects
	  where name = 'mon_config'
	    and uid = 1)
begin
	drop table tempdb.dbo.mon_config
end
go

/*
** sp_monitor_crt_mon_config
**
**	Utility procedure to [re-]create control table, mon_config in tempdb.
**	Caller can optionally ask for table to be dropped and then recreate it.
**	If not, and if table already exists, we leave it alone. Else, create
**	a new one.
**
** Parameters:
**	@do_drop	- Boolean; whether to drop table and then create it.
**	@callerID	- To trace who is calling us. (Debugging hook)
**
** Returns:
**	@@error code from drop/create work, if any.
{
*/
create procedure sp_monitor_crt_mon_config(
				  @do_drop	int 		= 0
				, @callerID	varchar(30) 	= NULL
)
as
begin
	declare @retval	int

	if (@callerID IS NOT NULL)
		print "Calling sp_monitor_crt_mon_config from %1!",
			@callerID
	if (@do_drop = 1)
	begin
		if exists(select 1 from tempdb.dbo.sysobjects
			  where name = 'mon_config'
			    and uid = 1)
		begin
			drop table tempdb.dbo.mon_config
			if (@@error != 0)
				return @@error
		end
	end
	else if exists(select 1 from tempdb.dbo.sysobjects
			  where name = 'mon_config'
			    and uid = 1)
	begin
		return 0
	end

	select    monitor = convert(varchar(30) NULL, "")
		, confignum = config
		, configval = value
		, configname = name
		, enabled = getdate()
		, sqlstmt = convert(varchar(1096) NULL, '')
		, sqlseqno = convert(tinyint NULL, 0)
	into tempdb.dbo.mon_config lock allpages
	from master.dbo.sysconfigures
	where 1 = 0

	select @retval = @@error
	if (@retval != 0)
		return @retval

	-- This index will avoid inserting duplicate rows into the control
	-- table when [e.g.] "sp_monitor enable, procedure" is performed
	-- repeatedly without an intermediate 'disable' command.
	--
	create unique clustered index mon_config_clustind
	on tempdb.dbo.mon_config(monitor, confignum)
	with ignore_dup_key
	if (@@error != 0)
		return @@error

	-- Insert into newly created control table a row to track tracing status
	-- whose status is inititally OFF.
	--
	insert tempdb.dbo.mon_config(monitor, confignum, configval, configname,
				     enabled)
	values ('tracing', 0, 0, 'sp_monitor trace level', getdate())

	return @@error

end	-- }
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_getcfgval"
go

/*
** This stored procedure provides the ability to get the configuration parameter
** value given the name of the configuration parameter.
**
** Parameters:
**      @cfgname	- configuration parameter name.
**	@value		- Output parameter
**	@type		- type of config value ('static', 'dynamic')
**
** Returns:
**	config value for the configuration parameter.
**	If 'static' is requested, the value from sysconfigures i
**	returned. If 'dynamic' is requested, the value from
**	syscurconfigs is returned. The caller has to choose which
**	value it wants returned, for validation.
{
*/

create procedure sp_monitor_getcfgval(
			  @cfgname	varchar(100)
			, @value 	int output
			, @type		varchar(10) = 'dynamic'
) as
begin
	declare @run_value	int
	      , @cfg_value	int

	select @cfg_value = co.value 
	     , @run_value = cu.value
	from master.dbo.sysconfigures co
	   , master.dbo.syscurconfigs cu
	where co.name = @cfgname
	  and co.config = cu.config

	-- By default, return static configured value, unless
	-- user has asked for run-value.
	--
	select @value = case @type
				when 'dynamic' then @cfg_value
				else @run_value
			end

	return(0)
end	-- }
go


-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_getcfgnum"
go

/*
** This stored procedure provides the ability to get the configuration number
** for the given configuration parameter.
**
** Parameters:
**      @cfgname	- configuration parameter name.
**
** Returns:
**	config option number for the configuration parameter.
*/
create procedure sp_monitor_getcfgnum @cfgname	varchar(100),
@option_num int output
as

select @option_num = config from master.dbo.sysconfigures
where name = @cfgname

return(0)
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_verify_setup"
go

/*
** This stored procedure verifies if everything is kosher to run the monitoring
** stored procedure. If any of the parameters are not satisfied, 
** an error is raised. If a particular monitoring type is being done (e.g.
** 'deadlock') then the appropriate configuration option setting up stuff
** like pipe buffers will be checked, and an error will be reported if the
** right configuration is missing.
**
** This routine does double-duty as both a verify-and-fail sproc, as well as
** as a verify-and-return-value sproc. The latter mode is used by the 'list'
** command. If the verification fails, and the caller wants an error, then an
** error is raised, returning 1 for failure. If the caller does not want an
** error, then the config item that is not properly statically configured
** is returned to the caller.
**
** Parameters:
**	@montype	- Type of entity being monitored whose setup
**			  and required cfg options' value is validated.
**	@raiserror	- Boolean to control whether to raise errors, or to
**			  only execute this code to collect and return config
**			  numnber (i.e. caller is in verify mode).
**
** Returns:
**	0 in case of sucess.
**	1 in case of failure, and caller is ok with raising an error.
**	Config num, in case of failure, and caller only wants to verify.
{
*/
create procedure sp_monitor_verify_setup(
				  @montype 	varchar(30) = NULL
				, @raiserror	int	= 1

) as
begin
declare @cfg_value	int
      , @cfg_item	varchar(100)
      , @cfg_cmd	varchar(100)
      , @cfg_num	int		-- matching cfg_item
      , @procval 	int

if (@raiserror = 1)
begin
	/*
	** Indicate that there is a problem if some of the key monitoring tables
	** are absent.
	*/
	if not exists (select 1 from  master.dbo.sysobjects
		       where name IN (  'monSysStatement'
				      , 'monProcessSQLText'
				      , 'monProcessActivity'
				      , 'monDeadLock'
				      ) )
	begin
		raiserror 19122, "MDA", "installmaster", "(mon_role)"
		return(1)
	end
end

-- In the following section, we check for individual config options that
-- need a value-setting (not boolean) for the particular type of monitoring
-- to be enabled. If the config option is NOT set to some non-zero value,
-- raise an error.
--
if (@montype IN ('connection', 'statement') )
begin
	select @cfg_item = "max SQL text monitored"

	exec sp_monitor_getcfgval @cfg_item, @cfg_value output, 'static'

	if (@cfg_value = 0)
	begin
		if (@raiserror = 1)
		begin
       			raiserror 19262, "sp_monitor", @montype,
					@cfg_item, "1024", "1024"
			return 1
		end

		exec sp_monitor_getcfgnum @cfg_item, @cfg_num output
        	return (@cfg_num)
	end
end

else if (@montype IN ('procedure'))
begin
	select @cfg_item = "statement pipe max messages"

	exec sp_monitor_getcfgval @cfg_item, @cfg_value output

	if (@cfg_value = 0)
	begin
		if (@raiserror = 1)
		begin
			select @cfg_value = 1024
			select @cfg_cmd  = "sp_configure '"
					 + @cfg_item + "', "
					 + convert(varchar, @cfg_value)
			raiserror 19480, "sp_monitor", @montype, @cfg_item
				, @cfg_value, @cfg_cmd
			return 1
		end

		exec sp_monitor_getcfgnum @cfg_item, @cfg_num output
        	return (@cfg_num)
	end
end

else if (@montype IN ('deadlock'))
begin
	select @cfg_item = "deadlock pipe max messages"

	exec sp_monitor_getcfgval @cfg_item, @cfg_value output

	if (@cfg_value = 0)
	begin
		if (@raiserror = 1)
		begin
			select @cfg_value = 200
			select @cfg_cmd  = "sp_configure '"
					 + @cfg_item + "', "
					 + convert(varchar, @cfg_value)
			raiserror 19480, "sp_monitor", @montype, @cfg_item
				, @cfg_value, @cfg_cmd
			return 1
		end

		exec sp_monitor_getcfgnum @cfg_item, @cfg_num output
        	return (@cfg_num)
	end
end

return(0)
end	-- }
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_verify_cfgval"
go

/*
** sp_monitor_verify_cfgval
**
** 	This stored procedure verifies if all the configuration parameters are 
** 	setup correctly as part of sp_monitor_enable
**
**	sp_monitor supports the following types of entities/objects/events.
**	Each type requires different types of configuration options to be
**	enabled. Otherwise, a SELECT from the appropriate monitor table will
**	fail with an error message.
**
**	The following table summarizes each type of monitoring, the tables it
**	selects from, and the configuration options needed.
**
**	All monitoring activity needs 'enable monitoring' turned ON.
**
** ============================================================================ 
** Type         | Monitoring Table         | Config option needed
**              |                          | o The *'ed ones are values, which
**              |                          |   means the user has to separately
**		| 			   |   configure a value for this
**		| 			   |   option. sp_monitor does not
**		| 			   |   support this config option.
**		| 			   | o The +'ed options means they are
**		| 			   |   static options.
** ============================================================================ 
** connection   | monProcessSQLText        | max SQL text monitored* +
**              |                          | SQL batch capture
**              |--------------------------------------------------------------
**              | monProcessActivity       | wait event timing
**              |                          | per object statistics active
** -------------+--------------------------------------------------------------
** statement    | monProcessSQLText        | max SQL text monitored* +
**              |                          | SQL batch capture
**              |--------------------------------------------------------------
**              | monProcessStatement      | statement statistics active
**              |                          | per object statistics active
**              |                          | wait event timing
** -------------+--------------------------------------------------------------
** event        | monProcessWaits          | wait event timing
**              |                          | process wait events
**              |--------------------------------------------------------------
**              | monWaitEventInfo         | (None)
** -------------+--------------------------------------------------------------
** procedure    | monSysStatement          | statement statistics active
**              |                          | per object statistics active
**              |                          | statement pipe max messages*
**              |                          | statement pipe active
** -------------+--------------------------------------------------------------
** deadlock     | monDeadLock              | deadlock pipe max messages*
**              |                          | deadlock pipe active
** -------------+--------------------------------------------------------------
** procstack    | monProcessProcedures     | (None)
** -------------+--------------------------------------------------------------
** To be implemented monitoring types:
** ----------------------------------------------------------------------------
** indexusage   | monOpenObjectActivity    | per object statistics active
**              |--------------------------------------------------------------
**              | monOpenPartitionActivity | per object statistics active
** ============================================================================ 
**
**	This procedure verifies that the required configuration is turned ON
**	for the type of monitoring being 'enabled'.
**
** NOTE:	**** MAINTENANCE NIGHTMARE ****
**
**	If ever we were to add additional config items as required for some
**	of these named monitoring types, OR, if we introduce a new class of
**	monitoring entity, remember to update the code in monitor_list for
**	the sproc sp_monitor_list. Towards the bottom of that sproc, we
**	essentially hard-code this mapping of config items that could be
**	required for one or more monitoring types.
**
** NOTE:	**** END MAINTENANCE NIGHTMARE ****
**
** Parameters:
**	@montype	- Monitoring type (from above).
**
** Returns:
**	0 in case of sucess, 1 in the case of failure.
**	1 in the case of failure.
{
*/
go

create procedure sp_monitor_verify_cfgval(
			  @montype 	varchar(10)
			, @raiserror	int	= 1
) as
begin

/* Config param values required so support this sproc */
declare @per_obj_stat int
declare @enable_monitoring int
declare @sql_batch_capture int
declare @wait_event_timing int
declare @process_wait_events int
declare @stmt_pipe_maxmsg int
declare @stmt_pipe_active int
declare @stmt_stat_active int
      , @deadlock_pipe_max_msgs	int
      , @deadlock_pipe_active	int
      , @retval			int	-- return code from sproc.


/* Names of the configuration parameters */
declare @enable_monitoring_cfg		varchar(100)
declare @sql_batch_capture_cfg		varchar(100)
declare @per_obj_stat_cfg		varchar(100)
declare @wait_event_cfg			varchar(100)
declare @process_wait_events_cfg	varchar(100)
declare @stmt_pipe_maxmsg_cfg		varchar(100)
declare @stmt_pipe_active_cfg		varchar(100)
declare @stmt_stat_active_cfg		varchar(100)
      , @deadlock_pipe_max_msgs_cfg	varchar(100)
      , @deadlock_pipe_active_cfg	varchar(100)


/* Note down the configuration parameters of interest */
select @enable_monitoring_cfg		= "enable monitoring"
     , @sql_batch_capture_cfg		= "SQL batch capture"
     , @per_obj_stat_cfg		= "per object statistics active"
     , @wait_event_cfg			= "wait event timing"
     , @process_wait_events_cfg		= "process wait events"
     , @stmt_pipe_active_cfg		= "statement pipe active"
     , @stmt_pipe_maxmsg_cfg		= "statement pipe max messages"
     , @stmt_stat_active_cfg		= "statement statistics active"
     , @deadlock_pipe_active_cfg	= "deadlock pipe active"


-- Assume there are no errors till we find otherwise.
select @retval = 0

-- We only want to do this if this sproc is being called from run-time
-- when enable is being done, or if actual monitoring is being done.
-- If caller is simply executing verification or 'list' mode, no need
-- to further validate whether 'enable monitoring'is ON, or not. (It would
-- be ON, if some monitoring type was already enabled, anyway.)
--
if (@raiserror = 1)
begin
	exec sp_monitor_getcfgval @enable_monitoring_cfg,
			@enable_monitoring output

	/* Verify if the 'enable monitoring' option is on */
	select @retval = case @enable_monitoring when 1 then 0 else 1 end
end

/*
** Note that setup-type configuration (where memory has to be allocated for
** stuff like, e.g., 'max SQL text monitored') has already been checked for
** in sp_monitor_verify_setup sproc. Here we only check for on/off settings.
** Check for config options depending on the type of monitoring.
*/
if (@montype = 'connection')
begin
	exec sp_monitor_getcfgval @sql_batch_capture_cfg
				, @sql_batch_capture output

	exec sp_monitor_getcfgval @wait_event_cfg
				, @wait_event_timing output

	exec sp_monitor_getcfgval @per_obj_stat_cfg
				, @per_obj_stat output

	if (   (@sql_batch_capture = 0)
	    or (@wait_event_timing = 0)
	    or (@per_obj_stat = 0)
	   )
	begin
		select @retval = 1
	end
end

else if (@montype = 'statement')
begin
	exec sp_monitor_getcfgval @sql_batch_capture_cfg
				, @sql_batch_capture output

	exec sp_monitor_getcfgval @stmt_stat_active_cfg
				, @stmt_stat_active output

	exec sp_monitor_getcfgval @per_obj_stat_cfg
				, @per_obj_stat output

	exec sp_monitor_getcfgval @wait_event_cfg
				, @wait_event_timing output

	if (   (@sql_batch_capture = 0)
	    or (@stmt_stat_active = 0)
	    or (@per_obj_stat = 0)
	    or (@wait_event_timing = 0)
	  )
	begin
		select @retval = 1
	end
end

else if (@montype = 'event')
begin
	exec sp_monitor_getcfgval @wait_event_cfg
				, @wait_event_timing output

	exec sp_monitor_getcfgval @process_wait_events_cfg
				, @process_wait_events output

	if (   (@wait_event_timing = 0)
	    or (@process_wait_events = 0)
	  )
	begin
		select @retval = 1
	end
end

else if (@montype = 'procedure')
begin
	exec sp_monitor_getcfgval @stmt_stat_active_cfg
				, @stmt_stat_active output

	exec sp_monitor_getcfgval @per_obj_stat_cfg
				, @per_obj_stat output

	exec sp_monitor_getcfgval @stmt_pipe_active_cfg
				, @stmt_pipe_active output

	if (   (@stmt_stat_active = 0)
	    or (@per_obj_stat = 0)
	    or (@stmt_pipe_active = 0)
	  )
	begin
		select @retval = 1
	end
end

else if (@montype = 'deadlock')
begin
	exec sp_monitor_getcfgval @deadlock_pipe_active_cfg
				, @deadlock_pipe_active output

	if (   (@deadlock_pipe_active = 0)
	  )
	begin
		select @retval = 1
	end
end

if ((@retval = 1) and (@raiserror = 1))
begin
	-- Build a string like 'enable, <montype> monitoring', so that
	-- it can be passed as 2nd arg to error message.
	-- (Reuse variable, to save space.)
	select @enable_monitoring_cfg = "'enable', '"
				      + @montype
				      + " monitoring'"

        raiserror 19261, "sp_monitor", @montype, "sp_monitor"
			, @enable_monitoring_cfg
end

return @retval
end	-- }
go

go
exec sp_procxmode 'sp_monitor_crt_mon_config', 'anymode'
go
grant execute on sp_monitor_crt_mon_config to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_getcfgval', 'anymode'
go
grant execute on sp_monitor_getcfgval to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_getcfgnum', 'anymode'
go
grant execute on sp_monitor_getcfgnum to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_verify_setup', 'anymode'
go
grant execute on sp_monitor_verify_setup to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_verify_cfgval', 'anymode'
go
grant execute on sp_monitor_verify_cfgval to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_enable_usage')
begin
	drop procedure sp_monitor_enable_usage
end
go
print "Installing sp_monitor_enable_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_enable')
begin
	drop procedure sp_monitor_enable
end
go
print "Installing sp_monitor_enable"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:39 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_enable [Total 1]
**
** 19260, "Invalid argument or unsupported command. Use sp_monitor 'help' to get usage information."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_enable [Total 2]
**
** 19270, "Usage: sp_monitor [ enable ]"
** 19271, "Examples: sp_monitor 'enable'"
*/
/*
** End spgenmsgs.pl output.
*/
go

exec sp_dbxt_recreate_proc "sp_monitor_enable_usage"
go

/*
** sp_monitor_enable_usage
**
**	Generate help/usage information in terse/verbose mode.
{
*/
create procedure sp_monitor_enable_usage(
				  @output_type		varchar(10)
				, @valid_type_names	varchar(256)
) as
begin
	declare @sqlmsg	varchar(256)

	print " "
	-- First generate terse messages.
	exec sp_getmessage 19270, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19271, @sqlmsg output	
	print @sqlmsg

	if (@output_type = 'terse')
	begin
		return 0
	end

	print " "
	print "  -- Enable monitoring for a specific type, to monitor statements."
	print "	sp_monitor enable, statement"
	print "	sp_monitor enable, 'statement monitoring'"
	
	print " "
	print "  -- Enable monitoring for connection monitoring"
	print "	sp_monitor enable, connection"
	print "	sp_monitor enable, 'connection monitoring'"

	print " "
	print "  -- Enable monitoring for all types"
	print "	sp_monitor enable"
	print "	sp_monitor enable, 'all'"
	print "	sp_monitor enable, 'all monitoring'"

	return 0

end	-- }
go

if (@@error != 0) select syb_quit()
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_enable"
go

/* Drop and recreate the control table used by sp_monitor */
declare @retval int
exec @retval = sp_monitor_crt_mon_config @do_drop = 1
if (@retval != 0)
	select syb_quit()
go

/*
** This stored procedure is a subordinate stored procedure that is invoked from
** the parent stored procedure sp_monitor when "enable" is passed as the 
** argument. This stored procedure provides a way to enable the configuration
** parameters relevant to monitoring
**
** sp_monitor "enable" should be run before any of the sp_monitor options are
** run. This ensures that all the configuration options required for all options
** are turned on. A table where we cache the monitoring cfg options is dropped
** and recreated.
**
** Alternately, issue: "sp_monitor enable, <monitoring type>" to only monitor
** certain types of entities. This way, users can do localized monitoring
** without turning ON every monitoring [sub-]configuration option. When
** individual items are enabled, only the cfg rows appropriate for that entity
** will be turned ON.
**
** Obtain the configuration parameter required for running sp_monitor
** commands and insert them into a table. This is needed for auto-tuning
** sp_monitor so that the user does not need to know the underlying config
** parameters that need to be tuned for the different sp_monitor options.
** Here, we turn ON only those config options that are a switch. Config
** options (such as 'statement pipe max messages') should be configured
** explicitly by the user.
**
** This sproc supports an 'all' mode, and an individual monitor type mode.
** As we do repeatedly the same SQL for both types, we use execute immediate
** where we build SQL fragments and invoke them.
**
** There is a 3-part logic here that is being implemented to control ths
** per-monitoring type tracking of config options:
**
**  1. 	First check if the required rows for the config options needed for
**	the monitoring type being enabled are already in the table. This is
**	where the IF NOT EXISTS SQL fragment below comes in. If we didn't do
**	this check, an attempt to insert duplicate rows _would_ be prevented
**	by the index defined as ignore_dup_key, but that creates a noise
**	message to the screen that "duplicate rows were ignored".
**
**  2.	Then INSERT new rows into the control table, setting -1 for the
**	'configval' column for each row. -1 means that we don't know the
**	setting of the config option just prior to calling this 'enable'
**	command.
**
**  3.	Then, go back and UPDATE the newly inserted row the specified
**	monitoring type. Set the configval to the min value  of the config
**	option before the rows were inserted for this monitoring type. (See
**	below.) Here we only update newly inserted rows, identified by the
**	configval being -1.
**
** Parameters:
**      @montype	- Type of monitoring being enabled.
**
** Returns:
**      0       - upon sucessful completion
**      1       - If an error resulted.
{
*/
go

create procedure sp_monitor_enable (@montype varchar(30) = NULL
) as
begin

/* Values of the configuration parameters */
declare @stmt_pipe_maxmsg int

/* Names of the configuration parameters */
declare @stmt_pipe_maxmsg_cfg char(100)

/* Configuration option numbers for the configuration parameters */
declare @stmt_pipe_maxmsg_cfg_num int

/* Misc declarations */
declare @rtnstatus int
declare @val int
      , @turn_all_on	tinyint

-- Generated fragments of SQL that will be executed to turn ON options.
declare @inlist_str	varchar(400)
      , @inlist_initial	varchar(30)
      , @sqlstmt	varchar(1024)
      , @notexists_sql	varchar(128)
      , @insert_stmt	varchar(128)
      , @rest_of_select	varchar(80)
      , @value_zero	varchar(20)
      , @updstmt	varchar(400)
      , @lcl_montype	varchar(30)
      , @found_montype	tinyint		-- validate monitoring type arg.
      , @char_index	int
      , @retval		int
      , @nrowsaffected	int

      -- Names for individual configuration options.
      , @enable_monitoring	varchar(30)
      , @sql_batch_capture	varchar(30)
      , @stmt_stats_active	varchar(30)
      , @stmt_pipe_active	varchar(30)
      , @perobj_stats_active	varchar(30)
      , @wait_event_timing	varchar(30)
      , @process_wait_events	varchar(30)
      , @deadlock_pipe_active	varchar(30)
      , @whoami		varchar(30)

select @whoami = object_name(@@procid, db_id('sybsystemprocs'))
exec @rtnstatus = sp_monitor_check_permission @whoami
if (@rtnstatus != 0)
	return(@rtnstatus)

exec @rtnstatus = sp_monitor_verify_setup
if (@rtnstatus != 0)
	return(@rtnstatus)

-- Initialize names for individual config options that we might use.
select @enable_monitoring	= "'enable monitoring'"
     , @sql_batch_capture	= "'SQL batch capture'"
     , @stmt_stats_active	= "'statement statistics active'"
     , @stmt_pipe_active	= "'statement pipe active'"
     , @perobj_stats_active	= "'per object statistics active'"
     , @wait_event_timing	= "'wait event timing'"
     , @process_wait_events	= "'process wait events'"
     , @deadlock_pipe_active	= "'deadlock pipe active'"

     , @turn_all_on		= 0
     , @found_montype		= 0

-- User might have entered: sp_monitor enable, 'procstack monitoring'
-- If so, strip out the term 'monitoring', and get the base monitoring type
-- which would be one of terms like 'all', 'connection', 'procstack' etc.
--
if (@montype LIKE "% monitoring")
begin
	-- Locate start of ' monitoring' phrase.
	select @char_index = charindex(' ', @montype)

	-- We could raise an error in the else case, but it's of no use.
	-- If the monitoring type is wrong, you get an error later on.
	if (@char_index > 0)
	begin
		select @montype = ltrim(rtrim(substring(@montype, 1,
							 (@char_index-1)) ) )
	end
end

-- Re-enabling 'all' means user is starting a new monitoring window. Drop and
-- re-create the control table, to re-capture the state of the config options.
--
if (@montype IS NULL) or (@montype = "all")
begin
	if exists (select 1 from tempdb.dbo.sysobjects 
		   where name = "mon_config" and uid = 1)
	begin
		print "Drop and recreate control table '%1!'"
			, "tempdb.dbo.mon_config"
		drop table tempdb.dbo.mon_config
	end
	select @turn_all_on 	= 1
	     , @found_montype	= 1
end

-- Create the table if it does not exist (dropped above), or if the user
-- is runnning 'enable' the 1st time on a monitor type (in which case the
-- table would not have been created earlier).
--
if (object_id('tempdb.dbo.mon_config') IS NULL)
begin
	exec @retval = sp_monitor_crt_mon_config
	if (@retval != 0)
		return @retval
end

select @insert_stmt = " INSERT INTO tempdb.dbo.mon_config"
		    + "(monitor, confignum, configval, configname, enabled)"
     , @value_zero = " AND value = 0"

     -- Insert a value of -1 for 'configval' as it will be updated later.
     -- See below.
     --
     , @rest_of_select  = ", config, -1, name, getdate()"
     			+ " FROM master.dbo.sysconfigures WHERE name IN "

     -- NOT EXISTS clause sql substring, to which we will append later on the
     -- IN-list that we are looking for before we insert any new rows.
     --
     , @notexists_sql = "IF NOT EXISTS (SELECT 1 FROM tempdb.dbo.mon_config"
     		      + " WHERE configname IN "

/*
** This is an UPDATE statement to register in the control table the value
** of the configuration option *BEFORE* the sp_monitor enable was ever
** started. We are trying to note down what the original config setting was
** prior to a config option being turned ON for some monitoring type. 
**
** o If this is the 1st row being inserted for a configuration option, save
**   the current run value from syscurconfigs for this config option.
**
** o If this is a row being inserted for a config option, and another row
**   already exists, then save off the min(configval) value, which will give
**   us the value of the config option *before* the first row was inserted.
**
** o ONLY do the update if the row is (are) newly inserted; i.e. configval =
**    -1. This way we avoid doing needless updates of the same rows if the
**   'enable' was run on the same monitoring type repeatedly.
**
** We do the UPDATE via execute immediate as it is the same exact SQL
** fragment that we want to run for each monitoring type, *except* that the
** WHERE clause will change for each monitoring type. Hence, build a common
** SQL frament and then attach the WHERE clause.
*/
select @updstmt =
	  "UPDATE tempdb.dbo.mon_config "
	+ " SET configval = (SELECT ISNULL(MIN(configval)"
	+				", (SELECT cu.value"
	+				"   FROM master.dbo.syscurconfigs cu"

	+                               "   WHERE cu.config = o.confignum) )"
	
	+		 " FROM tempdb.dbo.mon_config i"
	+		 " WHERE i.configval != -1"
	+		 "  AND i.confignum = o.confignum)"
	+ " FROM tempdb.dbo.mon_config o"
	+ " WHERE o.configval = -1"

select @inlist_initial = "(" + @enable_monitoring

/*
** Here we continually build an IN-list string, for various configuration
** options that would be needed if a particular type of monitoring is being
** enabled. In the 'all' case, we might end up generating duplicate config
** options in the IN-list, but that's not a problem as the WHERE clause
** will only essentially consider one instance.
*/
if (@montype = 'connection') or (@turn_all_on = 1)
begin
	select @inlist_str = @inlist_initial
			   + "," + @sql_batch_capture
			   + "," + @wait_event_timing
			   + "," + @perobj_stats_active
			   + ")"
	     , @lcl_montype = "connection"
	     , @found_montype = 1

	-- Do not include the @value_zero clause here as we want to INSERT
	-- all the config options that are required for this monitoring type
	-- into the control table. If we insert only the ones that are
	-- currently zero, it might be that some of the config options that
	-- are shared between different monitoring types are already ON, and
	-- so don't get tracked under this monitoring type in the control
	-- table. This means if this monitoring type is subsequently disabled,
	-- we don't have all the data needed to turn OFF all the required
	-- config options; some will be left ON (which is inconsistent with
	-- the defined semantic of disable turning OFF all related items).
	--
	select @sqlstmt = @notexists_sql
			+ @inlist_str
			+ " AND monitor = '" + @lcl_montype + "'"
			+ ")"
			+ @insert_stmt
			+ " SELECT " + "'" + @lcl_montype + "'"
			+ @rest_of_select
			+ @inlist_str
			-- + @value_zero

	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus

	select @sqlstmt = @updstmt
			+ " AND monitor = '" + @lcl_montype + "'"
	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
					, @nrowsaffected output
	if (@rtnstatus != 0)
		return @rtnstatus
end

if (@montype = 'statement') or (@turn_all_on = 1)
begin
	select @inlist_str = @inlist_initial
			   + "," + @sql_batch_capture
			   + "," + @stmt_stats_active
			   + "," + @perobj_stats_active
			   + "," + @wait_event_timing
			   + ")"
	     , @lcl_montype = "statement"
	     , @found_montype = 1

	select @sqlstmt = @notexists_sql
			+ @inlist_str
			+ " AND monitor = '" + @lcl_montype + "'"
			+ ")"
			+ @insert_stmt
			+ " SELECT " + "'" + @lcl_montype + "'"
			+ @rest_of_select
			+ @inlist_str

	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus

	select @sqlstmt = @updstmt
			+ " AND monitor = '" + @lcl_montype + "'"
	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus
end

if (@montype = 'event') or (@turn_all_on = 1)
begin
	select @inlist_str = @inlist_initial
			   + "," + @wait_event_timing
			   + "," + @process_wait_events
			   + ")"
	     , @lcl_montype = "event"
	     , @found_montype = 1

	select @sqlstmt = @notexists_sql
			+ @inlist_str
			+ " AND monitor = '" + @lcl_montype + "'"
			+ ")"
			+ @insert_stmt
			+ " SELECT " + "'" + @lcl_montype + "'"
			+ @rest_of_select
			+ @inlist_str

	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus

	select @sqlstmt = @updstmt
			+ " AND monitor = '" + @lcl_montype + "'"
	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus
end

if (@montype = 'procedure') or (@turn_all_on = 1)
begin
	select @inlist_str = @inlist_initial
			   + "," + @stmt_stats_active
			   + "," + @perobj_stats_active
			   + "," + @stmt_pipe_active
			   + ")"
	     , @lcl_montype = "procedure"
	     , @found_montype = 1

	select @sqlstmt = @notexists_sql
			+ @inlist_str
			+ " AND monitor = '" + @lcl_montype + "'"
			+ ")"
			+ @insert_stmt
			+ " SELECT " + "'" + @lcl_montype + "'"
			+ @rest_of_select
			+ @inlist_str

	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus

	select @sqlstmt = @updstmt
			+ " AND monitor = '" + @lcl_montype + "'"
	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus
end

if (@montype = 'deadlock') or (@turn_all_on = 1)
begin
	select @inlist_str = @inlist_initial
			   + "," + @deadlock_pipe_active
			   + ")"
	     , @lcl_montype = "deadlock"
	     , @found_montype = 1

	select @sqlstmt = @notexists_sql
			+ @inlist_str
			+ " AND monitor = '" + @lcl_montype + "'"
			+ ")"
			+ @insert_stmt
			+ " SELECT " + "'" + @lcl_montype + "'"
			+ @rest_of_select
			+ @inlist_str

	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus

	select @sqlstmt = @updstmt
			+ " AND monitor = '" + @lcl_montype + "'"
	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus
end

if (@montype = 'procstack') or (@turn_all_on = 1)
begin
	-- Procedure stack monitoring does not need any additional
	-- config options to be turned ON. It selects from a table that is
	-- always around.

	select @inlist_str = @inlist_initial
			   + ")"
	     , @lcl_montype = "procstack"
	     , @found_montype = 1

	select @sqlstmt = @notexists_sql
			+ @inlist_str
			+ " AND monitor = '" + @lcl_montype + "'"
			+ ")"
			+ @insert_stmt
			+ " SELECT " + "'" + @lcl_montype + "'"
			+ @rest_of_select
			+ @inlist_str

	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus

	select @sqlstmt = @updstmt
			+ " AND monitor = '" + @lcl_montype + "'"
	exec @rtnstatus = sp_exec_SQL @sqlstmt, @lcl_montype
	if (@rtnstatus != 0)
		return @rtnstatus
end

-- This means user asked to enable a monitoring type that is invalid.
-- Raise an error and bail.
if (@found_montype = 0)
begin
	raiserror 19260, "sp_monitor 'help', 'enable'"
	return 1
end

--
-- Enable the configuration parameters that have not already been turned
-- ON, from the ones that are relevant to the monitoring type being enabled.
-- If the user is running in 'all' mode, then turn ON all the config options
-- that are currently 0. If user is running enable for a particular monitor
-- type, turn ON only those config options that are needed for that type of
-- monitoring. In the latter case, the CASE statement below is the one that
-- selects based on an IN-list only those config options that need to be turned
-- ON.

select @sqlstmt = "declare @val int "
		+ "SELECT @val = config_admin(23, confignum, 1, 0, NULL, NULL)"
		+ " FROM tempdb.dbo.mon_config"
		+ " WHERE 1 = 1"
		+ case @turn_all_on
			when 1 then ""
			else " AND configname IN " + @inlist_str
		  end
		+ " AND configval = 0"
		+ " AND confignum > 0"	-- eliminate non-config item rows.

exec @rtnstatus = sp_exec_SQL @sqlstmt, "sp_monitor_enable-config_admin"

-- If the config_admin() built-in were to fail due to some memory configuration
-- issue, rollback the entire 'enable' command's work, by calling the disable
-- feature on the monitoring type being enabled.
--
if (@rtnstatus != 0)
begin
	-- Reuse variable to define name of sp_monitor sproc.
	select @enable_monitoring = "sybsystemprocs.dbo.sp_monitor"
	exec @enable_monitoring 'disable', @montype
	return @rtnstatus
end

/* 
** Certain configuration parameters such as 'statement pipe max messages'
** need to be tuned to some optimal values. Get the config value for 
** these options and tune them to some predefined values. Also insert them
** into the mon_config table so that as part of sp_monitor "disable", these
** values can be reset back to their original values.
*/
select @stmt_pipe_maxmsg_cfg = "statement pipe max messages"

exec sp_monitor_getcfgval @stmt_pipe_maxmsg_cfg, @stmt_pipe_maxmsg output

exec sp_monitor_getcfgnum @stmt_pipe_maxmsg_cfg, @stmt_pipe_maxmsg_cfg_num output


-- Tune the 'statement pipe max messages' option if it is not already on.
-- It's only needed for procedure monitoring, so turn it ON to some
-- pre-selected default value only in case we are enabling proceduring 
-- monitoring, or 'all' monitoring.
--
if (   (@stmt_pipe_maxmsg = 0)
    and ((@montype = 'procedure') or (@turn_all_on = 1) ) )
begin
	select @val = config_admin(23, @stmt_pipe_maxmsg_cfg_num, 100000, 0, NULL, NULL)
	insert into tempdb.dbo.mon_config(
		monitor, confignum,configval, configname, enabled)
	values('procedure',
		@stmt_pipe_maxmsg_cfg_num, 100000, @stmt_pipe_maxmsg_cfg,
		getdate())
end

select @val = mdaconfig('disable_lwp', 'begin')

return(0)
end	-- }
go
go
exec sp_procxmode 'sp_monitor_enable_usage', 'anymode'
go
grant execute on sp_monitor_enable_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_enable', 'anymode'
go
grant execute on sp_monitor_enable to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_disable_usage')
begin
	drop procedure sp_monitor_disable_usage
end
go
print "Installing sp_monitor_disable_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_disable')
begin
	drop procedure sp_monitor_disable
end
go
print "Installing sp_monitor_disable"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:39 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_disable [Total 1]
**
** 19260, "Invalid argument or unsupported command. Use sp_monitor 'help' to get usage information."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_disable [Total 4]
**
** 17778, "Option '%1!' turned off."
** 19272, "Usage: sp_monitor [ disable ]"
** 19273, "Examples: sp_monitor 'disable'"
** 19479, "Disabling monitoring type '%1!'."
*/
/*
** End spgenmsgs.pl output.
*/
go

exec sp_dbxt_recreate_proc "sp_monitor_disable_usage"
go

/*
** sp_monitor_disable_usage
**
**	Generate help/usage information in terse/verbose mode.
{
*/
create procedure sp_monitor_disable_usage(
				  @output_type		varchar(10)
				,@valid_type_names	varchar(256)
) as
begin
	declare @sqlmsg	varchar(256)

	print " "
	-- First generate terse messages.
	exec sp_getmessage 19272, @sqlmsg output	
	print @sqlmsg
	exec sp_getmessage 19273, @sqlmsg output	
	print @sqlmsg

	if (@output_type = 'terse')
	begin
		return 0
	end

	print " "
	print "  -- Disable monitoring for a specific type, here for statements."
	print "	sp_monitor disable, statement"
	
	print " "
	print "  -- Disable monitoring for deadlock events"
	print "	sp_monitor disable, deadlock"
	print "	sp_monitor disable, 'deadlock monitoring'"

	print " "
	print "  -- Disable monitoring for all types"
	print "	sp_monitor disable"
	print "	sp_monitor disable, 'all'"
	print "	sp_monitor disable, 'all monitoring'"

	return 0

end	-- }
go

/* Drop and recreate the control table used by sp_monitor */
declare @retval int
exec @retval = sp_monitor_crt_mon_config @do_drop = 1
if (@retval != 0)
	select syb_quit()
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_disable"
go

/*
** sp_monitor_disable
**
** This stored procedure is a subordinate stored procedure that is invoked from
** the parent stored procedure sp_monitor when "disable" is passed as the 
** argument. This stored procedure provides a way to disable the configuration
** parameters relevant to monitoring
**
** sp_monitor "disable" should be run once the monitoring activities using
** sp_monitor stored procedures that use monitoring tables are complete. 
** This will ensure that all the configuration parameters doing monitoring
** are turned off.
**
** Monitoring can be disabled using 'all' mode where all the config options
** related to all monitoring items are turned OFF. Optionally, individual
** config options for individual monitoring types can be selectively
** disabled. If 'all' monitoring types are disabled, the control table is then
** dropped.
**
** Parameters:
**      @montype	- Type of monitoring to be disabled.
**
** Returns:
**      0       - upon sucessful completion
**      1       - If an error resulted.
{
*/

create procedure sp_monitor_disable(@montype varchar(30) = NULL
) as
begin
declare @rtnstatus 	int
declare @val 		int
      , @char_index	int
      , @cfgnum		int
      , @cfgname	varchar(80)
      , @printmsg_cfg	varchar(80)
      , @printmsg_type	varchar(80)
      , @whoami		varchar(30)

select @whoami = object_name(@@procid, db_id('sybsystemprocs'))
exec @rtnstatus = sp_monitor_check_permission @whoami
if (@rtnstatus != 0)
	return @rtnstatus

exec @rtnstatus = sp_monitor_verify_setup
if (@rtnstatus != 0)
	return @rtnstatus

-- User might have entered: sp_monitor disable, 'procstack monitoring'
-- If so, strip out the term 'monitoring', and get the base monitoring type
-- which would be one of terms like 'all', 'connection', 'procstack' etc.
--
if (@montype LIKE "% monitoring")
begin
	-- Locate start of ' monitoring' phrase.
	select @char_index = charindex(' ', @montype)
	if (@char_index > 0)
	begin
		select @montype = ltrim(rtrim(substring(@montype, 1,
							 (@char_index-1)) ) )
	end
end

-- Validate argument for monitoring type and error out if it's invalid.
--
if (@montype IS NOT NULL) and (@montype NOT IN (  'all'
						, 'connection'
						, 'statement'
						, 'event'
						, 'procedure'
						, 'deadlock'
						, 'procstack'
					       ) )
begin
	raiserror 19260, "sp_monitor 'help', 'disable'"
	return 1
end
				
-- Silently return if there is no work to do; i.e. the control table is
-- not to be found.
--
if (object_id('tempdb.dbo.mon_config') IS NULL)
begin
	return 0
end

exec sp_getmessage 19479, @printmsg_type output
exec sp_getmessage 17778, @printmsg_cfg output

if (@montype IS NULL) or (@montype = 'all')
begin
  if (object_id('tempdb.dbo.mon_config') IS NOT NULL)
  begin
	print @printmsg_type, "all"

	-- Turn OFF monitoring for all options that you find set ON in the
	-- control table. Eliminate duplicate rows, as certain config options
	-- are common across monitoring types and will appear more than once
	-- in the control table.
	--
	select distinct confignum, configname
	into #mon_configs_on
	from tempdb.dbo.mon_config
	where configval = 0
	  and confignum > 0	-- eliminate non-config entry  rows.

	-- Report which config options are being turned OFF.
	declare mon_configs_on_cur cursor for
	select confignum, configname
	from #mon_configs_on
	for read only

	open mon_configs_on_cur
	while (1 = 1)
	begin
		fetch mon_configs_on_cur into @cfgnum, @cfgname
		if (@@sqlstatus != 0)
			break

		print @printmsg_cfg, @cfgname
	end

	close mon_configs_on_cur
	deallocate cursor mon_configs_on_cur

	select @val = config_admin(23, confignum, 0, 0, NULL, NULL)
	from #mon_configs_on

	drop table #mon_configs_on
	drop table tempdb.dbo.mon_config

	select @val = mdaconfig('disable_lwp','end')
  end
end

else
begin
	print @printmsg_type, @montype

	-- Turn OFF config options for individual monitoring items.
	-- Some of these config options are common between different monitoring
	-- types. So, if are we turning OFF, say, monitoring for 'statement',
	-- and we still want to retain monitoring for 'connection', we don't
	-- want to turn OFF the config options that are common between them.
	-- The way we handle this situation is:

	--   . Find the config options for this monitoring type that are 0.
	--     (If the option was recorded as 1, it means that when monitoring
	--      was enabled for the type being disabled, that config option
	--      was already ON, turned ON by the user using sp_configure.)

	--   . For each such option, find out if the option is ON for some
	--     other monitoring type. If so, leave it alone.

	--   . Otherwise, turn OFF this config option. This will ensure that
	--     we only affect those config options that are needed by this
	--     monitoring type and are currently unused by any other type.
	--
	declare cfg_option_cur cursor for
	select m1.confignum, m1.configname
	from tempdb.dbo.mon_config m1
	where m1.monitor = @montype
	  and not exists (select 1
	  		  from tempdb.dbo.mon_config m2
			  where m2.monitor != @montype
			    and m2.confignum = m1.confignum)

	  and (m1.configval = 0) -- cfg was not ON before monitoring started
	  and m1.confignum > 0	-- eliminate non-config entry rows.
	for read only

	open cfg_option_cur

	while (1 = 1)
	begin
		fetch cfg_option_cur into @cfgnum, @cfgname
		if (@@sqlstatus != 0)
			break

		print @printmsg_cfg, @cfgname
		select @val = config_admin(23, @cfgnum, 0, 0, NULL,NULL)
	end

	close cfg_option_cur
	deallocate cursor cfg_option_cur

	-- Delete all rows to indicate that monitoring is disabled now.
	delete tempdb.dbo.mon_config where monitor = @montype
end

return(@rtnstatus)
end	-- }
go
go
exec sp_procxmode 'sp_monitor_disable_usage', 'anymode'
go
grant execute on sp_monitor_disable_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_disable', 'anymode'
go
grant execute on sp_monitor_disable to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_trace')
begin
	drop procedure sp_monitor_trace
end
go
print "Installing sp_monitor_trace"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_trace_level')
begin
	drop procedure sp_monitor_trace_level
end
go
print "Installing sp_monitor_trace_level"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_trace [Total 1]
**
** 19060, "Procedure %1!, %2! must be a positive integer."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_trace [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

sp_dbxt_recreate_proc sp_monitor_trace
go

/*
** sp_monitor_trace
**
**	Utility procedure to update the trace level in the control table
**	in tempdb.
**
** Usage:	sp_monitor trace, '1'
** 		sp_monitor trace, '2'
{
*/
create procedure sp_monitor_trace(
			@trace_str	varchar(10)	= 'a'
) as
begin
	declare @trace	int
	      , @nrows	int

	if (@trace_str IS NULL)
		return 0

	-- If a valid integer was passed, update the trace level.
	if (patindex("%[^0-9]%", @trace_str) = 0)
	begin
		select @trace = convert(int, @trace_str)

		update tempdb.dbo.mon_config
		set configval = @trace
		where monitor = 'tracing'

		select @nrows = @@rowcount
		if (@nrows > 0)
		begin
			print "Updated trace level to %1!. (%2! row(s) affected.)"
				, @trace, @nrows
		end
	end
	else
	begin
		raiserror 19060, 'sp_monitor_trace', @trace_str
		return 1
	end

	return 0
end	-- }
go

sp_dbxt_recreate_proc sp_monitor_trace_level
go

/*
** sp_monitor_trace_level
**
**	Utility procedure to return the current trace level from the control
**	table.
{
*/
create procedure sp_monitor_trace_level
as
begin
	declare @trace	int

	select @trace = configval
	from tempdb.dbo.mon_config
	where monitor = 'tracing'

	if (@trace IS NULL)
		select @trace = 0

	return @trace
end	-- }
go
go
exec sp_procxmode 'sp_monitor_trace', 'anymode'
go
grant execute on sp_monitor_trace to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_trace_level', 'anymode'
go
grant execute on sp_monitor_trace_level to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_archive_usage')
begin
	drop procedure sp_monitor_archive_usage
end
go
print "Installing sp_monitor_archive_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_mon_gen_columnlist')
begin
	drop procedure sp_mon_gen_columnlist
end
go
print "Installing sp_mon_gen_columnlist"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_mon_archive_genSQL')
begin
	drop procedure sp_mon_archive_genSQL
end
go
print "Installing sp_mon_archive_genSQL"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_mon_archive_data')
begin
	drop procedure sp_mon_archive_data
end
go
print "Installing sp_mon_archive_data"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_mon_archive_monTable')
begin
	drop procedure sp_mon_archive_monTable
end
go
print "Installing sp_mon_archive_monTable"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_mon_archive_deadlock')
begin
	drop procedure sp_mon_archive_deadlock
end
go
print "Installing sp_mon_archive_deadlock"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_parse_archive_cmd')
begin
	drop procedure sp_monitor_parse_archive_cmd
end
go
print "Installing sp_monitor_parse_archive_cmd"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_archive')
begin
	drop procedure sp_monitor_archive
end
go
print "Installing sp_monitor_archive"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:39 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_archive [Total 8]
**
** 17284, "'%1!' is not a valid identifier."
** 17870, "Table '%1!' does not exist in database '%2!'. %3!"
** 18464, "%1! name cannot be null."
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
** 19260, "Invalid argument or unsupported command. Use sp_monitor 'help' to get usage information."
** 19491, "Archive prefix name '%1!' cannot exceed %2! bytes as this can cause the extended name of the archive table to be an invalid identifier."
** 19492, "Cannot use database '%1!' as a database to archive data as it is a '%2!' database."
** 19493, "Cannot use database '%1!' as a database to archive data as it does not have the '%2!' option set."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_archive [Total 8]
**
** 17050, "select into/bulkcopy/pllsort"
** 18954, "Usage:"
** 19261, "Executing option '%1!' '%2!' requires the '%3!' '%4!' option to be executed first."
** 19486, "Archiving is currently supported for only these monitoring types: %1!."
** 19487, "Example: Archive deadlock events to a default archive named '%1!' in the current database:"
** 19488, "Example: Archive deadlock events to an archive named '%1!%2!' in %3!:"
** 19489, "Created new archive '%1!'."
** 19490, "Archived %1! rows to archive table '%2!' with timestamp '%3!'."
*/
/*
** End spgenmsgs.pl output.
*/
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_monitor_archive_usage
go

/*
** sp_monitor_archive_usage
**
**	Generate help/usage info, in terse/verbose mode.
**
** Parameters:
**	@output_type	- 'terse' or 'verbose'
{
*/
create procedure sp_monitor_archive_usage(
			  @output_type	varchar(8)
) as
begin
	declare @usage		varchar(10)
	      , @msg		varchar(256)
	      , @prefix		varchar(6)
	      , @mondeadlock	varchar(11)
	      , @supported	varchar(30)

	select @mondeadlock	= 'monDeadLock'
	     , @prefix		= 'daily_'

	print " "
	exec sp_getmessage 18954, @usage output

	select @msg = @usage
		    + " sp_monitor 'archive [using prefix=<string>]' "
		    + "{, '<monitoring_type>' }"
	print @msg

	select @supported = "'deadlock'"
	exec sp_getmessage 19486, @msg output
	print @msg, @supported

	if (@output_type = 'terse')
		return 0

	print " "
	exec sp_getmessage 19487, @msg output
	print @msg, @mondeadlock
	print "	sp_monitor archive, deadlock"

	print " "
	select @supported = "tempdb"	-- Reuse @variable for @dbname
	exec sp_getmessage 19488, @msg output
	print @msg, @prefix, @mondeadlock, @supported
	print "	%1!..sp_monitor 'archive using prefix=%2!', deadlock"
		, @supported, @prefix
end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_mon_gen_columnlist
go

/*
** sp_mon_gen_columnlist
**
**	Generate the column list for a given [monitoring] table in an output
**	SQL buffer. This is sort-of a specialiased routine for extracting
**	data from monitoring tables. We scan syscolumns in the master db to
**	find the columns for the given monitoring table.
**
**	o For columns named '%DBID' if there is not already an equivalent
**	  %DBName column, generate the SQL for the "db_name(<column>)" fragment.
**
**	o For columns named, '%Name', generate the SQL to convert the name to
**	  varchar(255) so that the schema of the archive table is ready to be
**	  used in 15.0 also.
**
**	For these two reasons above, we cannot simply use a "SELECT *"
**	SQL fragment followed by a list of other generated columns. Existing
**	columns in some cases might need in-line convert() clauses to be
**	applied to them.
**
**	We expect that the caller has already initialized a prefix of the
**	SELECT list, and start generating a comma-separated column list here.
**	End result is a "SELECT <selectlist>" for all columns that need to be
**	archived, including some generated columns like 'DBName' etc. The
**	generated columns always appear at the end of the list of columns for
**	the monitoring tables, after the default columns, and are always
**	generated as NULL'able columns. This is so that users can still do:
**
**		insert <archivetable> ( <column list from monitoring_Table> )
**		select * from <monitoring_Table>
**
**	to manually archive data into an archive created by this script and
**	still not get column name/datatype mismatches during the INSERT ...
**	SELECT. (The trailing NULL'able generated columns will all get NULLs.)
**
** Parameters:
**	@montable	- Name of monitoring table to archive data from
**	@sellist	- (Out) Generated SELECT list statement.
**	@gen_cols	- (Out) SQL for generated column list.
**
** Returns:
**	0	- If the generation was successful.
**	!=0	- Otherwise.
{
*/
go

create procedure sp_mon_gen_columnlist(
			  @montable	varchar(30)
			, @sellist	varchar(1500)	output
			, @gen_cols	varchar(768)	output
) as
begin
	declare @retval		int
     	      , @colname	varchar(30)
	      , @col_dbname	varchar(30)
	      , @col_sep	char(1)
	      , @id_start	tinyint
	      , @id_length	tinyint
	      , @mon_tabid	int

	select @retval 		= 1	-- Assume failure
	     , @id_length	= datalength('ID')
	     , @col_sep		= NULL

	     , @mon_tabid	= isnull((select o.id
	     				  from master.dbo.sysobjects o
					  where o.name = @montable
					    and o.uid = user_id('dbo')), 0)

	-- For the rare case that the specified monitor table does not exist
	-- in masterdb, trap an error and return.
	--
	if (@mon_tabid = 0)
	begin
		select @montable = 'dbo.' + @montable
		raiserror 17870, @montable, 'master', ""
		return 1
	end

	declare colcur cursor for 
	select c.name from master.dbo.syscolumns c
	where c.id = @mon_tabid
	order by c.colid asc
	for read only

	open colcur

	while (1 = 1)
	begin	-- {
		fetch colcur into @colname
		if (@@error != 0)
		begin
			goto end_cursor
		end
		else if (@@sqlstatus != 0)
			break

		-- Keep them short, to avoid row-size warnings, in the generated
		-- SQL fragment.
		-- (dbname is still varchar(30) in 15.0x also.)
		--
		if (@colname like '%DBName%')
		begin
			select @sellist = @sellist + @col_sep + @colname
		end

		else if (@colname like '%Name%')
		begin
			select @sellist = @sellist
					+ @col_sep
					+ @colname
					+ '=convert(varchar(255),'
					+ @colname
					+ ')'
		end

		else
		begin	-- {
			select @sellist = @sellist + @col_sep + @colname

			-- Add equivalent '*DBName' column if this column is
			-- some '%DBID' column.
			--
			if (@colname like '%DBID')
			begin	-- {

				-- Convert column to '%DBName' column.
				--
				select @id_start = (datalength(@colname)
							- @id_length) + 1
				select @col_dbname = stuff(@colname,
							   @id_start,
							   @id_length,
							   'Name')

				-- Append the equivalent dbname column if it
				-- does not already exist for this table.
				--
				if not exists (select 1
						from master.dbo.syscolumns
						where id = @mon_tabid
						  and name = @col_dbname)
				begin
							/*
							+ '=convert(varchar(30),db_name(case (select 1 from master.dbo.sysdatabases where dbid=m.'
							+ @colname
							+ ') when 1 then '
							+ @colname
							+ ' else NULL end'
							*/

					select @gen_cols = @gen_cols
							+ ','
							+ @col_dbname
							+ '=convert(varchar(30),db_name('
							+ @colname
							+ '))'
				end
			end	-- }

			-- Special-case logic for some monitoring tables where
			-- we want to archive extra info when it does not
			-- already exist in the table.
			--
			-- NOTE: There is a wart here worth mentioning.
			-- Normally, we simply should be able to convert the
			-- (HeldProcedureID, HeldProcDBID) pair to the holding
			-- procedure's dbname, but if you pass-in an invalid
			-- 'dbid' to the db_name() built-in, it doesn't cope &
			-- returns an 913 error. (DB not found). To avoid that
			-- noise errors, fabricate a SQL where we first
			-- validate that the 'HeldProcDBID' does, indeed,
			-- exist in sysdatabases, and only then use it as the
			-- 2nd arg to db_name().
			--
			-- The generated SQL appears like so, to translate the
			-- HeldProcedureID to its dbname equivalent:
			--
			-- object_name(HeldProcedureID,case (select 1 from master.dbo.sysdatabases where dbid=m.HeldProcDBID) when 1 then HeldProcDBID else NULL end))
			else if (@montable = 'monDeadLock')
			begin
				select @gen_cols = @gen_cols
						+ case @colname
						    when 'HeldProcedureID'
						    then ',HeldProcedureName=convert(varchar(255) NULL,object_name(HeldProcedureID,'

						      -- See note above:
						      + 'case (select 1 from master.dbo.sysdatabases where dbid=m.'
						      + 'HeldProcDBID'
						      + ') when 1 then '
						      + 'HeldProcDBID'
						      + ' else NULL end))'
						      -- End see note above:

						      -- Delete above lines and
						      -- reinstate this when
						      -- the wart is fixed.
						      --
						      -- + ,HeldProcDBID))'
						      --
						    when 'InstanceID'
						    then ',InstanceName=convert(varchar(30) NULL, instance_name(InstanceID))'
						    else NULL
						  end
			end
		end	-- }

		-- Now that we've got the 1st col, reset the column-separator
		-- to a valid value.
		--
		select @col_sep = ','

	end	-- }

	select @retval = 0

end_cursor:
	close colcur
	deallocate cursor colcur

	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_mon_archive_genSQL
go

/*
** sp_mon_archive_genSQL
**
**	SQL Generator. Given a monitoring table whose data needs to be
**	archived, this sproc checks if an existing archive already exists.
**	If so, it will generate an appropriate INSERT ... SELECT statement.
**	Otherwise, to create a brand new archive, a SELECT INTO will be
**	generated. The generated SQL is then passed back to the caller for
**	further processing.
**
**	Caller passes in a datetime value (@datestamp) which will be used
**	as a hard-coded value while generating the SQL. This value will be
**	stored in the 'ArchiveDate' column in the archive data, so that all
**	rows archived in one pass can be identified, and archived data across
**	different tables can be joined with the ArchiveDate column.
**
**	To optimize the case where users might be archiving data from the
**	same monitoring table back to the archive, we generate the SQL 
**	statement once and store it away in the control table. For subsequent 
**	uses, we simply extract the fragments from the control table and 
**	return it to the user after replacing a placeholder patter for the 
**	'datestamp' (archive date) with the passed-in [current] @datestamp 
**	value.
**
**	This sproc depeneds on the existence of the control table, which
**	would have been created by the top-level sp_monitor when it was
**	first invoked.
**
** Parameters
**	@montable	- Name of monitoring table to generate SQL for.
**	@datestamp	- Date value to use for ArchiveDate column.
**	@selstmt	- SQL SELECT statement buffer; should be large enough.
**	@fromclause	- "FROM <monTable> clause" to be reused by caller.
**	@printsql	- Boolean, to print SQL for re-use in other scripts.
**			  (Driven by trace facility.)
**
** Returns:
**	0		- Success
**	Non-zero	- Otherwise.
{
*/
go

create procedure sp_mon_archive_genSQL(
			  @montable	varchar(30)
			, @datestamp	datetime
			, @selstmt	varchar(1500)	output
			, @fromclause	varchar(30)	= NULL output
			, @printsql	tinyint	 = 0
) as
begin
	declare @retval		int
	      , @generated_cols	varchar(1024)
	      , @filler		varchar(10)

	      , @whoami		varchar(30)
	      , @indent		varchar(32)

	      -- ESD/version/EBF # info from @@version
	      , @esdnumstr	varchar(20)
	      , @ebfnumstr	varchar(20)
	      , @esdnum		int
	      , @ebfnum		int


	select @whoami	= 'sp_mon_archive_genSQL'
	     , @indent	= char(10) + space(2 * @@nestlevel)

	-- Start the SELECT statement. We skimp on white spaces here
	-- mainly to use as much SQL buffer space as possible. This compromises
	-- on readability, but we only do this once, and once stable, there
	-- will be no need to view this generated SQL (hopefully!).
	--
	select @selstmt 	= 'SELECT '
	     , @generated_cols	= NULL

	       -- This is used as a placeholder in the generated SQL for the
	       -- current date time. It'll be replaced shortly below.
	       --
	     , @filler		= 'XXXXXXXXXX'

	if (@printsql = 1)
	begin
		print "%1!---- Start Trace %2!: ----"
			, @indent, @whoami
	end

	-- If a previously generated SQL statement was found in the control
	-- table, retrieve the fragments and replace that directly.
	-- 
	if exists (select 1 from tempdb.dbo.mon_config
		   where monitor = @montable
		     and confignum = 0)
	begin
		select @selstmt 	= sqlstmt
		     , @fromclause	= configname
		from tempdb.dbo.mon_config
		where monitor = @montable
		  and confignum = 0

		select @retval = @@error
		if (@retval != 0)
			return @retval

		-- Replace the placeholder with the real date stamp for this
		-- run.
		--
		select @selstmt = str_replace(@selstmt, @filler, @datestamp)

		if (@printsql = 1)
		begin
			print "%1! Retrieved SQL from control table: %2!"
				, @indent, 'tempdb.dbo.mon_config'
		end

		goto exit_proc
	end

	-- Generate column list for the specific monitoring table.
	exec @retval = sp_mon_gen_columnlist @montable, @selstmt output
					, @generated_cols output
	if (@retval != 0)
		return @retval

	-- Pull-out version string related useful info.
	--
	exec sp_versioncrack @@version, "ESD", @esdnumstr out, @esdnum out
	exec sp_versioncrack @@version, "EBF", @ebfnumstr out, @ebfnum out

	-- Add the remaining fields explicitly as NULL'able fields.
	select @generated_cols = @generated_cols
			+ ',ServerName=convert(varchar(30) NULL, @@servername)'
			+ ",ArchiveDate=convert(datetime NULL,"
			+ "'" + @filler + "'" + ")"

			-- Generated columns to identify server
			+ ",VersionNum=" + convert(varchar,@@version_number)
			+ ",ESDNum=" + convert(varchar, @esdnum)
			+ ",EBFNum=" + convert(varchar, @ebfnum)

	-- Print this, so that in other scripts that reference this
	-- #temp table we can cut-and-paste this directly and avoid code
	-- errors.
	--
	if (@printsql = 1)
	begin
		print "%1! ", @selstmt
		print "%1! -- '%2!'", @generated_cols, @datestamp
		print "INTO #%1!", @montable
		print "%1!", @fromclause
	end

	select @selstmt = @selstmt + @generated_cols
	     , @fromclause = "FROM " + 'master.dbo.' + @montable + ' m'

	-- Save off this generated SQL in the control table, so that we can
	-- reuse it later, and simply replace the @filler with the new
	-- @datestamp that we will get on subsequent reuses.
	--
	insert tempdb.dbo.mon_config(monitor, confignum, configval, configname,
				     enabled, sqlstmt)
	select @montable
	     , 0
	     , 0
	     , @fromclause
	     , @datestamp
	     , @selstmt

	select @retval = @@error
	if (@retval != 0)
		return @retval

	-- Before returning to caller, replace the filler substring with
	-- the real datestamp for this run.
	--
	select @selstmt = str_replace(@selstmt, @filler, @datestamp)

	if (@printsql = 1)
	begin
		print "%1! Generated SQL and archive to control table: %2!"
			, @indent, 'tempdb.dbo.mon_config'
	end

exit_proc:

	if (@printsql = 1)
	begin
		print "%1!---- End Trace %2! (retval = %3!) ----"
			, @indent, @whoami, @retval
	end
	return 0

end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_mon_archive_data
go

/*
** sp_mon_archive_data
**
**	Main procedure where the monitoring data actually gets archived into
**	an archive table.
**
** Parameters:
**	@archivename	- Name of archive table
**	@selstmt	- SELECT statement describing columns to archive
**	@fromclause	- FROM clause naming the monitoring table to archive
**	@filters	- Any filters user wants to apply during archiving
**	@whereclause	- WHERE clause, if user wants to apply special logic
**	@uniqueindex_name
**			- Name to give the unique index on archive table.
**	@datestamp	- Unique datetime value for the rows being archived.
**	@created	- [Out] whether a new archive was created.
**	@unique_col1	- Names of columns that should be used to perform ...
**	@unique_col2	- .. duplicate elimination. (Upto 5 provided.)
**	@unique_col3
**	@unique_col4
**	@unique_col5
**
** This works as follows:
**
**	o If the archive table does not exist, create one using SELECT INTO.
**	  The SELECT list, FROM clause and archive name SQL fragments are used
**	  here to construct the SELECT INTO statement.
**
**	o Create a unique index on the archive with IGNORE_DUP_KEY so that
**	  on subsequent inserts we won't insert duplicates. User has supplied
**	  the columns on which the unique index should be created.
**
**	o Else, then archive the data using INSERT ... SELECT. 
**
** Returns:
**	0	- If data was successfully archived.
**	!= 0	- If any errors occured.
{
*/
go

create procedure sp_mon_archive_data(
			  @archivename		varchar(40)
			, @selstmt		varchar(1500)
			, @fromclause		varchar(30)
			, @whereclause		varchar(255)	= NULL
			, @uniqueindex_name	varchar(30)	= NULL
			, @datestamp		datetime
			, @created 		int	output
			, @trace		int
			, @unique_col1		varchar(30)	= NULL
			, @unique_col2		varchar(30)	= NULL
			, @unique_col3		varchar(30)	= NULL
			, @unique_col4		varchar(30)	= NULL
			, @unique_col5		varchar(30)	= NULL
) as
begin
	declare @whoami		varchar(30)
	      , @indent 	varchar(32)
	      , @sqlstmt	varchar(1500)
	      , @msg		varchar(80)
	      , @do_freeze_mda	tinyint
	      , @retval		int
	      , @mda_retval	int
	      , @tmp_retval	int
	      , @num_rows	int
	      , @crt_newarchive	tinyint

	select @whoami	= 'sp_mon_archive_data'
	     , @indent	= char(10) + space(2 * @@nestlevel)

	if (@trace = 1)
	begin
		print "%1!---- Start Trace %2!: ----"
			, @indent, @whoami
	end
	if (object_id(@archivename) IS NULL)
	begin	-- {
		-- Create a new table using SELECT INTO.
		--
		select @sqlstmt = @selstmt
				+ " INTO " + @archivename
				+ ' '
				+ @fromclause
				+ ' '
				+ @whereclause

		     , @crt_newarchive = 1
		     , @do_freeze_mda = 1
	end	-- }
	else
	begin	-- {

		-- Re-create an INSERT...SELECT SQL statement adding WHERE
		-- clauses for duplicate elimination, using the columns
		-- specified for uniqueness.
		--
		select @sqlstmt = 'INSERT ' + @archivename
				+ ' '
				+ @selstmt
				+ ' ' 
				+ @fromclause
				+ ' '
				+ @whereclause

		     -- Archive already exists. Just insert into it.
		     , @crt_newarchive 	= 0

		     -- We need to freeze MDA for insert-select, also.
		     --
		     , @do_freeze_mda	= 1

	end	-- }

	-- If we are creating a new archive, here is where the SQL
	-- to extract data from monDeadLock will get executed. Freeze
	-- it, and unfreeze it after the SQL executes.
	--
	if (@do_freeze_mda = 1)
	begin
		select @mda_retval = mdaconfig('freeze', 'begin')
	end

	select @num_rows = 0
	exec @retval = sp_exec_SQL @sqlstmt
				, "sp_mon_archive_data-archive"
				, @num_rows output
				, @trace
	if (@do_freeze_mda = 1)
	begin
		select @mda_retval = mdaconfig('freeze', 'end')
	end

	-- The data was correctly archived either via SELECT-INTO or
	-- INSERT-SELECT. Report on that.
	--
	if (@retval = 0)
	begin
		-- Reset archive name to be full name, incl dbname.
		-- [Reuse variable for message reporting.]
		--
		select @sqlstmt =  db_name() + ".dbo." + @archivename
		if (@crt_newarchive = 1)
		begin
			exec sp_getmessage 19489, @msg output
			print @msg, @sqlstmt
		end
		exec sp_getmessage 19490, @msg output
		print @msg, @num_rows , @sqlstmt, @datestamp

	end

	-- Start building the CREATE INDEX sql and then exec it. Unique
	-- index used for duplicate elimination during future inserts.
	--
	if ((@retval = 0) and (@crt_newarchive = 1))
	begin
		select @sqlstmt = "CREATE UNIQUE INDEX "
				+ @uniqueindex_name
				+ " ON "
				+ @archivename
				+ "("

		if (@unique_col1 IS NOT NULL)
		begin
			select @sqlstmt = @sqlstmt
					+ @unique_col1
		end

		if (@unique_col2 IS NOT NULL)
		begin
			select @sqlstmt = @sqlstmt
					+ ","
					+ @unique_col2
		end

		if (@unique_col3 IS NOT NULL)
		begin
			select @sqlstmt = @sqlstmt
					+ ","
					+ @unique_col3
		end

		if (@unique_col4 IS NOT NULL)
		begin
			select @sqlstmt = @sqlstmt
					+ ","
					+ @unique_col4
		end

		if (@unique_col5 IS NOT NULL)
		begin
			select @sqlstmt = @sqlstmt
					+ ","
					+ @unique_col5
		end
		select @sqlstmt = @sqlstmt
				+ ")"
				+ " WITH IGNORE_DUP_KEY"

		exec @retval = sp_exec_SQL @sqlstmt
					, 'archive_data-crt-unique-index'
					,  NULL, @trace
	end

	-- Deem successful creation of table only if index was also
	-- successfully built.
	--
	if (@retval = 1)
		select @created = 1

	if (@trace = 1)
	begin
		print "%1!---- End Trace %2! (retval=%3!) ----"
			, @indent, @whoami, @retval
	end

	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_mon_archive_monTable
go

/*
** sp_mon_archive_monTable
**
**	Generic sproc to drive the archival of data for one monitoring table.
**
**	Archive the data for the specified monitoring table into an archive
**	table in the current db, using a specified 'prefix' string. If the
**	archive table does not exist, create one using SELECT INTO. Otherwise,
**	INSERT SELECT into it from the given monitoring table, eliminating
**	duplicates on the given key columns of the unique index.
**
** Parameters:
**	@montable	- Monitoring table to be archived.
**	@prefix	 	- Prefix string to be appended to archive name.
**	@datestamp	- datetime value when archive is being run.
**	@created	- [Out] whether a new archive was created.
**	@trace		- Debugging trace (internaly use only).
**	@unique_col1	- Names of columns that should be used to perform ...
**	@unique_col2	- .. duplicate elimination. (Upto 5 provided.)
**	@unique_col3
**	@unique_col4
**	@unique_col5
**
** Returns:
**	0	- If data was successfully archived.
**	!=0	- Otherwise.
{
*/
go

create procedure sp_mon_archive_monTable(
				  @montable	varchar(30)
				, @prefix	varchar(30)
				, @datestamp	datetime
				, @created	int	output
				, @trace	int		= NULL
				, @unique_col1	varchar(30)	= NULL
				, @unique_col2	varchar(30)	= NULL
				, @unique_col3	varchar(30)	= NULL
				, @unique_col4	varchar(30)	= NULL
				, @unique_col5	varchar(30)	= NULL
) as
begin
	declare @whoami		varchar(30)
	      , @archivename	varchar(30)
	      , @arch_dbname	varchar(30)
	      , @retval		int
	      , @sellist	varchar(1500)
	      , @sellist_len	int
	      , @fromclause	varchar(40)
	      , @fromclause_len	int
	      , @indent		varchar(32)

	      -- Name of the index created for duplicate elimination
	      , @uniqueindex_name	varchar(30)

	select @whoami		= 'sp_mon_archive_monTable'

	-- Prepend user-supplied prefix string, if any.
	select @archivename 	= @prefix + @montable
	     , @arch_dbname	= db_name()

	     , @indent		= char(10) + space(2 * @@nestlevel)
	     , @uniqueindex_name	= @montable + "_uidx"

	if (@trace = 1)
	begin
		print "%1!---- Start Trace %2!: MonTable='%3!', ArchiveDb='%4!' Archive='%5!'"
			, @indent
			, @whoami
			, @montable
			, @arch_dbname
			, @archivename
	end

	exec @retval = sp_mon_archive_genSQL
					  @montable
					, @datestamp
					, @sellist 	output
					, @fromclause	output
					, @trace

	if (@trace = 1)
	begin

		print " "
		select @sellist_len 	= datalength(@sellist)
		     , @fromclause_len 	= datalength(@fromclause)

		print "%1!%2!: Sqlstmt (length=%3!)=[%4!]"
			, @indent
			, @montable
			, @sellist_len, @sellist

		print "%1!%2!: FROM clause (length=%3!)=[%4!]"
			, @indent
			, @montable
			, @fromclause_len, @fromclause
	end

	if (@retval != 0)
		return @retval

	exec @retval = sp_mon_archive_data @archivename
					 , @sellist
					 , @fromclause
					 , NULL
					 , @uniqueindex_name
					 , @datestamp
					 , @created output
					 , @trace

					 -- List of columns used for dup-elimn
					 , @unique_col1
					 , @unique_col2
					 , @unique_col3
					 , @unique_col4
					 , @unique_col5

	if (@trace = 1)
	begin
		print "%1!---- End Trace %2! (retval=%3!): ----"
			, @indent, @whoami, @retval
	end

	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_mon_archive_deadlock
go

/*
** sp_mon_archive_deadlock
**
**	Shell sproc to drive the archival for monitoring tables required for
**	the 'deadlock' monitoring type. The tables affected are:
**
**	Table		  Unique index keys:
**	-----		  --------------------
**	monDeadLock	- (ResolveTime, DeadlockID, 
**			   HeldSPID, WaitSPID, ServerName)
**
**	After a new archive has been created, appropriate index(es) are
**	created on the archive to help improve report performance.
**
** Parameters:
**	@prefix	 	- Prefix string to be prepended to archive name.
**	@datestamp	- datetime value when archive is being run.
**	@trace		- Debugging trace (internaly use only).
{
*/
go

create procedure sp_mon_archive_deadlock(
				  @prefix	varchar(30)
				, @datestamp	datetime
				, @trace	int		= NULL
) as
begin
	declare @retval			int
	      , @montable		varchar(11)
	      , @sqlstmt		varchar(256)
	      , @new_arch_created	int	-- whether a new archive 
	      					-- was created by callee.

	select @montable = 'monDeadLock'
	exec @retval = sp_mon_archive_monTable @montable
					     , @prefix
					     , @datestamp
					     , @new_arch_created output
					     , @trace
					     , 'ResolveTime'
					     , 'DeadlockID'
					     , 'HeldSPID'
					     , 'WaitSPID'
					     , 'ServerName'

	-- If a new archive was created successfully, go back and create
	-- more unique indexes as faster access methods. It's quite cmmon
	-- to expect that archival analysis will be done for particular 
	-- deadlock ID instances, so create an index on that column.
	--
	if ((@retval = 0) and (@new_arch_created = 1))
	begin
		select @sqlstmt = "CREATE INDEX "
				+ @montable + "_ncind1"
				+ " ON "
				+ @montable
				+ '('
				+ 'DeadlockID'
				+ ')'
		exec @retval = sp_exec_SQL @sqlstmt, 'sp_mon_archive_deadlock'
					,  NULL, @trace
	end

	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ############################################################################ 
/*
** NOTE: The syntax for the 'archive' and 'report' commands is similar to the
**	 syntax added for these commands under sp_spaceusage feature which
**	 is [will be] available in 15.0.2. Much of the parsing code you see
**	 here is shared code pulled from that implementation. See 436433-1.
**	 The one difference is that this feature only allows one sub-clause;
**	 i.e. 'prefix=<string>', whereas that other feature allows more
**	 <using_items> such as 'dbname=<name>', 'unit=<unit>' etc. Hence, this
**	 is a new implementation of the parsing routines, rather than directly
**	 re-using the code that parses the USING clause for sp_spaceusage.
*/
exec sp_dbxt_recreate_proc sp_monitor_parse_archive_cmd
go

/*
** sp_monitor_parse_archive_cmd
**
**	Procedure to parse the 'archive', or 'report' commands to sp_monitor.
**	Those commands share a syntax as follows:
**
**		archive [USING prefix=<string> ]
**		report  [USING prefix=<string> ]
**
**	Validate that the user-input arg to sp_monitor is one of these two.
**	If the 'prefix' clause is found, extract the sub-string following the
**	'prefix' keyword, and return that as the prefix name of the archive
**	table(s). Validate the prefix string to be a valid identifier and also
**	impose some length checks on it (to avoid later downstream errors
**	while creating/accessing the archive tables).
**
** Parameters:
**	@archivecmd	- User-input argument for this archive/report command.
**	@archive_str	- Whether it's 'archive' or 'report'
**	@archive_syntax	- What the valid syntax should be (for errors).
**	@arch_prefix	- (Out) Validated archive table's prefix string.
**
** Returns:
**	0	- Command is valid, and @arch_prefix is result value.
**	!=0	- Some usage errors. (Error messages will be reported.)
{
*/
go

create procedure sp_monitor_parse_archive_cmd(
			  @archivecmd		varchar(255)
			, @archive_str		varchar(7)
			, @archive_syntax	varchar(40)
			, @arch_prefix		varchar(8)	output
			, @trace		int	= NULL
)as
begin
	declare	@whoami		varchar(30)
	      , @indent		varchar(32)
	      , @msg		varchar(200)
	      , @retval		int
	      , @option_found	int

	      , @opt_sep	char(1)
	      , @charindex	tinyint
	      , @usingIndex	int
	      , @using_clause	varchar(30)
	      , @prefix_str	varchar(30)
	      , @option_item	varchar(30)
	      , @left_substr	varchar(30)

	      -- We restrict this to a short string for 125.x due to the
	      -- limited tablename length.
	      --
	      , @arch_prefix_dflt	varchar(8)
	      , @arch_prefix_maxlen	int
	      , @arch_prefix_lcl	varchar(30)	-- Parsed value.

	      -- [Currently] unused output variables that are returned by the
	      -- common parsing routine sp_spaceusage_processusing.
	      --
	      , @archive_db_unused	varchar(30)
	      , @unit_unused		varchar(30)
	      , @unit_found		tinyint

	select @whoami		= 'sp_monitor_parse_archive_cmd'
	     , @indent		= char(10) + space(2 * @@nestlevel)
	     , @prefix_str	= 'prefix'
	     , @arch_prefix_dflt= 'archive_'
	     , @arch_prefix_lcl	= NULL
	     , @using_clause 	= NULL
	     , @retval		= 1	-- expect failure till we know otherwise
	     , @usingIndex	= 0

	     -- Initialize to aid in error checking for inapplicable syntax.
	     , @archive_db_unused	= NULL
	     , @unit_unused		= NULL
	     , @unit_found		= 0

	-- This is the max prefix name length, as the identifiers are
	-- restricted to be 30 bytes. This prefix allows for the possibility
	-- to archive data from the MDA table with the longest name, if at
	-- all we want to add that funcationality.
	--
	select @arch_prefix_maxlen	= datalength(@arch_prefix_dflt)

	if (@trace = 1)
	begin
		print "%1!---- Start Trace %2! archivecmd='%3!'"
			, @indent, @whoami
			, @archivecmd
	end

	-- =================================================================
	-- If the archivecmd has a "USING prefix=<string>" argument, parse
	-- that out and validate it. (Note we allow mixed-case for keywords
	-- like USING, PREFIX etc.)
	--

	-- Check whether the user has specified a USING clause.
	select @usingIndex = charindex("USING", upper(@archivecmd))

	if (@usingIndex != 0)
	begin
		-- 0 => case insensitive
		exec sp_split_string @archivecmd, "USING", 0
					 , @left_substr out
					 , @using_clause out
		select @using_clause = ltrim(rtrim(@using_clause))
	end

	else if (@archivecmd != @archive_str)
	begin
		-- Reuse @whoami to build command-specific help.
		select @whoami = "'@" + @archive_str + "'"
		raiserror 18640, @whoami, @archivecmd, @archive_syntax

		-- print "@archivecmd: '%1!', @archive_str: '%2!'",
		-- 	@archivecmd, @archive_str
		goto error_exit
	end

	if (@using_clause IS NOT NULL)
	begin
		exec @retval = sp_spaceusage_processusing
					  @using_clause
					, @archive_db_unused out
					, @arch_prefix_lcl out
					, @unit_unused out
					, @unit_found out

		-- Check for cases that user might have provided sub-args
		-- to USING clause that are valid for other interfaces (and
		-- are hence legal per sp_spaceusage_processusing logic)
		-- but are not legal here. Error out in such cases.
		-- Expected: "archive[ USING prefix=<string>]"
		-- Expected: "report[ USING prefix=<string>]"
		--
		if (   (@retval != 0)
		    or (@archive_db_unused IS NOT NULL)
		    or ((@unit_unused IS NOT NULL) and (@unit_found = 1)) )
		begin
			-- Reuse @whoami to build command-specific help.
			select @whoami = "'@" + @archive_str + "'"

			raiserror 18640, @whoami, @archivecmd, @archive_syntax

			if (@trace = 1)
			begin
				print "@retval: %1! @archive_db_unused: %2! @unit_unused: %3! @unit_found: %4!"
					, @retval
					, @archive_db_unused
					, @unit_unused
					, @unit_found
			end

			-- Reset to indicate an error condition.
			select @retval = 1
			goto error_exit
		end
	end

	-- Validate that the length of the prefix is what we can support 
	-- in 12.5.x
	--
	if (@arch_prefix_lcl IS NULL) or (@arch_prefix_lcl = "")
	begin
		-- Allow user to create archives named simply 'monDeadLock'.
		select @arch_prefix = NULL 	-- @arch_prefix_dflt
	end

	else if (valid_name(@arch_prefix_lcl) = 0)
	begin
		raiserror 17284, @arch_prefix_lcl
		goto error_exit
	end

	else if (datalength(@arch_prefix_lcl) > @arch_prefix_maxlen)
	begin
		raiserror 19491, @arch_prefix_lcl, @arch_prefix_maxlen
		goto error_exit
	end
	else
	begin
		select @arch_prefix = @arch_prefix_lcl
	end

	-- All ok; @arch_prefix is a valid prefix for archive tables.
	select @retval = 0

error_exit:
	if (@trace = 1)
	begin
		print "%1!---- End Trace %2! archivecmd='%3!' arch_prefix='%4!' (retval=%5!)"
			, @indent, @whoami
			, @archivecmd
			, @arch_prefix
			, @retval
	end

	return @retval
end	-- }
go

-- ############################################################################ 
exec sp_dbxt_recreate_proc sp_monitor_archive
go

/*
** sp_monitor_archive
**
**	Driver procedure to archive data from one or more monitoring tables
**	into an archive. The archive can be a database name alone, or a
**	user-specified table name. If it's a database, a pre-named and
**	documented archive table will be created. If it's a tablename, then
**	existing monitoring data will be archived to that table with a date
**	timestamp.
**
**	This procedure is written in a generic manner to drive the archiving
**	for more monitoring types in the future.
**
** Parameters:
**	@montype	- Monitoring type.
**	@archivecmd	- 'archive' command with optional 'prefix' clause etc.
**
** Archival Logic:
**
**	We support archiving into an archive table, with a fixed name.
**	The user has the option of specifying a prefix string.
**
**	If the archive table does not exist, it will be created first.
**	Otherwise, new rows will be inserted into it.
**
** Returns:
**	0, if archive was successful. Non-zero otherwise.
{
*/
go

create procedure sp_monitor_archive(
			  @montype	varchar(30)	= NULL
			, @archivecmd	varchar(255)	= NULL
			, @trace	int		= NULL
) as
begin
	declare	@whoami		varchar(30)
	      , @indent		varchar(32)
	      , @retval		int
	      , @mda_retval	int
	      , @found_montype	tinyint

	      , @opt_sep	char(1)
	      , @charindex	tinyint
	      , @archive_str	varchar(7)
	      , @option_item	varchar(30)
	      , @datestamp	datetime

	      , @archive_syntax	varchar(40)

	      -- We restrict this to a short string for 125.x due to the
	      -- limited tablename length.
	      --
	      , @arch_prefix_dflt	varchar(8)
	      , @arch_prefix_maxlen	int
	      , @arch_prefix		varchar(30)

	      , @arch_dbname	varchar(30)
	      , @baseprocname	varchar(100)
	      , @archprocname	varchar(60)

	      -- DB status flags
	      , @sel_into_ok	int	-- status word
	      , @user_proxy_db	int
	      , @ha_proxy_db	int

	      -- Variables to store status bit settings.
	      , @sel_into_flag	int
	      , @proxy_db_flag	int

	select @whoami		= object_name(@@procid, db_id('sybsystemprocs'))
	     , @indent		= char(10) + space(2 * @@nestlevel)
	     , @archive_str	= 'archive'

	     -- This will be the single timestamp used for all data archived
	     -- under this command. This way, this set of data can be all 
	     -- joined in one pass, using this common field.
	     --
	     , @datestamp	= getdate()

	     -- Various status flags for database settings.
	     , @sel_into_ok	= 4
	     , @user_proxy_db	= 1
	     , @ha_proxy_db	= 2

	     -- Assume error till we know that it's a valid monitoring type 
	     , @found_montype	= 0

	if (@montype IN (  'deadlock'
			) )
	begin
		select @found_montype = 1
	end

	-- This means user asked to archive data for a monitoring type that is
	-- an illegal monitoring type, or archiving for that type is currently
	-- not supported. Raise an error and bail.
	--
	if (@found_montype = 0)
	begin
		select @archive_syntax = "sp_monitor 'help', '"
				       + @archive_str
				       + "'"
		raiserror 19260, @archive_syntax
		return 1
	end

	exec @retval = sp_monitor_check_permission @whoami
	if (@retval != 0)
		return @retval

	-- Do routine monitoring specific validation for setup/configuration.
	--  'archive' is not really a monitoring type, so instead pass-in a
	-- dummy sproc name as the arg, which will be anyway ignored .
	--
	exec @retval = sp_monitor_verify_setup 'sp_monitor_archive'

	exec @mda_retval = sp_monitor_verify_cfgval @montype

	-- Bail out if there were any errors.
	if (@retval != 0)
		return @retval
	else if (@mda_retval != 0)
		return @mda_retval

	if (@trace IS NULL)
		exec @trace = sp_monitor_trace_level

	if (@trace = 1)
	begin
		print "%1!---- Start Trace %2! montype='%3!' archivecmd='%4!' datestamp='%5!'"
			, @indent, @whoami
			, @montype
			, @archivecmd
			, @datestamp
	end

	if (@montype IS NULL)
	begin
		raiserror 18464, "'@monitoring_type'"
		return 1
	end
	else if (@archivecmd IS NULL)
	begin
		raiserror 18464, "'@archivecmd'"
		return 1
	end

	-- Always archive in the current db of the sproc's execution.
	select @arch_dbname	= db_name()

	-- Disallow certain key system-dbs for archival uses.
	if (@arch_dbname IN (   'master'
			      , 'model'
			      , 'sybsystemprocs'
			      , 'sybsystemdb'
			      , 'sybsecurity'
			     ) 
	   )
	begin
		raiserror 19492, @arch_dbname, "system"
		return 1
	end

	-- Check if archive db allows for select-into and return error
	-- now, to avoid future errors at run-time.
	--
	select @sel_into_flag = (d.status & @sel_into_ok)
	from master.dbo.sysdatabases d
	where name = @arch_dbname

	if (@sel_into_flag != @sel_into_ok)
	begin
		exec sp_getmessage 19261, @baseprocname output
		print @baseprocname, "sp_monitor", @archive_str,
				"sp_dboption", "select into"

		-- Reuse @var to get string name for 17050.
		exec sp_getmessage 17050, @baseprocname output
		raiserror 19493, @arch_dbname , @baseprocname
		return 1
	end

	-- check and disallow user- and HA-proxy dbs as an archive db.
	--
	select @proxy_db_flag = (d.status3 & (@user_proxy_db | @ha_proxy_db))
	from master.dbo.sysdatabases d
	where name = @arch_dbname

	if (@proxy_db_flag IN (@user_proxy_db, @ha_proxy_db))
	begin
		raiserror 19492, @arch_dbname, "proxy"
		return 1
	end

	select @archive_syntax	= "'" + @archive_str + " [using prefix=<string>]'"
	exec @retval = sp_monitor_parse_archive_cmd
				  @archivecmd
				, @archive_str
				, @archive_syntax
				, @arch_prefix output
				, @trace
	if (@retval != 0)
		return @retval

	-- =================================================================
	-- Call the monitoring-type specific archival routine
	-- Currently, we only support archiving for one monitoring type.
	-- In future, we might consider extending this to archive for 'all'
	-- monitoring types in one go.
	--
	-- Build the procedure's name prefixed by the archive db name, so that
	-- when we execute the specific archiving sproc, it will run in the
	-- archive db. (We just have to append the monitoring type for each
	-- type of monitoring whose data will be archived.)
	--
	select @baseprocname = @arch_dbname + ".." + "sp_mon_archive_"

	if (@montype IN ('deadlock', 'all'))
	begin
		select @archprocname 	= @baseprocname + 'deadlock'
		     , @found_montype	= 1

		-- The reason why we getdate() here and pass it all the way
		-- down the stack is that sometime in the future when we
		-- support archival for other monitoring types (or 'all')
		-- we would like to keep the archive date across multiple tables
		-- the same for all data that is being archived in one command.
		--
		exec @retval = @archprocname @arch_prefix
					   , @datestamp
					   , @trace
		if (@retval != 0)
			return @retval
	end


	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_report_usage')
begin
	drop procedure sp_monitor_report_usage
end
go
print "Installing sp_monitor_report_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_report')
begin
	drop procedure sp_monitor_report
end
go
print "Installing sp_monitor_report"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_report [Total 1]
**
** 19481, "Reporting from an archive is currently supported for only these monitoring types: %1!."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_report [Total 6]
**
** 18954, "Usage:"
** 19481, "Reporting from an archive is currently supported for only these monitoring types: %1!."
** 19482, "options supported for monitoring_type"
** 19483, "Example: Report deadlock events from a default archive named '%1!' in the current database:"
** 19484, "Example: Report deadlock events from an archive named '%1!%2!' in database %3!:"
** 19485, "Example: Report deadlock events for a particular day from an archive named '%1!%2!' in database '%3!':"
*/
/*
** End spgenmsgs.pl output.
*/
go
exec sp_dbxt_recreate_proc sp_monitor_report_usage
go

/*
** sp_monitor_report_usage
**
**	Produce basic help usage for the 'report' command.
{
*/
create procedure sp_monitor_report_usage(
			  @output_type	varchar(8)
) as
begin
	declare @usage		varchar(10)
	      , @msg		varchar(256)
	      , @supported	varchar(80)
	      , @prefix		varchar(8)
	      , @mondeadlock	varchar(11)
	      , @newline	char(1)
	      , @tabchar	char(1)

	select @mondeadlock	= 'monDeadLock'
	     , @prefix		= 'daily_'
	     , @newline		= char(10)
	     , @tabchar		= char(9)

	print " "
	exec sp_getmessage 18954, @usage output

	-- Build the usage message string, plucking out fragments.
	--
	select @msg = @usage
		    + " sp_monitor 'report [using prefix=<string>]' "
		    + ", '<monitoring_type>' "
		    + @newline + @tabchar + @tabchar
		    + "[ <"

	exec sp_getmessage 19482, @supported output
	select @msg = @msg + @supported + "> ]"
	print @msg

	select @supported = "'deadlock'"
	exec sp_getmessage 19481, @msg output
	print @msg, @supported

	if (@output_type = 'terse')
		return 0

	print " "
	exec sp_getmessage 19483, @msg output
	print @msg, @mondeadlock
	print "	sp_monitor report, deadlock"

	print " "
	select @supported = "tempdb"	-- Reuse @variable for @dbname
	exec sp_getmessage 19484, @msg output
	print @msg, @prefix, @mondeadlock, @supported
	print "	%1!..sp_monitor 'report using prefix=%2!', deadlock"
		, @supported, @prefix

	print " "
	select @prefix = 'weekly_'
	     , @supported = "mondb"	-- Reuse @variable for @dbname
	exec sp_getmessage 19485, @msg output
	print @msg, @prefix, @mondeadlock, @supported
	print "	%1!..sp_monitor 'report using prefix=%2!', deadlock, 'May 25, 2006'"
		, @supported, @prefix
end	-- }
go

if (@@error != 0) select syb_quit()
go

exec sp_dbxt_recreate_proc sp_monitor_report
go

/*
** sp_monitor_report
**
**	Shell procedure to drive control to sub-procedure for given monitoring
**	type, and invoke its 'report' facility.
**
** Parameters:
**	@montype	- Monitoring type.
**	@reportcmd	- 'report' command, with optional prefix string.
**	@filter		- Filter arg, that may be used by sub-proc.
**	@output		- Monitoring-type-specific output modes.
**
** Returns:
**	Return value from sub-proc.
{
*/
create procedure sp_monitor_report(
			  @montype	varchar(30)
			, @reportcmd	varchar(30)
			, @filter	varchar(30)
			, @output	varchar(30)
) as
begin
	declare @retval			int
	      , @report_procname	varchar(30)
	      , @supported		varchar(30)

	-- Archiving logic is fairly generic based on the monitoring type,
	-- but reporting is really monitoring type specific. Hence, call back
	-- into the monitoring-type-specific driver procedure that will now
	-- know how to handle the report argument.
	--
	if (@montype IN (  'deadlock') )
	begin
		select @report_procname = "sp_monitor_" + @montype
		exec @retval = @report_procname @reportcmd, @filter, @output
	end
	else
	begin
		select @supported = "'deadlock'"
		raiserror 19481, @supported
		select @retval = 1
	end
	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_monitor_report_usage', 'anymode'
go
grant execute on sp_monitor_report_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_report', 'anymode'
go
grant execute on sp_monitor_report to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_connection_usage')
begin
	drop procedure sp_monitor_connection_usage
end
go
print "Installing sp_monitor_connection_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_connection')
begin
	drop procedure sp_monitor_connection
end
go
print "Installing sp_monitor_connection"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:39 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_connection [Total 1]
**
** 19260, "Invalid argument or unsupported command. Use sp_monitor 'help' to get usage information."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_connection [Total 2]
**
** 19264, "Usage: sp_monitor [ connection, [ cpu | diskio | elapsed time]]"
** 19265, "Examples: sp_monitor 'connection', 'elapsed time'"
*/
/*
** End spgenmsgs.pl output.
*/
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_connection_usage"
go

/*
** sp_monitor_connection_usage
**
**	Generate help/usage information in terse/verbose mode.
{
*/
create procedure sp_monitor_connection_usage(
				  @output_type	varchar(10)
) as
begin
	declare @sqlmsg	varchar(256)

	print " "
	-- First generate terse messages.
	exec sp_getmessage 19264, @sqlmsg output
	print @sqlmsg
	exec sp_getmessage 19265, @sqlmsg output
	print @sqlmsg

	if (@output_type = 'terse')
	begin
		return 0
	end

	print " "
	print "  -- Monitor all connections, by cpu usage:"
	print "	sp_monitor connection, 'cpu'"
	
	print " "
	print "  -- Monitor all connections, by disk I/O usage:"
	print "	sp_monitor connection, 'diskio'"
	
	return 0
end
go

if (@@error != 0) select syb_quit()
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_connection"
go

if ((select object_id("#conn_elapse")) is not NULL)
begin
        drop table #conn_elapse
end
go

if ((select object_id("#conn_cpu")) is not NULL)
begin
        drop table #conn_cpu
end
go

if ((select object_id("#conn_dsk")) is not NULL)
begin
        drop table #conn_dsk
end
go

/*
** This stored procedure is a subordinate stored procedure that is invoked from
** the parent stored procedure sp_monitor when "connection" is passed as the 
** argument. 
**
** This stored procedure provides performance metrics pertaining
** to user connections. It provides this information for each user connection
** that is active at the time the command is executed. A snapshot is collected
** from the monitoring tables of interest and presented. The output for each
** user connection is by default sorted based on the elapsed time. Elapsed time
** is defined as sum of cpu time and wait time i.e. the effective cpu time
** spent + the time spent waiting for acquiring resources needed for execution
** of the query.
** 
** Different sort options include "elapsed time", "cpu" and "diskio"
**
** This procedure uses tempdb. For this procedure to be run tempdb should 
** be sized depending on the number of active connections on the system and
** the size of the queries they are executing.
**
** Parameters:
**      @OrderBy 	- Parameter for ordering the output.
**
** Returns:
**      0       - upon sucessful completion
**      1       - If an error resulted.
{
*/

create procedure sp_monitor_connection(
			  @OrderBy 	varchar(30)	= NULL
) as

declare @upper_option varchar(100)
declare @option varchar(100)
declare @val int
declare @procname char(10)
declare @rtnstatus 	int
      , @this_spid	int	-- trace this spid
      , @whoami		varchar(30)

select @procname = "connection"
     , @whoami = object_name(@@procid, db_id('sybsystemprocs'))

exec @rtnstatus = sp_monitor_check_permission @whoami
if (@rtnstatus != 0)
	goto error

exec @rtnstatus = sp_monitor_verify_setup @procname
if (@rtnstatus != 0)
	goto error

exec @rtnstatus = sp_monitor_verify_cfgval @procname
if (@rtnstatus != 0)
	goto error

/* Convert the parameters to upper case */
select @upper_option=upper(@OrderBy)

/* If the option is elapsed time, order by the sum of CPUTime and Wait Time */
if @upper_option="ELAPSED TIME"
begin
	select @option="CPUTime+WaitTime"
end

/* If the option is cpu, order by CPUTime */
else if @upper_option = "CPU" 
begin
	select @option="CPUTime"
end

/* If the option is diskio, order by PhysicalReads */
else if @upper_option = "DISKIO" 
begin
	select @option="PhysicalReads"
end

/* 
** Put all the values in the monProcessSQLText and monProcessActivity
** tables into respective #temp tables.
** The reason this is done is to split the processing phase from
** the collection phase in order to minimize the chances of losing
** data on account of monitoring and SQL Processing at the same time
**
** monProcessSQLText provides the SQL Text that is executed at the
** instant the stored procedure is run
** 
** monProcessActivity provides detailed statistics about the processes
** at the instant the stored procedure is executed
**
** the mdaconfig built-in helps freeze monitoring when the data is being
** populated into the temp tables.
*/
select @rtnstatus = mdaconfig('freeze', 'begin')

select *, DisplayStats = 0
into #temp_P_SQLText 
from master..monProcessSQLText 

update #temp_P_SQLText
set a.DisplayStats = 1
from #temp_P_SQLText a
where a.LineNumber=(select min(LineNumber) from #temp_P_SQLText b
                        where b.SPID= a.SPID) 
and a.SequenceInLine=1


select * 
into #temp_P_Activity 
from master..monProcessActivity 

update #temp_P_Activity
set LocksHeld = 0 where LocksHeld < 0

/* Unfreeze the MDA counters */
select @rtnstatus = mdaconfig('freeze', 'end')

/* 
** By default we report in the descending order of Elapsed time 
** which is taken as sum of CPUTime and WaitTime 
** 
** The following is the core SQL that produces the o/p order 
** by the passed in option 
**
** This reports the following information
** 1. The spid for which data is presented
** 2. The LoginName for the spid
** 3. The Elapsed time
** 4. Number of locks held
** 5. SQL being executed at that instant by the task.
*/
if @option="CPUTime+WaitTime"
begin

	select	case when
		(st.DisplayStats=1) then
		convert(varchar(10),ps.SPID) else '' end as spid,
		case when(st.DisplayStats=1)
		then 
		convert(varchar(30),suser_name(sysp.suid))
		else '' end as LoginName,
		case when (st.DisplayStats=1)
		then convert(varchar(10),(ps.CPUTime+ps.WaitTime))
		else '' end as 'ElapsedTime',
		case when (st.DisplayStats=1)
		then convert(varchar(10),(ps.CPUTime))
		else '' end as 'CPU_Time',
		case when (st.DisplayStats=1) then
		convert(char(10), ps.PhysicalReads) 
		else '' end as 'Physical_Reads',
		case when (st.DisplayStats=1)
		then convert(varchar(10),ps.LocksHeld)
		else '' end as 'LocksHeld',
		st.SQLText as 'SQLText'
		into #conn_elapse
		from #temp_P_Activity ps,
		#temp_P_SQLText st, master.dbo.sysprocesses sysp
		where ps.SPID=st.SPID  AND ps.SPID != @@spid AND
		sysp.spid = ps.SPID 
		AND (ps.CPUTime+ps.WaitTime) ! = 0
		order by (ps.CPUTime+ps.WaitTime) desc, ps.SPID,
		st.LineNumber asc, st.SequenceInLine

		exec sp_autoformat @fulltabname = '#conn_elapse'

end
else if (@option = "CPUTime")
begin
	/* Core SQL that produces the o/p order by the passed in option */
	select case when 
		(st.DisplayStats=1) then
		convert(varchar(10), ps.SPID) else '' end as spid,
		case when(st.DisplayStats=1)
		then 
		convert(varchar(30), suser_name(sysp.suid)) 
		else '' end as LoginName,
		case when (st.DisplayStats=1)
		then convert(varchar(10),(ps.CPUTime+ps.WaitTime))
		else '' end as 'ElapsedTime',
		case when (st.DisplayStats=1)
		then convert(varchar(10),(ps.CPUTime))
		else '' end as 'CPU_Time',
		case when (st.DisplayStats=1) then
		convert(char(10), ps.PhysicalReads) 
		else '' end as 'Physical_Reads',
		case when (st.DisplayStats=1) then
		convert(varchar(10), ps.LocksHeld) 
		else '' end as 'LocksHeld', 
		st.SQLText as 'SQLText'
		into #conn_cpu
		from #temp_P_Activity ps, 
			#temp_P_SQLText st,
			master.dbo.sysprocesses sysp
		where ps.SPID != @@spid AND  ps.SPID=st.SPID  AND
			sysp.spid = ps.SPID 
		AND ps.CPUTime ! = 0
		order by ps.CPUTime desc, ps.SPID, 
		st.LineNumber asc, st.SequenceInLine


	exec sp_autoformat @fulltabname = '#conn_cpu'
end
else if (@option = "PhysicalReads")
begin
	/* Core SQL that produces the o/p order by the passed in option */
	select case when 
		(st.DisplayStats=1) then
		convert(varchar(10), ps.SPID) else '' end as spid,
		case when(st.DisplayStats=1)
		then 
		convert(varchar(30), suser_name(sysp.suid)) 
		else '' end as LoginName,
		case when (st.DisplayStats=1)
		then convert(varchar(10),(ps.CPUTime+ps.WaitTime))
		else '' end as 'ElapsedTime',
		case when (st.DisplayStats=1)
		then convert(varchar(10),(ps.CPUTime))
		else '' end as 'CPU_Time',
		case when (st.DisplayStats=1) then
		convert(char(10), ps.PhysicalReads) 
		else '' end as 'Physical_Reads',
		case when (st.DisplayStats=1) then
		convert(varchar(10), ps.LocksHeld) 
		else '' end as 'LocksHeld', 
		st.SQLText as 'SQLText'
		into #conn_dsk
		from #temp_P_Activity ps, 
			#temp_P_SQLText st,
			master.dbo.sysprocesses sysp
		where ps.SPID != @@spid AND  ps.SPID=st.SPID  AND
		sysp.spid = ps.SPID 
		AND ps.PhysicalReads ! = 0
		order by  ps.PhysicalReads desc, ps.SPID, 
		st.LineNumber asc, st.SequenceInLine

	exec sp_autoformat @fulltabname = '#conn_dsk'
end
else
begin
	raiserror 19260, "sp_monitor 'help', 'connection'"
	return 1
end


return(0)

error: 
return(1)	-- }
go
go
exec sp_procxmode 'sp_monitor_connection_usage', 'anymode'
go
grant execute on sp_monitor_connection_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_connection', 'anymode'
go
grant execute on sp_monitor_connection to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_event')
begin
	drop procedure sp_monitor_event
end
go
print "Installing sp_monitor_event"
go


/*
** Generated by spgenmsgs.pl on Tue Dec  2 17:55:42 2003
**
** raiserror Messages for monitor_event [Total 0]
**
** sp_getmessage Messages for monitor_event [Total 0]
**
** End spgenmsgs.pl output.
**
*/
-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_event"
go

if ((select object_id("#evop0")) is not NULL)
begin
        drop table #evop0
end
go

if ((select object_id("#evop1")) is not NULL)
begin
        drop table #evop1
end
go

if ((select object_id("#evop2")) is not NULL)
begin
        drop table #evop2
end
go

/*
** This stored procedure is a subordinate stored procedure that is invoked from
** the parent stored procedure sp_monitor when "event" is passed as the
** argument. 
**
** This stored procedure provides wait event metrics for all tasks in the system
** based on a snapshot collected when the sp_monitor "event" stored procedure is
** executed.
**
** If a specific <spid> is passed in it provides wait event information for
** that particular task.
**
** Wait events help analyze specific resource bottlenecks in the system.
**
** Parameters:
**      @spid		- spid for which the events needs to be displayed.
**
** Returns:
**      0       - upon sucessful completion
**      1       - If an error resulted.
*/

create procedure sp_monitor_event (@spid int = 0)
as

/* Parameters needed to support monitoring of sprocs, connections and stmts */
declare @rtnstatus 	int
declare @procname 	char(5)
declare @whoami 	varchar(30)
      , @tmptab		varchar(10)

select @procname = "event"
     , @whoami = object_name(@@procid, db_id('sybsystemprocs'))

exec @rtnstatus = sp_monitor_check_permission @whoami
if (@rtnstatus != 0)
        goto error

exec @rtnstatus = sp_monitor_verify_setup @procname
if (@rtnstatus != 0)
	goto error

select @procname = "event"

exec @rtnstatus = sp_monitor_verify_cfgval @procname
if (@rtnstatus != 0)
	goto error

/* Freeze the MDA counters */
select @rtnstatus = mdaconfig('freeze', 'begin')

/*
** If the spid is 0 which is the default, display the wait event
** information for all the user tasks in the descending order of wait times
** else display it only for the passed in spid.
*/
if (@spid < 0)
begin
	-- Display information about both user and system tasks
	select mpw.SPID, mpw.WaitTime , mwe.Description
	into #evop0
	from   master..monProcessWaits mpw,  master..monWaitEventInfo mwe
	where mpw.WaitEventID = mwe.WaitEventID
	  AND mpw.WaitTime != 0

	select @tmptab = "#evop0"
end
else
if (@spid = 0)
begin
         -- Display information only about all the user tasks
         select mpw.SPID, mpw.WaitTime , mwe.Description
         into #evop1
         from   master..monProcessWaits mpw,
	 	master..monWaitEventInfo mwe,
		master..monProcessLookup mpl
         where mpw.WaitEventID=mwe.WaitEventID
         AND mpw.WaitTime != 0
         AND mpl.SPID=mpw.SPID

	select @tmptab = "#evop1"
end
else
if (@spid > 0)
begin
	-- Display information for a particular SPID
	select mpw.WaitTime , mwe.Description
	into #evop2
	from   master..monProcessWaits mpw,  master..monWaitEventInfo mwe
	where mpw.SPID = @spid AND 
	mpw.WaitEventID=mwe.WaitEventID AND 
	mpw.WaitTime != 0

	select @tmptab = "#evop2"
end

/* Unfreeze the MDA counters */
select @rtnstatus = mdaconfig('freeze', 'end')

exec sp_autoformat @fulltabname = @tmptab
		  , @orderby = "order by WaitTime desc"
return(0)

error:
return(1)

go
go
exec sp_procxmode 'sp_monitor_event', 'anymode'
go
grant execute on sp_monitor_event to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_procedure')
begin
	drop procedure sp_monitor_procedure
end
go
print "Installing sp_monitor_procedure"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_procedure [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_procedure [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_procedure"
go

if ((select object_id("#procstats")) is not NULL)
begin
        drop table #procstats
end
go

/*
** Stored Procedure: sp_monitor "procedure"
**
** This stored procedure provides a report on performance metrics for 
** stored procedures that have been run on the server.
** It provides data for each execution of a stored procedure
** or average statistics for a stored procedure for
** all of the times it has recently been executed. Either or
** both reports can be generated depending on the input parameters.
** You can also specify a single procedure to report on.
**
** This procedure uses the monSysStatement Monitoring Table
** to collect statistics on the execution of stored procedures.
**
** Usage:
**	sp_monitor "procedure", [<dbname> [, <procname> [, <summary | detail>]]]
**
** Examples:
**	sp_monitor "procedure" -- Display summary for all stored procedures
**	sp_monitor "procedure", "detail" -- Display detail for all stored procs
**	sp_monitor "procedure", "db1" -- Display average data for database db1
**	sp_monitor "procedure", "db1", "detail" -- Detail for database db1
**	sp_monitor "procedure", "db1", "sproca" -- Display avg data for sproca
**	sp_monitor "procedure", "db1", "sproca", "detail" -- Detail for sproca
**
** If no procedure and database name is given then this procedure
** provides a report on all stored procedures run on the system
** since the sp_monitor "procedure" stored procedure was previously run.
**
** If a procedure and database name are provided, then a report
** on activity by that stored prcedure since the last time the
** sp_monitor "procedure" stored procedure was run is reported.
**
** All of the data is sorted in descending order of Elapsed Times.
**
** Parameters:
** dbname:   Optional.  Name of database for stored procedure. 
**		- Reports Average of stored procedure
**		  executions for the database specified.
**		- If not supplied or if 'summary' was supplied, it 
**		  reports Average stored procedure statistics for all databases.
**		- If 'detail' is supplied, then report detailed
**		  stored procedure execution statistics for the entire server.
**		REQUIRED if a stored procedure name is supplied.
** procname: Optional. Name of stored procedure to report on.
**		- If not supplied, statistics for all stored
**		  procedures is displayed for the given database.
**		- If value is 'summary', then only average execution
**		  statistics are reported for each procedure that
**		  has been executed for the given database.
**		- If value is 'detail', then details of procedure
**		  procedure execution and average execution
**		  statistics will be reported for each stored 
**		  procedure that executed for the given database.
** option:   Optional.  Additional information
**		- If stored procedure and database name are
**		  given and the value of option is 'summary' then
**		  only average execution statistics for the
**		  specified stored procedure are reported.
**		- If stored procedure and database name are
**		  given and the value of option is 'detail' then
**		  detailed statistics are provided
**		  for the passed in stored procedure.
**
{
*/

create procedure sp_monitor_procedure
@dbname varchar(30) = NULL,
@procname varchar(30) = "%",
@option varchar(30) = NULL
as

/* Parameters needed to support monitoring of sprocs, connections and stmts */
declare @output varchar(1024)
declare @dbid int
declare @procedureID int
declare @query_text varchar(1024)
declare @rptline char(255)
declare @averages int
declare @detail int
declare @sqlmsg	char(255)
declare @cursprocname varchar(30)
declare @myobjid int
declare @sybprocs_dbid int
declare @rtnstatus 	int
      , @mdacfg_retval	int
      , @whoami		varchar(30)

select @sybprocs_dbid = db_id('sybsystemprocs')
     ,  @whoami = object_name(@@procid, db_id('sybsystemprocs'))

select @myobjid = id
	from sybsystemprocs..sysobjects
	where name = 'sp_monitor_procedure'
	and type = 'P'

select @cursprocname = "procedure"

exec @rtnstatus = sp_monitor_check_permission @whoami
if (@rtnstatus != 0)
	goto error

exec @rtnstatus = sp_monitor_verify_setup @cursprocname

exec @mdacfg_retval = sp_monitor_verify_cfgval @cursprocname

if ((@rtnstatus != 0) or (@mdacfg_retval != 0))
        goto error

if (@procname is NULL)
begin
        select @procname = "%"
end

/*
** Process the input parameters.  Determine whether the
** all or average option was specified.
*/
if (@dbname = 'detail' and @procname = "%")
begin
	select @dbname = NULL
	select @averages = 0
	select @detail = 1
end
else if (@dbname = 'summary' and @procname = "%")
begin
	select @dbname = NULL
	select @averages = 1
	select @detail = 0
end
else if (@dbname is not NULL and @procname = 'detail')
begin
	select @procname = "%"
	select @averages = 1
	select @detail = 1
end
else if (@dbname is not NULL and @procname = 'summary')
begin
	select @procname = "%"
	select @averages = 1
	select @detail = 0
end
else if (@dbname is not NULL and @procname != "%" and @option = 'detail')
begin
	select @averages = 1
	select @detail = 1
end
else if (@dbname is not NULL and @procname != "%" and @option = 'summary')
begin
	select @averages = 1
	select @detail = 0
end
else
begin
	select @averages = 1
	select @detail = 0
end

/*
** Create temporary table here so either one of the insert
** statements below can populate it.  The ASE parser will not
** allow two select-into statements to the same table in the
** same procedure.
*/
select ProcName = convert(varchar(30), ""),
	DBName = convert(varchar(30), ""),
	SPID, DBID, ProcedureID, BatchID, CpuTime=convert(float,""), WaitTime=convert(float, ""),
	PhysicalReads=convert(float, ""), LogicalReads=convert(float,""),
	PacketsSent=convert(float, ""),
	StartTime = convert(datetime, ""),
	EndTime = convert(datetime, ""),
	ElapsedTime = convert(int, "")
into #procstats
from master..monSysStatement
where 1 = 2


/*
** Populate table with one row per stored procedure.
** These  queries aggregates data for all of the rows in the 
** monSysStatement table for a single instance of a stored procedure
** execution into a single row.  This yields a summary of the 
** statistics for the execution instance.
*/
if (@dbname is NULL)
begin
	insert #procstats
	select ProcName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"),
		DBName = isnull(db_name(DBID), "UNKNOWN"),
		SPID,
		DBID,
		ProcedureID,
		BatchID,
		CpuTime = sum(1.0*CpuTime),
		WaitTime = sum (1.0*WaitTime),
		PhysicalReads = sum(1.0*PhysicalReads),
		LogicalReads =  sum(1.0*LogicalReads),
		PacketsSent = sum(1.0*PacketsSent),
		StartTime = min(StartTime),
		EndTime = max(EndTime),
		ElapsedTime = datediff(ms, min(StartTime), max(EndTime))
	from master..monSysStatement
	group by SPID, DBID, ProcedureID, BatchID
	having ProcedureID != 0
	and not (DBID = @sybprocs_dbid and ProcedureID = @myobjid)
end
else 
begin
	insert #procstats
	select ProcName = isnull(object_name(ProcedureID, DBID),
						"UNKNOWN"),
		DBName = isnull(db_name(DBID), "UNKNOWN"),
		SPID,
		DBID,
		ProcedureID,
		BatchID,
		CpuTime = sum(1.0*CpuTime),
		WaitTime = sum (1.0*WaitTime),
		PhysicalReads = sum(1.0*PhysicalReads),
		LogicalReads =  sum(1.0*LogicalReads),
		PacketsSent = sum(1.0*PacketsSent),
		StartTime = min(StartTime),
		EndTime = max(EndTime),
		ElapsedTime = datediff(ms, min(StartTime), max(EndTime))
	from master..monSysStatement
	group by SPID, DBID, ProcedureID, BatchID
	having object_name(ProcedureID, DBID) like @procname
	and @dbname = db_name(DBID)

end


/*
** Display details of each execution of a stored procedure
*/
if (@detail = 1)
begin
	print "Detailed Procedure Statistics"
	print "============================="
	print ""
	select ProcName,
		DBName,
		SPID ,
		ElapsedTime = 
			convert(varchar(2), datediff(hh, StartTime,
					EndTime) % 24)
			+ ':'
			+ convert(varchar(2), datediff(mi, StartTime,
					EndTime) % 60)
			+ ':'
			+ convert(char(5),
			    convert(numeric(4,2),
				convert(float,
				  (datediff(ms, StartTime,
					EndTime) % 60000))/1000)),
		CpuTime = convert(int, CpuTime),
		WaitTime = convert(int, WaitTime),
		PhysicalReads = convert(int, PhysicalReads),
		LogicalReads = convert(int, LogicalReads),
		PacketsSent = convert(int, PacketsSent),
		StartTime = convert(char(8), StartTime, 108),
		EndTime = convert(char(8), EndTime, 108)
	into #procstats_detail
	from #procstats

	exec sp_autoformat @fulltabname = #procstats_detail
			 , @orderby = "order by ElapsedTime desc"
end

/*
** Display average statistics for each stored procedure
*/
if (@averages = 1)
begin
	print ""
	print "Average Procedure Statistics"
	print "============================"
	print ""
	select ProcName, 
		DBName, 
		AvgElapsedTime = avg(ElapsedTime),
		AvgCPUTime = avg(CpuTime),
		AvgWaitTime = avg(WaitTime),
		AvgPhysicalReads = avg(PhysicalReads),
		AvgLogicalReads = avg(LogicalReads),
		AvgPacketsSent = avg(PacketsSent),
		NumExecs = count(ProcName)
	into #procstats_avg
	from #procstats
	group by ProcName, DBName

	exec sp_autoformat @fulltabname = #procstats_avg
			 , @orderby = "order by AvgElapsedTime desc"
end

return (0)

error:
return(1)	-- }
go
go
exec sp_procxmode 'sp_monitor_procedure', 'anymode'
go
grant execute on sp_monitor_procedure to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_statement')
begin
	drop procedure sp_monitor_statement
end
go
print "Installing sp_monitor_statement"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_statement [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_statement [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/
go

-- Drop the stored procedure if it already exists
exec sp_dbxt_recreate_proc "sp_monitor_statement"
go

if ((select object_id("#stmt_elapse")) is not NULL)
begin
        drop table #stmt_elapse
end
go
if ((select object_id("#stmt_cpu")) is not NULL)
begin
        drop table #stmt_cpu
end
go
if ((select object_id("#stmt_dsk")) is not NULL)
begin
        drop table #stmt_dsk
end
go

/*
** This stored procedure is a subordinate stored procedure that is invoked from the
** parent stored procedure sp_monitor when "statement" is passed as the
** argument. 
**
** This stored procedure provides performance metrics pertaining
** to query statements. It provides this information for each statement
** that is active at the time the command is executed. A snapshot is collected
** from the monitoring tables of interest and presented. The output for each
** statement is by default sorted based on the elapsed time. Elapsed time
** is defined as sum of cpu time and wait time i.e. the effective cpu time
** spent + the time spent waiting for acquiring resources needed for execution
** of the query.
**
** Different sort options include "elapsed time", "cpu" and "diskio"
**
** This procedure uses tempdb. For this procedure to be run tempdb should 
** be sized depending on the number of active statements and
** the number of user connections on the system.
**
**
** Parameters:
**      @OrderBy                - Parameter for ordering the output.
**
** Returns:
**      0       - upon sucessful completion
**      1       - If an error resulted.
{
*/
go

create procedure sp_monitor_statement  @OrderBy varchar(30)=NULL
as

declare @upper_option varchar(100)
declare @option varchar(100)
declare @procname char(9)
declare @rtnstatus int
      , @whoami		varchar(30)

select @procname = "statement"
     , @whoami = object_name(@@procid, db_id('sybsystemprocs'))

exec @rtnstatus = sp_monitor_check_permission @whoami
if (@rtnstatus != 0)
	goto error

exec @rtnstatus = sp_monitor_verify_setup @procname
if (@rtnstatus != 0)
	goto error

exec @rtnstatus = sp_monitor_verify_cfgval @procname
if (@rtnstatus != 0)
	goto error

/* Convert the parameters to upper case */
select @upper_option=upper(@OrderBy)

/* If the option is elapsed time, order by the sum of CPUTime and Wait Time */
if @upper_option="ELAPSED TIME"
begin
	select @option="CpuTime+WaitTime"
end

/* If the option is cpu, order by CPUTime */
if @upper_option = "CPU" 
begin
	select @option="CpuTime"
end

/* If the option is diskio, order by PhysicalReads */
if @upper_option = "DISKIO" 
begin
	select @option="PhysicalReads"
end

/* 
** Freeze the MDA counters to get a consistent version across monitoring
** tables
*/
select @rtnstatus = mdaconfig('freeze', 'begin')

/*
** Put all the values in the monProcessSQLText, monProcessActivity and
** monProcessStatement tables into respective temptable
** The reason this is done is to split the processing phase from
** the collection phase in order to minimize the chances of losing
** data on account of monitoring and SQL Processing at the same time
**
** The logic behind the SQL is as follows :
**
** Display the SPID, and its corresponding SQL text. The SQL text has
** to be batched together for the given spid. The default sorting
** for the output is the descending order of the elapsed time which
** is CPUTime + Wait time
**
*/
select *, DisplayStats = 0
into #tmp_P_SQLText
from master..monProcessSQLText

update #tmp_P_SQLText
set a.DisplayStats = 1
from #tmp_P_SQLText a
where a.LineNumber=(select min(LineNumber) from #tmp_P_SQLText b
                        where b.SPID= a.SPID)
and a.SequenceInLine=1


select * 
into #tmp_P_Statement 
from master..monProcessStatement 

/* Unfreeze the MDA counters */
select @rtnstatus = mdaconfig('freeze', 'end')

if @option="CpuTime+WaitTime"
begin
	/* Core SQL that produces the o/p order by the passed in option */
	select case when 
			(st.DisplayStats=1) then 
			convert(char(5), ps.SPID) else '' end as spid,
			case when(st.DisplayStats=1)
			then 
			convert(varchar(30), suser_name(sysp.suid)) 
			else '' end as LoginName,
			case when (st.DisplayStats=1)
			then
			convert(char(10), ps.CpuTime+ps.WaitTime) 
			else '' end as 'ElapsedTime',
			case when (st.DisplayStats=1)
			then
			convert(varchar(10),ps.CpuTime) 
			else '' end as CpuTime,
			case when (st.DisplayStats=1)
			then
			convert(varchar(10), ps.PhysicalReads)
			else '' end as 'PhysicalReads',
			st.SQLText as 'SQLText'
			into #stmt_elapse
			from #tmp_P_Statement ps, 
			#tmp_P_SQLText st, master..sysprocesses sysp
			where ps.SPID=st.SPID  AND ps.SPID != @@spid AND
				sysp.spid = ps.SPID
			AND (ps.CpuTime+ps.WaitTime) ! = 0
			order by (ps.CpuTime+ps.WaitTime) desc, ps.SPID, 
			st.LineNumber asc, st.SequenceInLine

	exec sp_autoformat @fulltabname = "#stmt_elapse"
end
else if (@option="CpuTime")
begin
	/* Core SQL that produces the o/p order by the passed in option */
	select case when 
			(st.DisplayStats=1) then
			convert(varchar(10), ps.SPID) else '' end as spid,
			case when(st.DisplayStats=1)
			then 
			convert(varchar(30), suser_name(sysp.suid)) 
			else '' end as LoginName,
			case when (st.DisplayStats=1)
			then
			convert(char(10), ps.CpuTime+ps.WaitTime) 
			else '' end as 'ElapsedTime',
			case when (st.DisplayStats=1)
			then
			convert(varchar(10),ps.CpuTime) 
			else '' end as CpuTime,
			case when (st.DisplayStats=1)
			then
			convert(varchar(10), ps.PhysicalReads)
			else '' end as 'PhysicalReads',
			st.SQLText as 'SQLText'
			into #stmt_cpu
			from #tmp_P_Statement ps, 
			#tmp_P_SQLText st, master.dbo.sysprocesses sysp
			where ps.SPID=st.SPID  AND ps.SPID != @@spid AND
				sysp.spid = ps.SPID
				
			AND ps.CpuTime ! = 0
			order by ps.CpuTime desc, ps.SPID, 
			st.LineNumber asc, st.SequenceInLine

	exec sp_autoformat @fulltabname = "#stmt_cpu"

end
else 
begin
	/* Core SQL that produces the o/p order by the passed in option */
	select case when 
			(st.DisplayStats=1) then
			convert(varchar(10), ps.SPID) else '' end as spid,
			case when(st.DisplayStats=1)
			then 
			convert(varchar(30), suser_name(sysp.suid)) 
			else '' end as LoginName,
			case when (st.DisplayStats=1)
			then
			convert(char(10), ps.CpuTime+ps.WaitTime) 
			else '' end as 'ElapsedTime',
			case when (st.DisplayStats=1)
			then
			convert(varchar(10),ps.CpuTime) 
			else '' end as CpuTime,
			case when (st.DisplayStats=1)
			then
			convert(varchar(10), ps.PhysicalReads)
			else '' end as 'PhysicalReads',
			st.SQLText as 'SQLText'
			into #stmt_dsk
			from #tmp_P_Statement ps, 
			#tmp_P_SQLText st, master.dbo.sysprocesses sysp
			where ps.SPID=st.SPID  AND ps.SPID != @@spid AND
				sysp.spid = ps.SPID
				
			AND ps.PhysicalReads ! = 0
			order by ps.PhysicalReads desc, ps.SPID, 
			st.LineNumber asc, st.SequenceInLine

	exec sp_autoformat @fulltabname = "#stmt_dsk"
end

return(0)

error:
return(1)

go	-- }
go
exec sp_procxmode 'sp_monitor_statement', 'anymode'
go
grant execute on sp_monitor_statement to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_deadlock_usage')
begin
	drop procedure sp_monitor_deadlock_usage
end
go
print "Installing sp_monitor_deadlock_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_deadlock_getopts')
begin
	drop procedure sp_monitor_deadlock_getopts
end
go
print "Installing sp_monitor_deadlock_getopts"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_deadlock_count_by')
begin
	drop procedure sp_monitor_deadlock_count_by
end
go
print "Installing sp_monitor_deadlock_count_by"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_deadlock_verbose')
begin
	drop procedure sp_monitor_deadlock_verbose
end
go
print "Installing sp_monitor_deadlock_verbose"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_deadlock_driver')
begin
	drop procedure sp_monitor_deadlock_driver
end
go
print "Installing sp_monitor_deadlock_driver"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_deadlock')
begin
	drop procedure sp_monitor_deadlock
end
go
print "Installing sp_monitor_deadlock"
go

/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:39 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_deadlock [Total 2]
**
** 17870, "Table '%1!' does not exist in database '%2!'. %3!"
** 18640, "Unknown %1! option : '%2!'. Valid options are : %3!."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_deadlock [Total 23]
**
** 18954, "Usage:"
** 19494, "Configuration: %1!"
** 19497, "Configure '%1!' config option to some reasonable value, say, %2!."
** 19498, "Examples: Deadlock Analysis from %1!:"
** 19499, "%1!Generate deadlock analysis for all deadlocks:"
** 19500, "%1!Generate deadlock analysis for a particular deadlock ID:"
** 19501, "%1!Generate verbose deadlock analysis for a particular deadlock ID:"
** 19502, "%1!Generate verbose deadlock analysis with page diagnostics for a particular deadlock ID:"
** 19503, "%1!Generate frequency of deadlocks by application name:"
** 19504, "%1!Generate frequency of deadlocks by table name:"
** 19505, "Examples: Deadlock Analysis from data archived in '%1!' table:"
** 19506, "%1!First archive deadlock analysis for all data into '%2!' table in current database '%3!':"
** 19507, "%1!Generate deadlock analysis for all data from '%2!..%3!' table:"
** 19508, "%1!Generate deadlock analysis from archived data '%2!' for a particular deadlock ID:"
** 19509, "%1!Generate verbose ouput for a particular deadlock ID from '%2!' in current database '%3!':"
** 19510, "%1!Generate deadlock analysis from archived data for all deadlocks on a given date from '%2!':"
** 19511, "%1!Generate frequency of deadlocks by date:"
** 19512, "%1!Generate frequency of deadlocks by application name:"
** 19513, "%1!Generate frequency of deadlocks by table name:"
** 19514, "Examples: Use 'prefix' sub-clause under 'archive', 'report' commands to name the archive table uniquely:"
** 19515, "%1!Archive all data to table named '%2!%3!' in current database '%4!':"
** 19516, "%1!Report from table named '%2!%3!' in current database '%4!':"
** 19637, "Frequency of deadlocks, by '%1!' from '%2!.dbo.%3!':"
*/
/*
** End spgenmsgs.pl output.
*/
go

/*
** Create a dummy #mon__deadlock_info table just so that this sproc can
** be created. It'll be created for real at run-time.
*/
if (object_id('mon__deadlock_info') IS NOT NULL)
	drop table #mon__deadlock_info
go

-- Create a template table used to create this sproc.
-- Instantiate db/object names from various IDs, so that if we have to
-- archive this data, we have the right object identity available.
-- (Object IDs in particular can be re-cycled, so if we don't store the
-- object names, it can lead to mistaken identities.)
--
select *
     /*
     ** The following SQL below will generate columns equivalent to this
     ** inline SQL.
     **
     , instance_name(InstanceID)			as InstanceName
     , db_name(ObjectDBID) 				as ObjectDBName
     , db_name(HeldProcDBID) 				as HeldProcDBName
     , object_name(HeldProcedureID,HeldProcDBID) 	as HeldProcedureName
     , @@servername
     , getdate() 					as ArchiveDate
     **
     */
     -- Columns generated using sp_mon_archive_genSQL
     ,InstanceName=convert(varchar(30) NULL,instance_name(InstanceID))
     ,ObjectDBName=convert(varchar(30),db_name(ObjectDBID))
     ,HeldProcDBName=convert(varchar(30),db_name(HeldProcDBID))
     ,HeldProcedureName=convert(varchar(255) NULL,object_name(HeldProcedureID,HeldProcDBID))
     ,ServerName=convert(varchar(30) NULL, @@servername)
     ,ArchiveDate=convert(datetime NULL,'May 25 2006 12:00AM')
     ,VersionNum=convert(int NOT NULL, 1)
     ,ESDNum=convert(int NOT NULL, 0)
     ,EBFNum=convert(int NOT NULL, 0)

into #mon__deadlock_info
from master.dbo.monDeadLock
where 1 = 0
go

if (@@error != 0) select syb_quit()
go

-- ########################################################################### 
exec sp_dbxt_recreate_proc sp_monitor_deadlock_usage
go

/*
** sp_monitor_deadlock_usage
**
**	Print the usage help information for monitoring deadlocks.
**
** Parameters:
**	@output_type		- 'terse' or 'verbose'
**	@output_count_by_date
**	@output_count_by_appln
**	@output_count_by_object
**	@output_count_by_date_object
**	@opt_verbose
**	@opt_pagdiag
**				- Output mode phrases that are recognized as
**				  valid and used to report in usage messages.
{
*/
create procedure sp_monitor_deadlock_usage(
				  @output_type			varchar(8)
				, @output_count_by_date		varchar(30)
				, @output_count_by_appln	varchar(30)
				, @output_count_by_object	varchar(30)
				, @output_count_by_date_object	varchar(30)
				, @opt_verbose			varchar(7)
				, @opt_pagediag			varchar(8)
) as
begin
	declare	@dlk_table	varchar(30)
	      , @deadlock	varchar(8)
	      , @deadlock_table	varchar(30)
	      , @mdlk_table	varchar(30)
	      , @arch_dbname	varchar(10)
	      , @prefix		varchar(10)
	      , @verb_pagediag	varchar(30)
	      , @msg		varchar(200)
	      , @sp_command	varchar(80)
	      , @dlk_pipe_max_msgs_cfg		varchar(30)
	      , @dlk_pipe_max_msgs_value	int
	      , @newline	char(1)
	      , @tabchar	char(1)
	      , @indent		varchar(5)

	select @dlk_table 	= 'daily_monDeadLock'
	     , @deadlock	= 'deadlock'
	     , @deadlock_table	= 'monDeadLock'
	     , @mdlk_table	= 'master.dbo.monDeadLock'
	     , @arch_dbname	= 'mondb'
	     , @prefix		= 'daily_'
	     , @verb_pagediag	= @opt_verbose + "," + @opt_pagediag
	     , @dlk_pipe_max_msgs_cfg	= "deadlock pipe max messages"
	     , @dlk_pipe_max_msgs_value	= 200
	     , @newline		= char(10)
	     , @tabchar		= char(9)
	     , @indent		= "  -- "

	print " "
	exec sp_getmessage 18954, @msg output
	select @sp_command = @msg
			   + " sp_monitor '%1!' [ [, '@filters' ] [, '@output_modes' ] ]"
	print @sp_command, @deadlock

	select @sp_command = @msg + " sp_monitor '%1!' "
	print @sp_command, @deadlock
	print "		[  [, '<deadlockID>' | '<for Date>' ]"
	print "		   [, { '%1!' | '%2!' }"
		, @opt_verbose, @opt_pagediag

	-- reuse sp_command to build print format string w/newlines embedded.
	--
	select @sp_command = @tabchar + @tabchar + "     |"
			   + "{   '%1!' "
			   + @newline + @tabchar + @tabchar + @tabchar
			   + "| '%2!' "
			   + @newline + @tabchar + @tabchar + @tabchar
			   + "| '%3!' "
			   + @newline + @tabchar + @tabchar + @tabchar
			   + "| '%4!' "
			   + @newline + @tabchar + @tabchar 
			   + "      } ]"
	-- print "		     | {   '%1!' | '%2!' | '%3!' | '%4!' } ]"
	print @sp_command
		, @output_count_by_date
		, @output_count_by_appln
		, @output_count_by_object
		, @output_count_by_date_object
	print "		]"

	if (@output_type = 'terse')
	begin
		return 0
	end

	print " "

	-- Reuse @verb_pagediag to store term for msg.
	exec sp_getmessage 19494, @verb_pagediag output
	select @sp_command = "sp_monitor 'enable', " + "'" + @deadlock + "'"
	print @verb_pagediag, @sp_command

	exec sp_getmessage 19497, @msg output
	print @msg
		, @dlk_pipe_max_msgs_cfg, @dlk_pipe_max_msgs_value
	
	select @sp_command = "sp_configure '" + @dlk_pipe_max_msgs_cfg + "'"
			   + ", " + convert(varchar, @dlk_pipe_max_msgs_value)

	print @verb_pagediag, @sp_command

	print " "
	exec sp_getmessage 19498, @msg output
	print @msg, @mdlk_table

	print " "
	exec sp_getmessage 19499, @msg output
	print @msg, @indent
	print "	sp_monitor 'deadlock'"

	print " "
	exec sp_getmessage 19500, @msg output
	print @msg, @indent
	print "	sp_monitor 'deadlock', '10'"

	print " "
	exec sp_getmessage 19501, @msg output
	print @msg, @indent
	print "	sp_monitor 'deadlock', '10', '%1!'"
			, @opt_verbose

	print " "
	exec sp_getmessage 19502, @msg output
	print @msg, @indent
	print "	sp_monitor 'deadlock', '10', '%1!'"
			, @verb_pagediag

	print " "
	exec sp_getmessage 19503, @msg output
	print @msg, @indent
	print "	sp_monitor 'deadlock', NULL, '%1!'"
		, @output_count_by_appln

	print " "
	exec sp_getmessage 19504, @msg output
	print @msg, @indent
	print "	sp_monitor 'deadlock', NULL, '%1!'"
		, @output_count_by_object

	print " "
	exec sp_getmessage 19505, @msg output
	print @msg, @deadlock_table

	print " "
	exec sp_getmessage 19506, @msg output
	print @msg, @indent , @deadlock_table , @arch_dbname
	print "	sp_monitor 'archive', 'deadlock'"

	print " "
	exec sp_getmessage 19507, @msg output
	print @msg, @indent, @arch_dbname , @deadlock_table
	print "	%1!..sp_monitor 'report', 'deadlock'"
		, @arch_dbname
		, @deadlock_table

	print " "
	exec sp_getmessage 19508, @msg output
	print @msg, @indent, @deadlock_table
	print "	sp_monitor 'report', 'deadlock', '10'"

	print " "
	exec sp_getmessage 19509, @msg output
	print @msg, @indent, @deadlock_table , @arch_dbname
	print "	sp_monitor 'report', 'deadlock', '10', '%1!'"
		, @opt_verbose

	print " "
	exec sp_getmessage 19510, @msg output
	print @msg, @indent, @deadlock_table 
	print "	sp_monitor 'report', 'deadlock', 'Mar 16 2006'"

	print " "
	exec sp_getmessage 19511, @msg output
	print @msg, @indent
	print "	sp_monitor 'report', 'deadlock', NULL, '%1!'"
		, @output_count_by_date

	print " "
	exec sp_getmessage 19512, @msg output
	print @msg, @indent
	print "	sp_monitor 'report', 'deadlock', NULL, '%1!'"
		, @output_count_by_appln

	print " "
	exec sp_getmessage 19513, @msg output
	print @msg, @indent
	print "	sp_monitor 'report', 'deadlock', NULL, '%1!'"
		, @output_count_by_object

	print " "
	exec sp_getmessage 19514, @msg output
	print @msg

	print " "
	exec sp_getmessage 19515, @msg output
	print @msg, @indent
		, @prefix, @deadlock_table , @arch_dbname
	print "	sp_monitor 'archive, prefix=%1!', 'deadlock'"
		, @prefix

	print " "
	exec sp_getmessage 19516, @msg output
	print @msg, @indent
		, @prefix, @deadlock_table , @arch_dbname
	print "	sp_monitor 'report, prefix=%1!', 'deadlock'"
		, @prefix

end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ########################################################################### 
exec sp_dbxt_recreate_proc sp_monitor_deadlock_getopts
go

/*
** sp_monitor_deadlock_getopts
**
**	Extract the individual options from a comma-separated print options
**	string, and set local output variables to pass back to the caller.
**
** Parameters:
**	@output			- User-specified output options.
**	@opt_verbose_str	- Name of verbose option
**	@opt_pagediag_str	- Name of page diagnostics option
**	@opt_verbose		- If verbose option was requested.
**	@opt_pagediag		- If page diagnostics was requested.
{
*/
create procedure sp_monitor_deadlock_getopts(
				  @output		varchar(30)
				, @opt_verbose_str	varchar(7)
				, @opt_pagediag_str	varchar(8)
				, @opt_verbose		int	= 0 output
				, @opt_pagediag		int	= 0 output
) as
begin
	declare @opt_sep	char(1)
	      , @sep_index	int
	      , @option_item	varchar(30)
	      , @option_found	int
	      , @valid_options	varchar(30)

	if (@output IS NULL)
		return 0

	-- Extract each comma-separated output option.
	select @opt_sep = ','
	while (1 = 1)
	begin
		exec @option_found = sp_getopts @output
						, @opt_sep
						, @option_item output
						, @output output
		if (@option_found = 0)
			return 0

		-- Decode option specified and set local variable.
		--
		if (@option_item = @opt_verbose_str)
			select @opt_verbose = 1

		else if (@option_item = @opt_pagediag_str)
			select @opt_pagediag = 1

		else
		begin
			-- Build list of valid print options.
			select @valid_options = @opt_verbose_str
					      + @opt_sep
					      + @opt_pagediag_str

			raiserror 18640, "print", @option_item, @valid_options
			return 1
		end
	end

	return 0

end	-- }
if (@@error != 0) select syb_quit()
go

-- ########################################################################### 
exec sp_dbxt_recreate_proc sp_monitor_deadlock_count_by
go

/*
** sp_monitor_deadlock_count_by
**
**	Process the @output option, if supplied. We support only a few types
**	of output options, mainly to generate summary data. The caller tells
**	us what options to support. Check if @output is one of them, and
**	generate the required frequency data.
**
** Parameters:
**	@deadlock_tabname	- Table containing deadlock event data.
**	@dbname			- DB where @deadlock_tabname exists.
**	@temp_tablename		- #temp table created in caller for processing.
**	@output_count_by_date
**	@output_count_by_appln
**	@output_count_by_object
**	@output_count_by_date_object
**				- String constants for various output modes.
**	@output			- Use supplied output mode argument.
**
** Returns:
**	0	- If all went well.
**	!= 0	- Otherwise.
{
*/
create procedure sp_monitor_deadlock_count_by(
				  @deadlock_tabname		varchar(30)
				, @dbname			varchar(30)
				, @temp_tablename		varchar(30)
				, @output_count_by_date		varchar(30)
				, @output_count_by_appln	varchar(30)
				, @output_count_by_object	varchar(30)
				, @output_count_by_date_object	varchar(30)
				, @output			varchar(30)
) as 
begin
	declare @sqlstmt	varchar(256)
	      , @mdacfg_retval	int
	      , @retval		int
	      , @insert		varchar(6)
	      , @select		varchar(6)

	-- We only proces 'count by ' output options here. Anything else
	-- might be a valid option, but we don't check for that here.
	-- 
	if ((@output IS NULL) OR (@output NOT LIKE "%count by%" ))
		return 0

	-- ==================================================================
	-- Process the output modes, displaying summary only if so
	-- requested. Then bail.
	-- For all output modes, cache the monitor table info into a #temp
	-- table, doing the GROUP BY while generating the #temp table.
	-- Then autoformat the results from that #temp for readability.
	--
	if (@output NOT IN (  @output_count_by_date
	 		      , @output_count_by_appln
			      , @output_count_by_object
			      , @output_count_by_date_object
			   ) )
	begin
		select @sqlstmt = "'" + @output_count_by_date + "'"
				+ ", '" + @output_count_by_appln + "'"
				+ ", '" + @output_count_by_object + "'"
				+ ", '" + @output_count_by_date_object + "'"

		raiserror 18640, "output", @output, @sqlstmt
		return 1
	end

	select @insert 	= "INSERT"
	     , @select	= "SELECT"

	if (@output = @output_count_by_date)
	begin
		print " " 
		exec sp_getmessage 19637, @sqlstmt output
		print @sqlstmt, 'ResolveDate' , @dbname, @deadlock_tabname
		print " " 

		-- Create an empty template table for future inserts.
		create table #freq_by_resolvedate(
				  ResolveDate	date
				, Frequency	int
		)
		select @sqlstmt = @insert
				+ " #freq_by_resolvedate "
				+ @select
				+ " CONVERT(DATE, ResolveTime)"
				+ ", COUNT(DISTINCT DeadlockID)"
				+ " FROM " + @temp_tablename
				+ " GROUP BY CONVERT(DATE, ResolveTime)"

		exec @retval = sp_exec_SQL @sqlstmt, @output

		if (@retval = 0)
			exec sp_autoformat
				  @fulltabname = #freq_by_resolvedate
				, @orderbyclause = "order by ResolveDate asc"
	end

	else if (@output = @output_count_by_appln)
	begin
		print " " 
		exec sp_getmessage 19637, @sqlstmt output
		print @sqlstmt, 'HeldApplName' , @dbname, @deadlock_tabname
		print " " 

		-- Create an empty template table for future inserts.
		create table #freq_by_applname(
				  ApplName	varchar(30)
				, Frequency	int
		)

		select @sqlstmt = @insert + " #freq_by_applname "
				+ @select
				+ " HeldApplName "
				+ ", COUNT(DISTINCT DeadlockID)"
				+ " FROM " + @temp_tablename
				+ " GROUP BY HeldApplName"

		exec @retval = sp_exec_SQL @sqlstmt, @output

		if (@retval = 0)
			exec sp_autoformat
				  @fulltabname = #freq_by_applname
				, @orderbyclause = "order by HeldApplName asc"
	end

	else if (@output = @output_count_by_object)
	begin

		print " " 
		exec sp_getmessage 19637, @sqlstmt output
		print @sqlstmt, 'DBName, ObjectName' , @dbname, @deadlock_tabname
		print " " 

		-- Create an empty template table for future inserts.
		select DBName = db_name()
		     , ObjectName = o.name
		     , Frequency = convert(int null, 0)
		into #freq_by_name
		from master.dbo.sysobjects o
		where 1 = 0

		-- Only generate the columns we really need to generate the
		-- group by counts into a #temptable.
		--
		select @sqlstmt = @insert + " #freq_by_name "
				+ @select
				+ " ObjectDBName"
				+ ", ObjectName"
				+ ", count(DeadlockID)"
				+ " FROM " + @temp_tablename
				+ " GROUP BY ObjectDBName, ObjectName"

		exec @retval = sp_exec_SQL @sqlstmt, @output

		if (@retval = 0)
			exec sp_autoformat
				  @fulltabname = #freq_by_name
				, @orderbyclause = "order by 1, 2"
	end

	else if (@output = @output_count_by_date_object)
	begin

		print " " 
		exec sp_getmessage 19637, @sqlstmt output
		print @sqlstmt, 'ResolveDate, DBName, ObjectName' 
			, @dbname, @deadlock_tabname
		print " " 

		-- Create an empty template table for future inserts.
		select ResolveDate = CONVERT(DATE, o.crdate)
		     , DBName = db_name()
		     , ObjectName = o.name
		     , Frequency = convert(int null, 0)
		into #freq_by_date_name
		from master.dbo.sysobjects o
		where 1 = 0

		-- Only generate the columns we really need to generate the
		-- group by counts into a #temptable.
		--
		select @sqlstmt = @insert + " #freq_by_date_name "
				+ @select
				+ " CONVERT(DATE, ResolveTime)"
				+ ", ObjectDBName"
				+ ", ObjectName"
				+ ", count(DeadlockID) "
				+ " FROM " + @temp_tablename
				+ " GROUP BY "
				+ "CONVERT(DATE, ResolveTime), ObjectDBName, ObjectName"

		exec @retval = sp_exec_SQL @sqlstmt, @output

		if (@retval = 0)
			exec sp_autoformat
				  @fulltabname = #freq_by_date_name
				, @orderbyclause = "order by 1, 2, 3"
	end

	-- Single return point for all "count by" options.
	-- Any error from sp_exec_SQL will be returned back via this stmt.
	return @retval

end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ########################################################################### 
exec sp_dbxt_recreate_proc sp_monitor_deadlock_verbose
go

/*
** sp_monitor_deadlock_verbose
**
**	Generate 'verbose' output for deadlock tracing. This involves stuff
**	like user/application names. Also, if a stored procedure was
**	involved in a deadlock, decode the stored procedure's name from the
**	various dbid/objectid data we have, and call the text analyzer to
**	spit out the fragment of SQL that was probably running when the
**	deadlock event occured.
**
** Parameters:
**	@deadlockid_str		- 'Deadlock ID' string.
**	@dlk_id_inner		- Deadlock ID being processed.
**	@heldspid		- SPID of task holding locks.
**	@heldusername		- User name of holding SPID.
**	@heldapplname		- Application name of holding SPID.
**	@waitusername		- User name of waiting SPID.
**	@heldprocdbid		- DBID of sproc (if any) of holding task.
**	@heldproecdureid	- Object ID of sproc (if any) of holding task.
**	@heldprocdbname		- Name of db of sproc executed by holding task.
**	@heldprocedurename	- Name of sproc executed by holding task.
**	@heldlinenumber		- Line # where holding SPID was executing.
**	@objdbid		- DBID of object whose page was involved.
**	@pagenumber		- Page # of page involved in deadlock.
**	@objname		- Name of object holding lock on page.
**	@pagediag		- Whether to call page diagnostics built-ins.
**
** Returns:
**	0	- If everything went well; 
**	!=0	- In case of any errors.
{
*/
create procedure sp_monitor_deadlock_verbose(
				  @deadlockid_str	varchar(12)	= NULL
				, @dlk_id_inner		int		= NULL
				, @heldspid		int		= NULL
				, @heldusername		varchar(30)	= NULL
				, @heldapplname		varchar(30)	= NULL
				, @waitusername		varchar(30)	= NULL

				, @heldprocdbid		int		= NULL
				, @heldprocedureid	int		= NULL
				, @heldprocdbname	varchar(30)	= NULL
				, @heldprocedurename	varchar(255)	= NULL
				, @heldlinenumber	int		= NULL
				, @objdbid		int		= NULL
				, @pagenumber		int		= NULL
				, @objname		varchar(30)	= NULL
				, @pagediag		int		= 0
				, @heldsrcID		varchar(30)	= NULL
				, @waitsrcID		varchar(30)	= NULL
) as
begin

	declare
	      -- Variable to store name of sp_showtext with db-context.
	        @sp_showtext		varchar(100)
	      
	      -- Fields extracted from a page header.
	      --
	      , @page_objid		int
	      , @page_indid		int
	      , @page_ptnid		int
	      , @curr_objname		varchar(30)
	      , @pagetype		varchar(20)
	      , @hpdbname_lcl		varchar(30)
	      , @hprocname_lcl		varchar(255)
	      , @noname			varchar(6)

	print "  %1! %2! Holding: [user name: '%3!' Appl Name: '%4!' procdbid='%5!' procid='%6!'] Waiting: [user name: '%7!']"
		, @deadlockid_str
		, @dlk_id_inner
		, @heldusername
		, @heldapplname
		, @heldprocdbid
		, @heldprocedureid
		, @waitusername

	-- Don't try to report these if they come out NULL, which they
	-- will if the data being reported on is from a 125x archive.
	--
	if ((@heldsrcID IS NOT NULL) or (@waitsrcID IS NOT NULL))
	begin
		print "  %1! %2! Held lock at '%3!' Waiting for lock at '%4!'"
			, @deadlockid_str
			, @dlk_id_inner
			, @heldsrcID
			, @waitsrcID
	end

	select @noname	= "<null>"

	-- ==================================================================
	-- Extract page's object identity, validate that it is still allocated
	-- to @objname. Then find out its partition id, and index ID. Report
	-- what kind of page it is (data, index, text etc.)
	--
	if (    (@pagediag = 1)
	    and (@objname IS NOT NULL) and (@pagenumber > 0)
	    and (@objdbid > 0))
	begin
		select @page_objid = pageinfo(@objdbid, @pagenumber,
					      "object id on extent")

		-- If page still belongs to the same object as it was when
		-- the deadlock was recorded, go back to the page and find
		-- out if it's an index/data/text page. Report it.
		--
		select @curr_objname = object_name(@page_objid, @objdbid)

		-- @objname is NOT NULL from above, so following will fail if
		-- @curr_objname is NULL (i.e. page is not currently allocated
		-- to any object) and will pass if page is still allocated
		-- to the same object as it was when the deadlock happened.
		--
		if (@curr_objname = @objname)	
		begin
			select @page_indid = pageinfo(@objdbid, @pagenumber
						      , "index id")

			select @pagetype = case @page_indid
					    when 0	then "data"
					    when 1	then "clustered index"
					    when 255	then "text"
					    else	"non-clustered index"
					  end

			print "  %1! %2! Page %3! is a '%4!' page, with index id=%5!, of object '%6!'"
				, @deadlockid_str, @dlk_id_inner
				, @pagenumber, @pagetype, @page_indid, @objname
		end
		else
		begin
			if (@curr_objname IS NULL)
				select @curr_objname = "<unallocated>"

			print "  %1! %2! Page %3! in dbid %4! now belongs to object '%5!' and not to object '%6!'"
				, @deadlockid_str, @dlk_id_inner
				, @pagenumber, @objdbid
				, @curr_objname, @objname
		end
	end
	else if (@pagediag = 1)
	begin
		print "  %1! %2! Requested page diagnostics skipped, as page IDs involved in deadlock were 0. Deadlock possibly due to table-level locks."
			, @deadlockid_str, @dlk_id_inner

	end

	if (     (@heldprocdbid IS NULL )
	     or  (@heldprocedureid IS NULL)
	     or  (@heldprocdbid = 0)
	     or  (@heldprocedureid = 0)
	   )
	begin
		print "  %1! %2! Holding task [dbid=%3! procedureid=%4!] was not executing a procedure at the time of the deadlock."
			, @deadlockid_str, @dlk_id_inner
			, @heldprocdbid, @heldprocedureid
		return
	end

	-- ==================================================================
	-- Check to see if the derived dbname/procname values are NULL. If so,
	-- print them as null and bail out. We can't process for SQL text
	-- if the names themselves are NULL.
	--
	select @hpdbname_lcl = case when @heldprocdbname IS NULL
				   then @noname
				   else @heldprocdbname
				end
	      , @hprocname_lcl = case when @heldprocedurename IS NULL
	      			      then @noname
				      else @heldprocedurename
				end

	print "  %1! %2! Holding procedure [dbname: '%3!' (dbid=%4!) name: '%5!' (id=%6!)]"
		, @deadlockid_str, @dlk_id_inner
		, @hpdbname_lcl, @heldprocdbid
		, @hprocname_lcl, @heldprocedureid

	if (@heldprocdbname IS NULL) or (@heldprocedurename IS NULL)
	begin
		print "  %1! %2! Cannot generate SQL text that was running at the time of the deadlock as the procedure/database names are NULL."
			, @deadlockid_str, @dlk_id_inner
		return 0
	end

	-- When we run deadlock analysis from an archive table, the archived
	-- data might not be in the original server where the deadlock event
	-- occurred.  In that case, it's possible that the procedure involved
	-- and the database that the sproc lives (lived) in, does not even
	-- exist in the server in which the deadlock analyzer is running.
	-- Check for the existence and match of identity of the sproc that
	-- was involved in the deadlock before calling for its SQL text.
	--
	if (   (@heldprocdbname != db_name(@heldprocdbid))
	    or (@heldprocedurename != object_name(@heldprocedureid,
	    					  @heldprocdbid))
	   )
	begin
		print "  %1! %2! Could not find procedure with id=%3! in database: '%4!'. Guessing that SQL text using db/procedure names might still match."
			, @deadlockid_str, @dlk_id_inner
			, @heldprocedureid, @heldprocdbid
	end

	print " " 

	if (@heldprocedurename IS NOT NULL)
	begin
		print "  %1! %2! Holding SPID %3! was executing following SQL fragment at line %4!:"
			, @deadlockid_str, @dlk_id_inner
			, @heldspid, @heldlinenumber 

		select @sp_showtext = @heldprocdbname
				    + case 
				        when @heldprocdbname IS NOT NULL
					then ".."
					else ""
				      end
				    + "sp_showtext"

		-- Execute the sproc to pull out the context block where 
		-- the deadlock occured.
		--
		exec @sp_showtext @objname = @heldprocedurename
				, @startline = @heldlinenumber
				, @numlines_or_ctxt = 10
				, @printopts = 'context,linenumbers'
		print " "
	end
	return 0

end	-- }
go

if (@@error != 0) select syb_quit()
go

-- ########################################################################### 
exec sp_dbxt_recreate_proc sp_monitor_deadlock_driver
go

/*
** sp_monitor_deadlock_driver
**
**	Main driver procedure to perform deadlock analysis.
**
** Parameters:
**	@opt_verbose		- Verbose output.
**	@opt_pagediag		- Generate page diagnostics also.
**				  (Only works if @opt_verbose is also 1.)
**	@num_deadlocks		- (Output) # of deadlock events processed.
**
** Returns:
**	Nothing.
{
*/
create procedure sp_monitor_deadlock_driver(
			  @opt_verbose		int	= 0
			, @opt_pagediag		int	= 0
			, @num_deadlocks	int	output
) as
begin
	declare @dlk_id		int
	      , @retval		int
	      , @resolve_time	datetime
	      , @dbname		varchar(30)

	      -- Variables to retrieve info about each line-item for
	      -- a given deadlock ID.

	      , @dlk_id_inner	int
	      , @held_spid	int
	      , @wait_spid	int
	      , @held_cmd	varchar(30)
	      , @held_xactname	varchar(255)

	      -- , @wait_cmd	varchar(30)
	      -- , @wait_xactname	varchar(255)
	      , @servername	varchar(30)
	      , @objname	varchar(255)
	      , @instancename	varchar(30)
	      , @objdbid	int
	      , @pagenumber	int
	      , @pagediag	int	--whether to call page diagnostics
	      , @heldlocktype	varchar(20)
	      , @waitlocktype	varchar(20)
	      , @heldusername	varchar(30)
	      , @heldapplname	varchar(30)
	      , @waitusername	varchar(30)

	      -- Location in code where deadlock occurred.
	      , @heldsrcID	varchar(30)
	      , @waitsrcID	varchar(30)

	      -- Get identity of proc (if any) of holding spid.
	      --
	     , @heldprocdbid	int
	     , @heldprocedureid	int
	     , @heldlinenumber	int
	     , @heldprocdbname		varchar(30)
	     , @heldprocedurename	varchar(255)

	      -- Common phrases used in print outputs. Centralize for
	      -- easy 'bgrep' processing.
	      , @deadlockid_str	varchar(12)

	select @num_deadlocks 	= 0
	     , @deadlockid_str	= "Deadlock ID"

	-- Process one row for given deadlock ID or all rows in the table,
	-- and produce a report for each deadlock occurence, to show the
	-- wait-for graph in English-language 1204'esque output.
	--
	declare dlitem_cur cursor for
	select DISTINCT ServerName, DeadlockID, ObjectDBName, 
					ResolveTime, InstanceName
	from #mon__deadlock_info

	open dlitem_cur

	declare dlitem_cur_inner cursor for
	select    DeadlockID
		, HeldSPID
		, WaitSPID
		, HeldCommand
		, HeldTranName
		, ObjectDBID
		, ObjectName
		, PageNumber
		, HeldLockType
		, WaitLockType

		-- Following Fields reported under 'verbose' output model
		, HeldUserName
		, HeldApplName
		, WaitUserName

		, HeldProcDBID
		, HeldProcedureID
		, HeldProcDBName
		, HeldProcedureName
		, HeldLineNumber
		, HeldSourceCodeID
		, WaitSourceCodeID

	from #mon__deadlock_info
	where DeadlockID = @dlk_id
	  and ResolveTime = @resolve_time

	while (1 = 1)
	begin	-- {
		fetch dlitem_cur into @servername, @dlk_id
				    , @dbname
				    , @resolve_time
				    , @instancename
		if (@@sqlstatus != 0)
			break

		select @num_deadlocks = @num_deadlocks + 1

		print ' '
		if (@@clustermode = 'shared disk cluster')
		begin
			print "****** Server: '%1!' %2! %3! Dbname: '%4!' Resolve Time: %5! Detected by Instance: '%6!' ****** "
				, @servername
				, @deadlockid_str
				, @dlk_id, @dbname
				, @resolve_time
				, @instancename
		end
		else
		begin
			print "****** Server: '%1!' %2! %3! Dbname: '%4!' Resolve Time: %5! ****** "
				, @servername
                                , @deadlockid_str
                  		, @dlk_id, @dbname 
				, @resolve_time
		end
		-- For this DeadlockID, go back and process all rows.
		open dlitem_cur_inner

		while (1 = 1)
		begin	-- {

			fetch dlitem_cur_inner into @dlk_id_inner
						  , @held_spid
						  , @wait_spid
						  , @held_cmd
						  , @held_xactname
						  , @objdbid
						  , @objname
						  , @pagenumber
						  , @heldlocktype
						  , @waitlocktype
						  , @heldusername
						  , @heldapplname
						  , @waitusername
						  , @heldprocdbid
						  , @heldprocedureid
						  , @heldprocdbname
						  , @heldprocedurename
						  , @heldlinenumber
						  , @heldsrcID
						  , @waitsrcID

			if (@@sqlstatus != 0)
				break

			print "  %1! %2! Spid %3! was waiting for '%4!' lock on dbid=%5! object '%6!' page=%7!"
				, @deadlockid_str
				, @dlk_id_inner
				, @wait_spid
				, @waitlocktype
				, @objdbid
				, @objname
				, @pagenumber

			print "  %1! %2! Spid %3! was holding '%4!' lock on object '%5!' page=%6!. Command: '%7!', Holding TranName: '%8!'"
				, @deadlockid_str
				, @dlk_id_inner
				, @held_spid
				, @heldlocktype
				, @objname
				, @pagenumber
				, @held_cmd
				, @held_xactname

			if (@opt_verbose = 1)
			begin	-- {

				exec @retval = sp_monitor_deadlock_verbose
						  @deadlockid_str
						, @dlk_id_inner
						, @held_spid
						, @heldusername
						, @heldapplname
						, @waitusername

						, @heldprocdbid
						, @heldprocedureid
						, @heldprocdbname
						, @heldprocedurename
						, @heldlinenumber

						, @objdbid
						, @pagenumber
						, @objname
						, @opt_pagediag

						, @heldsrcID
						, @waitsrcID
						  
			end	-- }

		end	-- }

		close dlitem_cur_inner

	end	-- }
	close dlitem_cur

	deallocate cursor dlitem_cur_inner
	deallocate cursor dlitem_cur

end	-- }
go

if (@@error != 0) select syb_quit()
go

drop table #mon__deadlock_info
go

-- ########################################################################### 
exec sp_dbxt_recreate_proc sp_monitor_deadlock
go

/*
** sp_monitor_deadlock
**
**	The documented user-interface is via 'sp_monitor deadlock'.
**	Caller might invoke us in the following ways:
**
**	-- With no arguments, process deadlock info from monDeadLock table:
**	sp_monitor deadlock
**
**	-- Process monDeadLock for all deadlocks on a given date entry.
**	sp_monitor deadlock, "Apr 27 2006"
**
**	-- Asking us to archive data in the monDeadLock table in the current db:
**	sp_monitor "archive", 'deadlock'
**
**	-- Asking us to archive data in the monDeadLock table in tempdb db:
**	tempdb..sp_monitor "archive", deadlock
**
**	-- Process all rows from the archive table (monDeadLock) in the 
**	-- current db.
**	sp_monitor [, 'report' , ] deadlock
**	sp_monitor 'report', deadlock
**
**	-- If you have archived data in default archive-named 'monDeadLock',
** 	-- then the following commands works identically when issued from the
**	-- archive db (e.g. mondb), or from 'master'. It will simply process
**	-- the data from 'monDeadLock' in the current db.
**
**	sp_monitor deadlock
**	tempdb..sp_monitor deadlock
**	tempdb..sp_monitor report, deadlock
**	master..sp_monitor report, deadlock

**	-- Process all rows from the archived table, 'daily_monDeadLock' in
**	-- pubs2:
**	pubs2..sp_monitor "report using prefix=daily_", deadlock
**
**	-- Process deadlock_info table for a given deadlock ID, from an archive
**	-- table named "daily_monDeadLock".
**	--
**	sp_monitor "report using prefix=daily_", deadlock, "3456"
**
** Parameters:
**	@deadlock_tabname	- Name of table to process deadlock events from.
**	@dlkID_or_for_Date	- Gives either the deadlock ID to process,
**				  or the date (ResolveTime) on which all
**				  deadlock events have to be processed.
**	@output			- Output mode (terse/verbose).
{
*/
create procedure sp_monitor_deadlock(
			  @arg1		varchar(30)	= NULL
			, @arg2		varchar(30) 	= NULL
			, @arg3		varchar(30) 	= NULL
) as
begin
	declare @sqlstmt	varchar(1500)
	      , @dbname		varchar(30)
	      , @num_deadlocks	int
	      , @retval		int		-- from sproc.
	      , @mdacfg_retval	int
	      , @num_rows	int		-- affected/inserted.
	      , @sel_stmt	varchar(1200)	-- to define SELECT list.
	      , @for_item	varchar(10)	-- 'deadlockID' or 'spid'
	      , @crt_newarchive	tinyint
	      , @do_freeze_mda	tinyint
	      , @datestamp	datetime

	      , @master_monDeadLock	varchar(22)	-- master.dbo.<name>
	      , @mondeadlock		varchar(11)	-- monDeadLock
	      , @deadlock_tabname	varchar(30)
	      , @dlkID_or_for_Date	varchar(30)
	      , @output_mode		varchar(30)

	      -- Various output options.
	      , @output_count_by_date		varchar(20)
	      , @output_count_by_appln		varchar(20)
	      , @output_count_by_object		varchar(20)
	      , @output_count_by_date_object	varchar(25)
	      , @output_verbose			varchar(7)
	      , @output_pagediag		varchar(8)

	      , @opt_verbose		int
	      , @opt_pagediag		int
	      , @trace			int

	-- Supported output options:
	select @output_count_by_date		= 'count by date'
	     , @output_count_by_appln 		= 'count by application'
	     , @output_count_by_object		= 'count by object'
	     , @output_count_by_date_object	= 'count by date, object'
	     , @output_verbose			= 'verbose'
	     , @output_pagediag			= 'pagediag'

	     -- Set some defaults to avoid errors
	     , @deadlock_tabname	= NULL

	-- Print usage help if no args are provided, or 'help' is requested.
	--
	if (@arg1 = 'help')
	begin
		exec sp_monitor_deadlock_usage
				  @arg2			-- Gives verbosity level
				, @output_count_by_date
				, @output_count_by_appln
				, @output_count_by_object
				, @output_count_by_date_object
				, @output_verbose
				, @output_pagediag
		return 0
	end

	select @sel_stmt = object_name(@@procid, db_id('sybsystemprocs'))
	exec @retval = sp_monitor_check_permission @sel_stmt
	if (@retval != 0)
		return @retval

	-- Do routine monitoring specific validation for setup/configuration.
	--
	select @sqlstmt = 'deadlock'
	exec @retval = sp_monitor_verify_setup @sqlstmt

	exec @mdacfg_retval = sp_monitor_verify_cfgval @sqlstmt

	-- Bail out if there were any errors.
	if (@retval != 0)
		return @retval
	else if (@mdacfg_retval != 0)
		return @mdacfg_retval

	set nocount on
	
	select @do_freeze_mda 	= 0
	     , @mondeadlock	= 'monDeadLock'

	select @master_monDeadLock	= "master.dbo." + @mondeadlock

	exec @trace = sp_monitor_trace_level

	-- ==================================================================
	-- Process the 'archive' mode first; If table exists, insert to it,
	-- or else, create a new archive table using SELECT-INTO.
	--
	if (@arg1 LIKE 'archive%')
	begin
		exec @retval = sp_monitor_archive 'deadlock'
					, @arg1
					, @trace
		return @retval

	end

	-- ==================================================================
	-- IF the user has asked to report from an archive, parse that command,
	-- and setup out the archive table name.
	--
	else if (@arg1 LIKE 'report%')
	begin
		exec @retval = sp_monitor_parse_archive_cmd
					  @arg1
					, 'report'
					, 'report [using prefix=<string>]'
					, @deadlock_tabname output

		if (@retval != 0)
			return @retval

		-- Create the full name of the archive table using the
		-- extracted prefix sub-string.
		--
		select @deadlock_tabname = @deadlock_tabname
					 + @mondeadlock

		-- Setup local vars for remaining args.
		select @dlkID_or_for_Date 	= @arg2
		     , @output_mode		= @arg3
	end
	else
	begin
		-- Setup local vars for remaining args.
		select @dlkID_or_for_Date 	= @arg1
		     , @output_mode		= @arg2

		     -- Default events table name is this one.
		     , @deadlock_tabname	= @mondeadlock
	end

	select @dbname = db_name()

	-- ==================================================================
	-- Validate that the requested deadlock events table name existst.
	-- Otherwise bail. Note that by now if we are running in report mode,
	-- @deadlock_tabname would be the name of the archived table.
	--
	if (object_id(@deadlock_tabname) IS NULL)
	begin
		select @sqlstmt = 'dbo.' + @deadlock_tabname
		raiserror 17870, @sqlstmt, @dbname, ""

		-- Disallow certain key system-dbs for archival uses.
		-- Guide the user if their current db is one of the restricted
		-- ones, and they are doing a report. 
		--
		if (    (@arg1 LIKE 'report%')
		     and @dbname IN (   'master'
				      , 'model'
				      , 'sybsystemprocs'
				      , 'sybsystemdb'
				      , 'sybsecurity'
				     )
		   )
		begin
			print "Cannot use database '%1!' as a database to archive data."
				, @dbname
		end

		return 1
	end

	-- If no cached archive tablename was given, then process data
	-- real-time from monDeadLock table. In this case, produce the
	-- extra columns that would normally appear in an archived table.
	-- If the archive name was provided (and found), simply select all
	-- the columns from it.
	--
	if (@deadlock_tabname = @mondeadlock) and (db_name() = 'master')
	begin
		-- We have to freeze MDA tables as this branch
		-- *does* SELECT from monDeadLock directly.
		--
		select @do_freeze_mda = 1
		     , @datestamp = getdate()

		-- This SELECT should re-generate all the columns that
		-- would normally be created in the archive from
		-- #mon__deadlock_info
		--
		exec @retval = sp_mon_archive_genSQL @mondeadlock
						, @datestamp
						, @sel_stmt output

	end
	else
	begin
		-- We are processing data from an archived table. This
		-- archive was (or should have been) created by this sproc
		-- interface. Select all the columns from that archive, so
		-- that we have all the event-related information in one place.
		--
		select @sel_stmt = 'SELECT * '
	end

	-- ==================================================================
	-- Cache the info from @deadlock_tabname into a #temp table in tempdb
	-- that is created as a copy of monDeadLock so that can iterate through
	-- it subsequently to generate a report for interesting deadlock IDs.
	--
	select *

	     -- This piece is hand-copied from the SQL generated by:
	     -- sp_mon_archive_genSQL monDeadLock, 'May 25 2006', 'yyy', 'zzz', 1

	     -- Columns generated using sp_mon_archive_genSQL
	     -- edited for readability with some white-spaces.
	     --
	     , InstanceName = convert (varchar(30) NULL,
						instance_name(InstanceID))
	     , ObjectDBName = convert(varchar(30),db_name(ObjectDBID))
	     , HeldProcDBName = convert(varchar(30),db_name(HeldProcDBID))
	     , HeldProcedureName = convert(varchar(255) NULL,
	     				   object_name(HeldProcedureID,
					   	      HeldProcDBID))
	     , ServerName = convert(varchar(30) NULL, @@servername)
	     , ArchiveDate = convert(datetime NULL,'May 25 2006 12:00AM')
	     , VersionNum = convert(int NOT NULL, 1)
	     , ESDNum = convert(int NOT NULL, 0)
	     , EBFNum = convert(int NOT NULL, 0)

	into #mon__deadlock_info
	from master.dbo.monDeadLock
	where 1 = 0

	-- The table alias 'm' is essential as one of the generated SQL
	-- fragments uses this 'm.<somecolumn>' notation to disambiguate
	-- column name references.
	--
	select @sqlstmt = 'INSERT #mon__deadlock_info '
			+ @sel_stmt
			+ " FROM " + @dbname + '..' + @deadlock_tabname + " m"
			+ " WHERE 1=1 "

	-- ==================================================================
	-- Filter out deadlocks occuring on requested date, if any.
	--
	if (@dlkID_or_for_Date IS NOT NULL)
	begin
		-- Check if user has passed in a deadlockID; i.e. all digits.
		if (patindex("%[^0-9]%", @dlkID_or_for_Date) = 0)
		begin
			select @sqlstmt = @sqlstmt
					+  " AND DeadlockID="
					+ @dlkID_or_for_Date

				, @for_item = 'DeadlockID'
		end
		else
		begin
			-- Assume that the user is playing fair and will
			-- only pass in valid dates. If not, the following
			-- SQL will barf any way, and they'll get an error.
			--
			select @sqlstmt = @sqlstmt
				+  " AND convert(date, ResolveTime)='"
					    + @dlkID_or_for_Date + "'"
				, @for_item = 'date'
		end
	end

	-- ==================================================================
	-- This creates the cached #mon__deadlock_info table on which
	-- the rest of the SQL code operates.
	--
	if (@do_freeze_mda = 1)
		select @mdacfg_retval = mdaconfig('freeze', 'begin')

	-- No more accesses to master.dbo.monDeadLock should happen after here.
	exec @retval = sp_exec_SQL @sqlstmt, 'sp_monitor_deadlock'
					, NULL, @trace

	if (@do_freeze_mda = 1)
		select @mdacfg_retval = mdaconfig('freeze', 'end')

	if (@retval != 0)
	begin
		return @retval
	end

	-- ==================================================================
	-- Process the output modes, displaying summary only if so
	-- requested. Then bail.
	-- NOTE: If the user has specified any filters, they are applied
	-- first before generating the GROUP BY result. So, users can check
	-- for frequency of deadlocks by 'count by object' for a given 
	-- ResolveTime (date), for instance.
	--
	if (@output_mode LIKE "%count by%")
	begin
		exec @retval = sp_monitor_deadlock_count_by
					  @deadlock_tabname
					, @dbname
					, "#mon__deadlock_info"
					, @output_count_by_date
					, @output_count_by_appln
					, @output_count_by_object
					, @output_count_by_date_object
					, @output_mode
		return @retval
	end

	-- ==================================================================
	-- Extract other possible print/output options

	exec @retval = sp_monitor_deadlock_getopts
					  @output_mode

					, @output_verbose
					, @output_pagediag
					, @opt_verbose	output
					, @opt_pagediag	output
	if (@retval != 0)
		return @retval

	-- ==================================================================
	-- Process the data from the #mon__deadlock_info table.
	--
	exec sp_monitor_deadlock_driver 	-- @deadlock_tabname
				  @opt_verbose
				, @opt_pagediag
				, @num_deadlocks output

	-- Print summary statistics of run.
	--
	print " "
	select @sqlstmt = @dbname + '.dbo.' + @deadlock_tabname
	if (@dlkID_or_for_Date IS NULL)
	begin
		print "Total of %1! deadlocks were analyzed in this run from '%2!'."
			, @num_deadlocks , @sqlstmt
	end
	else
	begin
		print "Total of %1! deadlocks were analyzed in this run for %2! %3! from '%4!'."
			, @num_deadlocks, @for_item, @dlkID_or_for_Date
			, @sqlstmt
	end

	-- Cleanup before exiting.
	if (object_id("#mon__deadlock_info") IS NOT NULL)
		drop table #mon__deadlock_info

end	-- }
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_monitor_deadlock_usage', 'anymode'
go
grant execute on sp_monitor_deadlock_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_deadlock_getopts', 'anymode'
go
grant execute on sp_monitor_deadlock_getopts to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_deadlock_count_by', 'anymode'
go
grant execute on sp_monitor_deadlock_count_by to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_deadlock_verbose', 'anymode'
go
grant execute on sp_monitor_deadlock_verbose to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_deadlock_driver', 'anymode'
go
grant execute on sp_monitor_deadlock_driver to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_deadlock', 'anymode'
go
grant execute on sp_monitor_deadlock to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_procstack_usage')
begin
	drop procedure sp_monitor_procstack_usage
end
go
print "Installing sp_monitor_procstack_usage"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_procstack')
begin
	drop procedure sp_monitor_procstack
end
go
print "Installing sp_monitor_procstack"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_procstack [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_procstack [Total 5]
**
** 17679, "There is no text for object '%1!'."
** 18954, "Usage:"
** 19494, "Configuration: %1!"
** 19495, "%1!Monitor a given spid (that may possibly be in a hung state), and if possible%2!generate a back trace of the procedures it is currently executing."
** 19496, "%1!To generate a procstack of your current connection, with a context block of 10 lines, do:"
*/
/*
** End spgenmsgs.pl output.
*/
go

-- ========================================================================
exec sp_dbxt_recreate_proc sp_monitor_procstack_usage
go

/*
** sp_monitor_procstack_usage
**
**	Generate help/usage information in terse/verbose mode.
{
*/
create procedure sp_monitor_procstack_usage(@output_type varchar(8)
) as
begin
	declare @sp_command	varchar(80)
	      , @msg		varchar(200)
	      , @indent		varchar(5)
	      , @nl_indent	varchar(6)	-- newline followed by indent

	print " "
	exec sp_getmessage 18954, @msg output

	select @sp_command = @msg + " sp_monitor 'procstack' [, '<spid>'] [, '<contextblock>' ]"
	print @sp_command
	if (@output_type = 'terse')
		return

	select @indent		= "  -- "
	select @nl_indent	= char(10) + @indent

	print " "
	exec sp_getmessage 19494, @msg output
	select @sp_command = "sp_monitor 'enable', " + "'procstack'"
	print @msg, @sp_command

	print " "
	exec sp_getmessage 19495, @msg output
	print @msg, @indent, @nl_indent
	print "	sp_monitor 'procstack', '<spid>'"

	print " "
	exec sp_getmessage 19496, @msg output
	print @msg, @indent
	print "	declare @spid_str	varchar(5)"
	print "	select @spid_str = convert(varchar, @@spid)"
	print "	exec sp_monitor 'procstack', @spid_str, '10'"
end
go

if (@@error != 0) select syb_quit()
go

-- ========================================================================
exec sp_dbxt_recreate_proc sp_monitor_procstack
go

/*
** sp_monitor_procstack
**
**	Main entry point  procedure to identify the procedure calling
**	sequence for what is probably [currently] a blocked spid. Also
**	reports on the nature of blocking; i.e. who is blocking whom on
**	what page/row/table lock resource. If possible, generate the SQL
**	fragment executing for sprocs and cached statements. If possible,
**	generate the query plan for the currently executing statement in
**	the top-most stored procedure in the stack.
**
**	This is also the interface to get the server-side stacktrace for
**	the process of interest.
**
** Parameters:
**	@spid		- Process SPID to trace sproc calling sequence
**	@context	- # of lines of context to generate of SQL executing.
**	@type		- Type of object to trace back.
{
*/
create procedure sp_monitor_procstack(
		  @spid		int
		, @context	int	= NULL	-- of lines of sproc text.
		, @type		varchar(10)	= 'procedure'
) as
begin
	declare @sqlstr		varchar(256)
	      , @maxnest	int		-- Nesting level of top proc
	      , @dbname		varchar(30)
	      , @ownername	varchar(30)
	      , @objname	varchar(255)
	      , @procname	varchar(92)
	      , @sp_showtext	varchar(90)
	      , @linenum	int
	      , @stmtnum	int		-- of stmt in top-most sproc
	      , @contextid	int
	      , @batchid	int
	      , @blocked	int		-- spid of blocking task.
	      , @retval		int
	      , @error		int		-- @@error value
	      , @proc_objid	int		-- Objid of sproc.
	      , @blocking_spid	int
	      , @ctxt_block	int		-- context block
	      , @nesting	int
	      , @do_freeze	int
	      , @trace_3604_ON	int		-- boolean, if 3604 is ON
	      , @topmost	tinyint		-- whether we are running the
	      					-- top-most sproc in the stack

	select @sqlstr = object_name(@@procid, db_id('sybsystemprocs'))
	exec @retval = sp_monitor_check_permission @sqlstr
	if (@retval != 0)
		return @retval

	-- For 'procstack' execution, all we want is that the monitoring tables
	-- be installed. We don't even need 'enable monitoring' turned ON.
	-- So only do setup verification; configuration verification  is not
	-- needed.
	--
	select @procname = "sybsystemprocs.dbo.sp_monitor_verify_setup"
	exec @retval = @procname 'procstack'
	if (@retval != 0)
		return @retval

	-- [Comments left behind intentionally.]
	-- Remember whether 'enable monitoring' is ON. Only then should we
	-- attempt to freeze MDA tables; otherwise we will get a noise error.
	--
	-- exec sp_monitor_getcfgval "enable monitoring", @do_freeze output
	--
	-- But in a situation like this one, where we are accessing only
	-- one MDA table, without a join, and the table is a state table,
	-- there is no additional value to be gained by a freeze. So skip it.
	--
	select @do_freeze = 0

	if (@type IS NULL OR @type IN ("procedure", "procedure with arguments"))
	begin
		if (@do_freeze = 1)
			select @retval = mdaconfig('freeze', 'begin')

		-- ######################################################### 
		-- Report the procedure stack information for this spid.
		--
		select    SPID
			, 'Nesting' = convert(tinyint, m.ContextID)
			, m.DBName
			, m.OwnerName
			, m.ObjectName
			, m.ObjectID
			, m.LineNumber
			, m.ContextID
			, Blocked 	= 0
			, Statement 	= 0
		into #monProcessProcedures
		from master.dbo.monProcessProcedures m
		where SPID = @spid

		if (@do_freeze = 1)
			select @retval = mdaconfig('freeze', 'end')

		-- Cache the locks held by this task and the ones it is
		-- requesting, along with the locks held by the task that is
		-- blocking this spid, if any.
		--
		set switch on 1202 with override, no_info

		select @blocking_spid = p.blocked
		     , @linenum = linenum
		     , @stmtnum = stmtnum
		from master.dbo.sysprocesses p
		where p.spid = @spid

		select lo.*, typestr = convert(varchar(30) null, "")
			, blocked = @blocking_spid
		into #syslocks
		from master.dbo.syslocks lo
		where (lo.spid = @spid
		   or  lo.spid = @blocking_spid)

		-- select * from #syslocks

		update #syslocks
		set typestr = (select v.name from master..spt_values v
				where v.type = "L" and v.number = l.type)
		from #syslocks l

		-- Only select rows that are either blocked due to a 
		-- request, or the cause of the block.
		--
		select spid, dbid, id, page, row, typestr, blocked
		into #syslocks_2
		from #syslocks l
		where (typestr LIKE '%request%' or typestr LIKE '%blk%')

		if (@@rowcount != 0)
		begin
			print "SPID %1! is involved in a blocking situation as follows:"
				, @spid

			-- Show if any blocks were found.
			exec sp_autoformat #syslocks_2
		end
		else
		begin
			print " "
			print "No blocks were found for SPID %1!", @spid
		end

		-- ######################################################### 
		-- From here on we execute code only if the task being
		-- backtraced is already executing a sproc. Otherwise, it's
		-- executing an ad-hoc SQL, in which case there will be
		-- no rows in this table. So bail, out.
		-- Get Nesting level of top-most executing sproc.
		--
		select @maxnest = max(Nesting)
		from #monProcessProcedures b
		where b.SPID = @spid	-- redundant, but still ...

		if (@maxnest IS NULL)
		begin
			return 0
		end

		-- Check if the procedure that is being run is a light-weight
		-- procedure. If so, they won't have any data in sysprocedures
		-- so there is no further need to drill down. Simply use
		-- a DBCC to generate the statement cache information and
		-- exit.
		--
		select    @procname = ObjectName
			, @proc_objid = ObjectID
			, @dbname = DBName
		from #monProcessProcedures
		where Nesting = @maxnest

		if (@procname LIKE '*%')
		begin
			print ">>> SPID %1! is running a cached statement '%2!' (object ID=%3!) in db '%4!' <<<"
				, @spid, @procname, @proc_objid, @dbname

			-- Figure out the various naming patterns for diff 
			-- forms of Light Weight Procedures.
			--
			--  . "[*]ss%ss[*]" is for statement cache LWPs.
			--  . "[*][0-9]*_%" is for dynamic SQL LWPs.
			--
			-- Recognize each of them, and appropriately call
			-- the interface that is available to generate the
			-- SQL text.
			--
			if (@procname LIKE '*ss%ss*')
			begin
				set switch ON print_output_to_client 
				with override, no_info

				-- 1 prints the showplan, if it's around.
				DBCC prsqlcache(@proc_objid, 1)

				set switch OFF print_output_to_client with no_info
			end
			else if (@procname LIKE '*[0-9]%_[0-9]%')
			begin
				exec sp_getmessage 17679, @sqlstr output
				print @sqlstr, @procname
			end

			return 0
		end

		-- ######################################################### 
		-- IF this spid also appears as blocked in sysprocesses,
		-- and has a valid line #, generate the sproc information
		-- using sp_showtext.
		--

		-- Update the line # field with the value you might find
		-- from sysprocesses for this 'hung' task.
		--
		if (@linenum IS NOT NULL) OR (@blocked IS NOT NULL)
		begin
			update #monProcessProcedures
			set 	  LineNumber = isnull(@linenum, 0)
				, Blocked = isnull(@blocked, 0)
				, Statement = isnull(@stmtnum, 0)
			where Nesting = @maxnest
		end

		print "Procedure stack trace for SPID %1!:", @spid
		print " "

		exec @retval = sp_autoformat
				   @selectlist = "Nesting, DBName, OwnerName, ObjectName,ObjectID, LineNumber,Blocked"
				 , @fulltabname = "#monProcessProcedures"
				 , @orderby = "order by Nesting desc"
		if (@retval != 0)
			return @retval

		-- ######################################################### 
		-- Iterate through each procedure in the tree and try to
		-- print the code fragment that was just executing.
		-- Obviously for all but the top-most sproc, the statement
		-- will be EXEC <something>. But the context block around
		-- that line of SQL will give the user some idea of what
		-- code path was executing when the block/situation occured.
		-- This will be helpful if there are multiple calls to procB
		-- from procA under some if()-conditional logic.
		--
		declare proc_cur cursor for
		select    a.DBName, a.OwnerName, a.ObjectName, a.LineNumber
			, a.Nesting
			, a.ContextID
		from #monProcessProcedures a
		where a.SPID = @spid
		order by a.Nesting desc

		open proc_cur

		select @topmost = 1
		while (1 = 1)
		begin	-- {
			fetch proc_cur into 	  @dbname
						, @ownername
						, @objname
						, @linenum
						, @nesting
						, @contextid
			if (@@sqlstatus != 0)
				break

			if ((@linenum IS NOT NULL) and (@objname IS NOT NULL) ) 
			begin	-- {

				-- Fabricate the full name for the 
				-- executing sproc.
				select @procname = @ownername
						 + '.'
						 + @objname

				if (@procname IS NOT NULL)
				begin
					print " "
					print ">>> SPID %1! [Nest: %2!] Procedure '%3!.%4!' at line number %5!: <<<"
						, @spid, @nesting
						, @dbname, @procname, @linenum
					print " "

					select @ctxt_block =
						case when (@context IS NOT NULL)
						     then @context
						     else 5
						end

					select @sp_showtext = @dbname + ".dbo.sp_showtext"
					exec @sp_showtext @objname = @procname
							, @startline = @linenum
							, @numlines_or_ctxt = @ctxt_block
							, @printopts = "context,linenumbers"

					/*
					** FUTURE: This works, but we need more
					** complete data from the monitoring
					** table to directly call the sproc.
					** Until that is available, run this
					** in a slower mode; works.
					*/
					-- Generate the plan of the currently
					-- executing statement in the top-most
					-- sproc.
					--
					if (@topmost = 1)
					begin
						exec @retval = sp_showplan
								    @spid
								  , NULL
								  , NULL
								  , NULL
						select @error = @@error
						select @topmost = 0
						if (@retval != 0)
						begin
							print "sp_showplan return code: %1! (@error=%2!)"
							   , @retval
							   , @error
							if (@error != 0)
								goto end_cursor
						end
					end
				end
			end	-- }
		end	-- }

end_cursor:
		close proc_cur

		deallocate cursor proc_cur

	end
	else if (@type = "server")
	begin
		select @trace_3604_ON = 
			(switchprop("print_output_to_client") & 1)

		-- If it's not set locally, turn it ON now.
		if (@trace_3604_ON != 1)
		begin
			set switch ON print_output_to_client 
			with override, no_info
		end

		dbcc stacktrace(@spid)

		if (@trace_3604_ON != 1)
		begin
			set switch OFF print_output_to_client with no_info
		end

		return @@error

	end

	return @retval
end	-- }
go

if (@@error != 0) select syb_quit()
go

go
exec sp_procxmode 'sp_monitor_procstack_usage', 'anymode'
go
grant execute on sp_monitor_procstack_usage to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_procstack', 'anymode'
go
grant execute on sp_monitor_procstack to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_list_montypes')
begin
	drop procedure sp_monitor_list_montypes
end
go
print "Installing sp_monitor_list_montypes"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_monitor_list')
begin
	drop procedure sp_monitor_list
end
go
print "Installing sp_monitor_list"
go


/*
** Generated by spgenmsgs.pl on Fri Jun 15 11:49:40 2007 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/monitor_list [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/monitor_list [Total 4]
**
** 19476, "No monitoring features are currently enabled via %1!."
** 19477, "Monitoring related configuration options found to be enabled via %1!:"
** 19634, "Monitoring is currently active for the following types:"
** 19638, "Monitoring types that are enabled but require some additional configuration options to be turned ON:"
*/
/*
** End spgenmsgs.pl output.
*/
go

sp_dbxt_recreate_proc sp_monitor_list_montypes
go

/*
** Temp table used to iterate through all possible monitoring types, and
** to identify if the required config options for each one is ON (set by
** either sp_monitor or sp_configure). If so, report back to the user what
** all monitoring entities are effectively currently enabled.
*/
create table #mon_types(
		  mon_type			varchar(30)
		, missing_cfg_option		int	default 0
		, enabled			int	default 0
		, numcfgs_enabled_via_spmon	int	default 0
		, config_name			varchar(100)	NULL
		, type				varchar(10)	NULL
		, cfg_value			int 	default 0
		, run_value			int	default 0
) lock allpages
go

/*
** sp_monitor_list_montypes
**
**	Utility sproc to look through various tables and present a summary
**	output of monitoring entities for which *ALL* required static
**	and dynamic config options are ON. Here we don't care whether the
**	config option was turned ON via sp_monitor or sp_configure or
**	the config file. If the set of config options required for a
**	particular monitoring type are found to be ON, we list it here.
**
** Returns:
**	0 , if all worked ok. 1, in case of any errors (in logic or ASE).
{
*/
go

create procedure sp_monitor_list_montypes
as
begin
	declare @retval	int
	      , @montype	varchar(30)
	      , @static_cfg_ok	int
	      , @dynamic_cfg_ok	int
	      , @msg		varchar(100)

	-- =============================================================
	-- First report the monitoring types found enabled either via
	-- sp_monitor or sp_configure where all the required config
	-- options and enabled status are ON.
	--
	-- Load the list of monitoring types that we currently support.
	--
	insert #mon_types(mon_type) values('connection')
	insert #mon_types(mon_type) values('deadlock')
	insert #mon_types(mon_type) values('event')
	insert #mon_types(mon_type) values('procedure')
	insert #mon_types(mon_type) values('procstack')
	insert #mon_types(mon_type) values('statement')

	-- Work through table of monitoring types, checking to see if the
	-- required config options (static and dynamic) ones are properly
	-- configured. If yes, update the 'enabled' status to record this.
	--
	declare moncur cursor for
	select mon_type from #mon_types

	open moncur

	select @retval = 0
	while (@retval = 0)
	begin
		fetch moncur into @montype
		if (@@sqlstatus != 0)
		begin
			if (@@error != 0)
				select @retval = 1
			break
		end

		-- Validate config options settings using utility sprocs.
		--
		exec @static_cfg_ok = sp_monitor_verify_setup @montype, 0

		exec @dynamic_cfg_ok = sp_monitor_verify_cfgval @montype, 0

		if (@static_cfg_ok = 0)
		begin
			if (@dynamic_cfg_ok = 0)
			begin
				update #mon_types
				set enabled = 1
				where mon_type = @montype
			end
		end
		else
		begin
			-- Record in the #temp table which static config
			-- option was not ON, but is required.
			--
			update #mon_types
			set missing_cfg_option = @static_cfg_ok
			where mon_type = @montype
		end

		-- Check for errors; only 1 row should be updated.
		if ((@@error != 0) and (@@rowcount != 1))
		begin
			select @retval = 1
			break
		end
	end

	close moncur

	deallocate cursor moncur

	-- exec sp_autoformat #mon_types

	-- Record the name of the config option that needs to be
	-- set statically, and its type.
	--
	update #mon_types
	set config_name = co.name
	  , type 	= cu.type
	  , run_value 	= cu.value
	  , cfg_value	= co.value
	  , numcfgs_enabled_via_spmon	= (select count(*)
	  				   from tempdb.dbo.mon_config mc
					   where mc.monitor = mt.mon_type)

	from #mon_types mt
	   , master.dbo.sysconfigures co
	   , master.dbo.syscurconfigs cu
	where mt.missing_cfg_option = co.config
	  and mt.missing_cfg_option = cu.config
	  and cu.config	= cu.config

	-- exec sp_autoformat #mon_types

	-- Report the monitoring types that are all setup and ready to go
	-- for monitoring, if any were so found, and if there were no errors
	-- in previous logic.
	--
	if (   (@retval = 0)
	    and ((select count(*) from #mon_types
	          where enabled = 1
		    and missing_cfg_option = 0) != 0) )
	begin
		exec sp_getmessage 19634, @msg output
		print @msg
		print ""

		-- For improved readability.
		update #mon_types
		set mon_type = mon_type + " monitoring"
		where enabled = 1

		exec sp_autoformat @fulltabname = #mon_types
				 , @selectlist = "mon_type"
				 , @whereclause = "where enabled = 1"
				 , @orderby = "order by mon_type"
	end

	return @retval
end
go	-- }

if (@@sqlstatus != 0) select syb_quit()
go

drop table #mon_types
go

sp_dbxt_recreate_proc sp_monitor_list
go

/*
** sp_monitor_list
**
**	Generate a summary listing of the various monitoring types that
**	are enabled, and associated config options that are ON (or not).
**	This summary report will give the user a quick snapshot of the
**	current state of monitoring in the server.
**
** Returns:
**	0 - Success; Non-zero for failure.
{
*/
create procedure sp_monitor_list
as
begin
	declare @sqlstmt	varchar(100)
	      , @retval		int

	-- For consistency with other commands, require both mon_role and
	-- sa_role, even though only sa_role is sufficient for this command.
	--
	select @sqlstmt = object_name(@@procid, db_id('sybsystemprocs'))
	exec @retval = sp_monitor_check_permission @sqlstmt
	if (@retval != 0)
		return @retval

	set nocount on

	-- Create a #temp table  in which we will stash away any config
	-- options found to b set in the control table. The control table
	-- itself might not be found, so we have to play games by creating
	-- a temp table first, and then use it to join later on.
	--
	select config into #mon_config
	from master.dbo.sysconfigures
	where 1 = 0

	print " "
	if (object_id('tempdb.dbo.mon_config') IS NULL)
	begin
		exec sp_getmessage 19476, @sqlstmt output
		print @sqlstmt, 'sp_monitor'
		print " "
	end
	else
	begin
		-- First collect and display the config items needed
		-- that are needed to be ON for the monitoring entity
		-- types that are seen to be 'enable'd from the control
		-- table.
		--
		select mc.monitor
		     , mc.configname
		     , mc.enabled
		     , run_value = cu.value
		     , type = cu.type
		into #mon_config_for_type
		from tempdb.dbo.mon_config mc
		   , master.dbo.syscurconfigs cu
		where monitor != 'tracing'
		  and confignum > 0		-- get real config item rows.
		  and cu.config = mc.confignum

		-- Identify the unique config options that were needed for
		-- all monitoring types currently found enabled.
		--
		select @sqlstmt = "INSERT #mon_config "
				+ "SELECT DISTINCT confignum "
				+ "FROM tempdb.dbo.mon_config"
				+ " WHERE monitor != 'tracing'"

		exec @retval = sp_exec_SQL @sqlstmt, "sp_monitor_list"
		if (@retval != 0)
			return @retval

		create table #mon_types(
				  mon_type			varchar(30)
				, missing_cfg_option		int	default 0
				, enabled			int	default 0
				, numcfgs_enabled_via_spmon	int	default 0
				, config_name			varchar(100)	NULL
				, type				varchar(10)	NULL
				, cfg_value			int 	default 0
				, run_value			int	default 0
		) lock allpages

		exec @retval = sp_monitor_list_montypes

		if (    (@retval = 0)
		    and (EXISTS (select 1 from #mon_types
		    		 where numcfgs_enabled_via_spmon > 0
				    and missing_cfg_option > 0) ) )
		begin
			-- We found some monitoring config options were ON, but
			-- in some cases they might not be turning ON all the
			-- required config options. Do a match between the
			-- monitoring entties that are known to be enabled
			-- via sp_monitor v/s their missing config options,
			-- and list those here, so that the user can at least
			-- know what config options are missing that prevents
			-- them from successfully doing a particular kind of
			-- monitoring (that they think they have already
			-- enabled via sp_monitor).
			--
			exec sp_getmessage 19638, @sqlstmt output
			print ""
			print @sqlstmt
			print ""

			exec sp_autoformat @fulltabname = #mon_types
					 , @selectlist = "mon_type, config_name, run_value, cfg_value, type"
					 , @whereclause = "where (numcfgs_enabled_via_spmon > 0) AND (missing_cfg_option > 0)"
					 , @orderby = "order by mon_type"
		end


		-- Then, report the mapping between monitoring types and
		-- associated config options enabled.
		--
		exec sp_getmessage 19477, @sqlstmt output
		print " "
		print @sqlstmt, 'sp_monitor'
		print " "

		exec sp_autoformat @fulltabname = #mon_config_for_type
				, @selectlist = "'mon_type'=monitor, 'config_name'=configname, run_value, enabled, type"
				, @orderby = "order by monitor"

	end

	print " "
	exec sp_getmessage 19477, @sqlstmt output
	print @sqlstmt, 'sp_configure'
	print " "

	-- select * from #mon_config

	-- Report on any configurations options that might have already
	-- been set by the user via sp_configure, but are not found in the
	-- control table. This will only report those config options that
	-- were set not by sp_monitor, but only by sp_configure/cfgfile.
	--
	select    mon_type = convert(varchar(100) NULL, "")
		, config_name = co.name
		, "run_value" = cu.value
		, 'cfg_value' = co.value
		, cu.type
	into #configures
	from 	  master.dbo.sysconfigures co
		, master.dbo.syscurconfigs cu
	where co.config = cu.config
	  and cu.value != 0
	  and co.config NOT IN (select config from #mon_config)
	  and co.parent = (select i.config
			   from master.dbo.sysconfigures i
	  		   where name = "Monitoring")

	-- Report the monitoring type if certain config options are found
	-- to be ON. This lists all known config options that are required
	-- for various monitoring entities. See the NOTE in the prolog of 
	-- sp_monitor_verify_cfgval.
	--
	update #configures
	set mon_type = CASE config_name
	
		    -- Keep list and entries in THEN clause in alphabetical order.
		    --
		    WHEN "SQL batch capture" 		THEN "connection,statement"
		    WHEN "deadlock pipe active" 	THEN "deadlock"
		    WHEN "deadlock pipe max messages" 	THEN "deadlock"
		    WHEN "max SQL text monitored" 	THEN "connection, statement"
		    WHEN "per object statistics active" THEN "connection,procedure,statement"
		    WHEN "process wait events" 		THEN "event"
		    WHEN "statement pipe active" 	THEN "procedure"
		    WHEN "statement pipe max messages" 	THEN "procedure,statement"
		    WHEN "statement statistics active" 	THEN "procedure,statement"
		    WHEN "wait event timing" 		THEN "connection,deadlock,event,statement"
		    -- WHEN "xx"			THEN "yy" dummy row.
		    ELSE ""
		   END

	exec @retval = sp_autoformat @fulltabname = #configures
			 , @selectlist = "config_name, run_value, cfg_value, type, mon_type"
			 , @orderby = "order by mon_type"
	return @retval

end	-- }
go

if (@@sqlstatus != 0) select syb_quit()
go


go
exec sp_procxmode 'sp_monitor_list_montypes', 'anymode'
go
grant execute on sp_monitor_list_montypes to public
go
dump tran master with truncate_only
go
exec sp_procxmode 'sp_monitor_list', 'anymode'
go
grant execute on sp_monitor_list to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_helpcache')
begin
	drop procedure sp_helpcache
end
go
print "Installing sp_helpcache"
go

/* This stored procedure is for displaying cache overhead and bindings */
/* 17260, "Can't run %1! from within a transaction." */
/* 18076, "Could not set curwrite to object level. Set your maxwrite label correctly." */
/* 18174, "The database '%1!' is offline. To obtain cache-bindings for objects in this database, please online the database and rerun sp_helpcache. */

create procedure sp_helpcache
@parm1		varchar(255) = NULL,
@parm2		varchar(255) = NULL
as

declare @cachename		varchar(255) /* Name of the cache */
declare @stat			int	/* cache status from sysconfigures */
declare @cstat			int	/* status return from config_admin */
declare	@unit_loc		int	/* location of unit specifier in str */
declare	@size			int	/* cache size from sysconfigures */
declare	@row_count		int	/* # rows in #syscacheconfig */
declare	@config_size		int	/* cache's configured size 
					** (syscurconfigs
					*/ 
declare	@run_size		int	/* cache's current run size from 
					** syscurconfigs
					*/
declare @overhead		int	/* cache's memory overhead */
declare @total_config		int	/* total configured cache memory */
declare	@total_run		int	/* total running cache memory */
declare @total_overhead		int	/* total amount of overhead used */
declare @status2		int	/* Sysdatabase[DAT_STATUS2] */
declare	@first_char		char(1)	/* first char of parm1 */
declare	@unit			varchar(5) /* unit of size for configuration */
declare @name			varchar(255)/* cache name from sysconfigures */
declare @config_sz_str		varchar(30)/* str value for run_size */ 
declare @run_sz_str		varchar(30)/* str value for config_size */  
declare @overhead_sz_str	varchar(30)/* str value for overhead size */
declare @print_str		varchar(255)/* general string to print info */
declare @instancename		varchar(255)
declare @instanceid		int
declare @curr_avail_cache_mem	float	/* current amount of memory available
					** for named cache configuration.
					*/
declare @tempdb_mask int	/* all tempdb status bits */

/* Dont allow sp_helpcache to run with in a transaction. */
if @@trancount > 0
begin
	/*
	** 17260, "Can't run %1! from within a transaction."
	*/
	raiserror 17260, "sp_helpcache"
	return (1)
end
else
begin
	set transaction isolation level 1
	set chained off
end

select @first_char = substring(@parm1, 1, 1)
select @instancename = NULL
select @instanceid = NULL

if (@parm1 is NULL or (patindex("%[a-z,A-Z]%", @first_char) != 0))
begin

	begin
		select @cachename = @parm1
	end


	select distinct co.config, co.name, co.value, co.value3, 
		co.status, 
	
		 cu.value run_size, cu.memory_used memory_used
	into #syscacheconfig
	from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
	where 1=2


	begin
		insert #syscacheconfig
		select distinct co.config, co.name, co.value, co.value3, 
				co.status, cu.value run_size,
				cu.memory_used memory_used
		from master.dbo.sysconfigures co, master.dbo.syscurconfigs cu
		where parent = 19
			and co.config = cu.config
			and co.config = 19
			and co.name = cu.comment
			and name like "%" + @cachename + "%"
		order by name, config
	end


	/*
	**  Find out the number of rows we want to look at.
	*/
	select @row_count = count(*) from #syscacheconfig
	
	/*
	**  If no rows qualify then this cache doesn't exist.
	*/
	if @row_count = 0
	begin
		raiserror 18135, @parm1
		return 1
	end

	/*
	** populate the result into temp table. 
	*/
	if ((select object_id("#cachesize_info")) IS NOT NULL)
	begin
		drop table #cachesize_info
	end

	create table #cachesize_info (
			cachename	varchar(255),
			configsize	varchar(30),
			runtimesize	varchar(30),
			overhead	varchar(30)) 

	declare sysc_cursor cursor

	for select name, value, status, run_size, memory_used
		from #syscacheconfig
		order by name

 
	open sysc_cursor

	select @total_config = 0
	select @total_run = 0
	select @total_overhead = 0

	while (@row_count > 0)
	begin

		fetch sysc_cursor into @name, @size, @stat, @run_size, @overhead




		if @stat & 16384 = 16384
		begin
			/* Cache is deleted */
			select @row_count = @row_count - 1
			continue
		end

		if (@stat & 32 = 32)
		begin
			select @config_size = @size
			/*
			**  The actual run size is in syscurconfigs
			*/

			if (@@instanceid != NULL) and
				exists(select * from master.dbo.sysconfigures
					where parent = 19 
					
					and name = @name) and
					 @instanceid = NULL
			begin
				select @run_size = 0
				select @overhead = 0
			end
			else
			begin
				select @total_config = @total_config + @config_size
			end

			select @total_run = @total_run + @run_size
		end
		if (@stat & 64 = 64)
		begin
			select @run_size = 0
			select @overhead = 0
			select @config_size = @size
			select @total_config = @total_config + @config_size
		end
		if (@stat & 128 = 128)
		begin
			select @config_size = 0

			if exists(select * from master.dbo.sysconfigures
					where parent = 19 
					
					and name = @name) and
					 @instanceid = NULL
			begin
				select @run_size = 0
				select @overhead = 0
			end

			select @total_run = @total_run + @run_size
		end	       
		
		select @total_overhead = @total_overhead + @overhead
		/*
		**  Convert run_size ,config_size and overhead to megabyte 
		**  values stored as strings
		*/
		select @run_sz_str = rtrim(str(convert(float,@run_size) / 1024, 7, 2)) + " Mb"
		select @config_sz_str = rtrim(str(convert(float,@config_size) / 1024, 7, 2)) + " Mb"
		select @overhead_sz_str = rtrim(str(convert(float,@overhead) / 1024, 7, 2)) + " Mb"

		if @instanceid != NULL	
		begin
			select @instancename = instance_name(@instanceid)
			select @name = @name+":"+@instancename
		end	
		insert into #cachesize_info values (@name, @config_sz_str, @run_sz_str, @overhead_sz_str)

		select @row_count = @row_count - 1
	end

	close sysc_cursor

	/* Display #cachesize_info */
	exec sp_autoformat @fulltabname = #cachesize_info,
		@selectlist = "'Cache Name' = cachename,'Config Size' = configsize,'Run Size' = runtimesize, 'Overhead' = overhead", 
		@orderby = "order by cachename"

	drop table #cachesize_info

	/*
	**  If we're doing a helpcache on a specific cache then don't print
	**  out info on global memory availability.
	*/
	if patindex("%[a-z]%", @first_char) = 0
	begin
		select @curr_avail_cache_mem = 
				config_admin(13, 0, 0, 0, NULL, NULL)

		/*
		**  Subtract all cache overhead from available cache
		**  memory.
		*/
		select @curr_avail_cache_mem = @curr_avail_cache_mem - 
				@total_overhead
	
		print " "
		print " "
		print "Memory Available For      Memory Configured"
		print "Named Caches              To Named Caches"
		print "--------------------       ----------------"
		select @print_str =  convert(char(28), str(convert(float,@curr_avail_cache_mem) / 1024, 7, 2) + " Mb") + str(convert(float,@total_config) / 1024, 7, 2) + " Mb"
		print @print_str
		print " "
	end


	print " "
	print "------------------ Cache Binding Information: ------------------ "
	print " "

	/*
	**  Find out the number of rows we want to look at.
	*/
	select @row_count = count(*) from #syscacheconfig
	
	declare bindings_cursor cursor
	for select name from #syscacheconfig
 
	open bindings_cursor

	print "Cache Name           Entity Name                Type               Index Name                    Status"
	print "----------           -----------                ----               ----------                    ------"
	while (@row_count > 0)
	begin
		fetch bindings_cursor into @name
		
		select @cstat = config_admin(9, 2, 0, 0, NULL, @name)

		select @row_count = @row_count - 1
	end

	close bindings_cursor

	/* Now print error message for offline databases. The built-in
	** function config_admin() ignores offline databases and we handle
	** them here after all online databases have been handled.  
	*/
	select @tempdb_mask =  number
		from master.dbo.spt_values
		where   type = "D3" and name = "TEMPDB STATUS MASK"

	select name, status2
        into #sysdb
        from master.dbo.sysdatabases
	where (status3 & @tempdb_mask) = 0

	/*
	**  Find out the number of rows we want to look at.
	*/
	select @row_count = count(*) from #sysdb
	
	declare offlinedb_cursor cursor
	for select name, status2 from #sysdb
 
	open offlinedb_cursor

	while (@row_count > 0)
	begin
		fetch offlinedb_cursor into @name, @status2
		
		if (@status2 & 16 != 0)
		begin
			/* 18174, "The database '%1!' is offline. To obtain 
			** cache-bindings for objects in this database, 
			** please online the database and rerun sp_helpcache. 
			*/
			raiserror 18174, @name
		end
		select @row_count = @row_count - 1
	end

	close offlinedb_cursor

	/* Print free cache device list for in-memory storage cache. */
	select @row_count = count(*) from #syscacheconfig 
	where (status & 65536 = 65536)

	if @row_count  > 0
	begin
		print " "
		print "------------------ In-memory Storage Cache Space Information ------------------"
		print " "

		select Name, DeviceName, Status, StartPage, NumPages, SizeKB
		into #cachedevice
		from master.dbo.monInmemoryStorage
		where Name like "%" + @cachename + "%"

		insert into #cachedevice
		select phyname, name, "active", low, (high - low + 1), ((high - low + 1) * 2) 
		from master.dbo.sysdevices 
		where status2 & 8 = 8
		and phyname like "%" + @cachename + "%"

		/* Display free cache device information. */
		exec sp_autoformat @fulltabname = #cachedevice,
				   @selectlist = "'Cache Name' = Name, 'Device Name'=DeviceName, 'Status' = Status, 'Start Page' = StartPage, 'Number of Pages' = NumPages, 'Size(KB)' = SizeKB",
				   @orderby = "order by Name, Status, SizeKB DESC"
		drop table #cachedevice
	end

	return 0
end
else
begin

	/*
	**  If we get here parm1 must be of the form %d[M P K G].
	*/
	exec @stat = sp_aux_getsize @parm1, @size output
	if @stat = 0
	begin
		return 1
	end

	select @overhead = config_admin(12, 0, @size, 0, NULL, NULL)
	select @overhead_sz_str = str(convert(float,@overhead) / 1024, 7, 2) + "Mb"

	select @print_str = convert(varchar(15), @overhead_sz_str) + " of overhead memory will be needed to manage a cache of size " + @parm1

	print @print_str
end

return 0
go
exec sp_procxmode 'sp_helpcache', 'anymode'
go
grant execute on sp_helpcache to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
insert master.dbo.spt_values (name, number, type, low)
values ("@(#)ver=15.0.3.5/2391/091109",  -2, "E", 0)
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_datatype_info_cts')
begin
	drop procedure sp_jdbc_datatype_info_cts
end
go
print "Installing sp_jdbc_datatype_info_cts"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_datatype_info')
begin
	drop procedure sp_jdbc_datatype_info
end
go
print "Installing sp_jdbc_datatype_info"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drv_column_default')
begin
	drop procedure sp_drv_column_default
end
go
print "Installing sp_drv_column_default"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drv_typeinfo')
begin
	drop procedure sp_drv_typeinfo
end
go
print "Installing sp_drv_typeinfo"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_localtypename')
begin
	drop procedure sp_localtypename
end
go
print "Installing sp_localtypename"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_columns')
begin
	drop procedure sp_jdbc_columns
end
go
print "Installing sp_jdbc_columns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_tables')
begin
	drop procedure sp_jdbc_tables
end
go
print "Installing sp_jdbc_tables"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_mda')
begin
	drop procedure sp_mda
end
go
print "Installing sp_mda"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_convert_datatype')
begin
	drop procedure sp_jdbc_convert_datatype
end
go
print "Installing sp_jdbc_convert_datatype"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_function_escapes')
begin
	drop procedure sp_jdbc_function_escapes
end
go
print "Installing sp_jdbc_function_escapes"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_fkeys')
begin
	drop procedure sp_jdbc_fkeys
end
go
print "Installing sp_jdbc_fkeys"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_exportkey')
begin
	drop procedure sp_jdbc_exportkey
end
go
print "Installing sp_jdbc_exportkey"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_importkey')
begin
	drop procedure sp_jdbc_importkey
end
go
print "Installing sp_jdbc_importkey"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getcrossreferences')
begin
	drop procedure sp_jdbc_getcrossreferences
end
go
print "Installing sp_jdbc_getcrossreferences"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_drv_bcpmetadata')
begin
	drop procedure sp_drv_bcpmetadata
end
go
print "Installing sp_drv_bcpmetadata"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getschemas_cts')
begin
	drop procedure sp_jdbc_getschemas_cts
end
go
print "Installing sp_jdbc_getschemas_cts"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getschemas')
begin
	drop procedure sp_jdbc_getschemas
end
go
print "Installing sp_jdbc_getschemas"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getcolumnprivileges')
begin
	drop procedure sp_jdbc_getcolumnprivileges
end
go
print "Installing sp_jdbc_getcolumnprivileges"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_computeprivs')
begin
	drop procedure sp_jdbc_computeprivs
end
go
print "Installing sp_jdbc_computeprivs"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_gettableprivileges')
begin
	drop procedure sp_jdbc_gettableprivileges
end
go
print "Installing sp_jdbc_gettableprivileges"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getcatalogs_cts')
begin
	drop procedure sp_jdbc_getcatalogs_cts
end
go
print "Installing sp_jdbc_getcatalogs_cts"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getcatalogs')
begin
	drop procedure sp_jdbc_getcatalogs
end
go
print "Installing sp_jdbc_getcatalogs"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_primarykey')
begin
	drop procedure sp_jdbc_primarykey
end
go
print "Installing sp_jdbc_primarykey"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_sql_type_name')
begin
	drop procedure sp_sql_type_name
end
go
print "Installing sp_sql_type_name"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getbestrowidentifier')
begin
	drop procedure sp_jdbc_getbestrowidentifier
end
go
print "Installing sp_jdbc_getbestrowidentifier"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getisolationlevels')
begin
	drop procedure sp_jdbc_getisolationlevels
end
go
print "Installing sp_jdbc_getisolationlevels"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getindexinfo')
begin
	drop procedure sp_jdbc_getindexinfo
end
go
print "Installing sp_jdbc_getindexinfo"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_stored_procedures')
begin
	drop procedure sp_jdbc_stored_procedures
end
go
print "Installing sp_jdbc_stored_procedures"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getprocedurecolumns')
begin
	drop procedure sp_jdbc_getprocedurecolumns
end
go
print "Installing sp_jdbc_getprocedurecolumns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getversioncolumns')
begin
	drop procedure sp_jdbc_getversioncolumns
end
go
print "Installing sp_jdbc_getversioncolumns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_default_charset')
begin
	drop procedure sp_default_charset
end
go
print "Installing sp_default_charset"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getudts')
begin
	drop procedure sp_jdbc_getudts
end
go
print "Installing sp_jdbc_getudts"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_getxacoordinator')
begin
	drop procedure sp_jdbc_getxacoordinator
end
go
print "Installing sp_jdbc_getxacoordinator"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_class_for_name')
begin
	drop procedure sp_jdbc_class_for_name
end
go
print "Installing sp_jdbc_class_for_name"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_jar_for_class')
begin
	drop procedure sp_jdbc_jar_for_class
end
go
print "Installing sp_jdbc_jar_for_class"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_jar_by_name')
begin
	drop procedure sp_jdbc_jar_by_name
end
go
print "Installing sp_jdbc_jar_by_name"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_classes_in_jar')
begin
	drop procedure sp_jdbc_classes_in_jar
end
go
print "Installing sp_jdbc_classes_in_jar"
go

/* Sccsid = "%Z% sun_svr4/sproc/src/%M% %I% %G%" */
/*
**  JDBC_INSTALL
**  This file contains the metadata Stored Procedures used by the JDBC drivers.
**
*/

/*
** sql_server.sql
**
**
** Tables created:
**
**      Name                    Default Location
**      ----------------------- ----------------
**      spt_jdbc_table_types    master
**      spt_mda                 master
**      spt_jtext               master
**      spt_jdbc_conversion     master
**      spt_jdbc_datatype_info      sybsystemprocs
**
**
** Stored procedures created:
**
**      Name                          Default Location
**      ----------------------------- ----------------
**      sp_mda                        sybsystemprocs
**      sp_jdbc_datatype_info         sybsystemprocs
**      sp_jdbc_datatype_info_cts     sybsystemprocs
**      sp_jdbc_columns               sybsystemprocs
**      sp_jdbc_tables                sybsystemprocs
**      jdbc_function_escapes         sybsystemprocs
**      sp_jdbc_convert_datatype      sybsystemprocs
**      sp_jdbc_function_escapes      sybsystemprocs
**      sp_jdbc_fkeys                 sybsystemprocs
**      sp_jdbc_exportkey             sybsystemprocs
**      sp_jdbc_importkey             sybsystemprocs
**      sp_jdbc_getcrossreferences    sybsystemprocs
**      sp_jdbc_getschemas            sybsystemprocs
**      sp_jdbc_getcolumnprivileges   sybsystemprocs
**      sp_jdbc_gettableprivileges    sybsystemprocs
**      sp_jdbc_computeprivs          sybsystemprocs
**      sp_jdbc_getcatalogs           sybsystemprocs
**      sp_jdbc_primarykey            sybsystemprocs
**      sp_sql_type_name              sybsystemprocs
**      sp_jdbc_getbestrowidentifier  sybsystemprocs
**      sp_jdbc_getisolationlevels    sybsystemprocs
**      sp_jdbc_getindexinfo          sybsystemprocs
**      sp_jdbc_stored_procedures     sybsystemprocs
**      sp_jdbc_getprocedurecolumns   sybsystemprocs
**      sp_jdbc_getversioncolumns     sybsystemprocs
**      sp_jdbc_escapeliteralforlike  sybsystemprocs
**      sp_default_charset            sybsystemprocs
**      sp_jdbc_getudts               sybsystemprocs
**      sp_jdbc_class_for_name        sybsystemprocs
**      sp_jdbc_jar_for_class         sybsystemprocs
**      sp_jdbc_jar_by_name           sybsystemprocs
**      sp_jdbc_classes_in_jar        sybsystemprocs
**      sp_drv_column_default         sybsystemprocs
**
**
** File Sections for use with the jConnect IsqlApp Sample:
**
**      Section Name  Description
**      ------------- ---------------------------------------
**      CLEANUP       Removes all of the tables/sprocs
**                    created by this script.
**
*/


set quoted_identifier on
go

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ADDPOINT_SP_VERSION */

declare @retval int
exec @retval = sp_version 'installjdbc',NULL,'jConnect (TM) for JDBC(TM)/6.05(Build 26515)/P/EBF16508/JDK14/Fri Jan 16 12:48:51 2009', 'start'
if (@retval != 0) select syb_quit()
go
/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

sp_configure 'allow updates', 1
go
/** SECTION END: CLEANUP **/


/*
**   spt_jdbc_datatype_info
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if (exists (select * from sysobjects
		where name = 'spt_jdbc_datatype_info' and type = 'U'))
    drop table spt_jdbc_datatype_info
go
/** SECTION END: CLEANUP **/

create table spt_jdbc_datatype_info 
(
	ss_dtype	   tinyint	not null, 
	type_name          varchar(255)  null, 
	data_type          smallint     not null, 
	data_precision     int          null, 
	numeric_scale      smallint     null, 
	numeric_radix      smallint     null, 
	length             int          null, 
	literal_prefix     varchar(32 )  null, 
	literal_suffix     varchar(32 )  null, 
	create_params      varchar(32 )  null, 
	nullable           smallint     not null, 
	case_sensitive     smallint     not null, 
	searchable         smallint     not null, 
	unsigned_attribute smallint     null, 
	money              smallint     not null, 
	auto_increment     smallint     null, 
	local_type_name    varchar(128) not null, 
	aux                int          null,
	maximum_scale	   smallint	null,
	minimum_scale	   smallint	null,
	sql_data_type	   smallint	null,
	sql_datetime_sub   smallint	null,
	num_prec_radix	   smallint	null,
	interval_precision smallint	null
)
go

grant select on spt_jdbc_datatype_info to public
go

/*
**	There is a complicated set of SQL used to deal with
**	the SQL Server Null data types (MONEYn, INTn, etc.)
**	ISNULL is the only conditional SQL Server function that can be used
**	to differentiate between these types depending on size.
**
**	The aux column in the above table is used to differentiate
**	the null data types from the non-null types.
**
**	The aux column contains NULL for the null data types and 0
**	for the non-null data types.
**
**	The following SQL returns the contents of the aux column (0)
**	for the non-null data types and returns a variable non-zero
**	value for the null data types.
**
**			 ' I   I I FFMMDD'
**			 ' 1   2 4 484848'
**	isnull(d.aux, ascii(substring('666AAA@@@CB??GG', 
**	2*(d.ss_dtype%35+1)+2-8/c.length, 1))-60)
**
**	The '2*(d.ss_dtype%35+1)+2-8/c.length' selects a specific character of
**	the substring mask depending on the null data type and its size, i.e.
**	null MONEY4 or null MONEY8.  The character selected is then converted
**	to its binary value and an appropriate bias (i.e. 60) is subtracted to
**	return the correct non-zero value.	This value may be used as a
**	constant, i.e. ODBC data type, precision, scale, etc., or used as an
**	index with a substring to pick out a character string, i.e. type name.
**
**	The comments above the substring mask denote which character is
**	selected for each null data type, i.e. In (INTn), Fn (FLOATn), 
**	Mn (MONEYn) and Dn (DATETIMn).
**
**      Note that we don't need a row for DATEn and TIMEn because 
**      those additional entries are needed only when the datatype
**      can hold more than one usertype. For example, DATETIMEn can
**      hold both DATETIME and SMALLDATETIME data. 
*/


declare @case smallint

select @case = 0
select @case = 1 where 'a' != 'A'

/* Local Binary */
insert into spt_jdbc_datatype_info values
/* ss_type, name, data_type, prec, scale, rdx, len, prf, suf, 
** cp, nul, case, srch, unsigned, money, auto, local, aux 
** max_scale, min_scale, sql_data_typ, sql_datetime_sub, num_prec_radix,
** interval_precision
*/
(45, 'binary', -2, null, null, null, null, '0x', null, 
 'length', 1, 0, 2, null, 0, null, 'binary', 0,
 null, null, null, null, null, null)

/* Local Bit */
insert into spt_jdbc_datatype_info values
(50, 'bit', -7, 1, 0, 2, null, null, null, 
 null, 0, 0, 2, null, 0, null, 'bit', 0,
 null, null, null, null, null, null)

/* Local Char */
insert into spt_jdbc_datatype_info values
(47, 'char', 1, null, null, null, null, '''', '''', 
'length', 1, @case, 3, null, 0, null, 'char', 0,
 null, null, null, null, null, null)

/* Local Unichar */
insert into spt_jdbc_datatype_info values
(135, 'unichar', 1, null, null, null, null, '''', '''',
'length', 1, @case, 3, null, 0, null, 'unichar', 0,
 null, null, null, null, null, null)

/* Local Date */
insert into spt_jdbc_datatype_info values
(49, 'date', 91, 10, 0, 10, null, '''', '''',
null, 1, 0, 3, null, 0, null, 'date', 0,
null, null, 91, null, null, null)

/* Local Time */
insert into spt_jdbc_datatype_info values
(51, 'time', 92, 12, 3, 10, null, '''', '''',
null, 1, 0, 3, null, 0, null, 'time', 0,
null, null, 92, null, null, null)

/* Local Datetime */
insert into spt_jdbc_datatype_info values
(61, 'datetime', 93, 23, 3, 10, 16, '''', '''', 
 null, 1, 0, 3, null, 0, null, 'datetime', 0,
 null, null, 93, null, null, null)

/* Local Smalldatetime */
insert into spt_jdbc_datatype_info values
(58, 'smalldatetime', 93, 16, 0, 10, 16, '''', '''', 
null, 1, 0, 3, null, 0, null, 'smalldatetime', 0,
 null, null, 93, null, null, null)

/* Local Datetimn  sql server type is 'datetimn' */
insert into spt_jdbc_datatype_info values
(111, 'smalldatetime', 93, 0, 0, 10, 0, '''', '''', 
null, 1, 0, 3, null, 0, null, 'datetime', null,
 null, null, 93, null, null, null)

/* Decimal sql server type is 'decimal' */
insert into spt_jdbc_datatype_info values
(55, 'decimal', 3, 38, 0, 10, 0, null, null,
'precision,scale', 1, 0, 2, 0, 0, 0, 'decimal', 0,
 38, 0, null, null, null, null)

/* Numeric sql server type is 'numeric' */
insert into spt_jdbc_datatype_info values
(63, 'numeric', 2, 38, 0, 10, 0, null, null,
'precision,scale', 1, 0, 2, 0, 0, 0, 'numeric', 0,
 38, 0, null, null, null, null)

/* Local RealFloat   sql server type is 'floatn' */
insert into spt_jdbc_datatype_info values
(109, 'float        real', 1111, 0, null, 10, 0, null, null,
 null, 1, 0, 2, 0, 0, 0, 'real      float', null,
 null, null, null, null, 10, null)

/* Local Real */
insert into spt_jdbc_datatype_info values
(59, 'real', 7, 7, null, 10, null, null, null,
null, 1, 0, 2, 0, 0, 0, 'real', 0,
 null, null, null, null, 10, null)

/* Local Double */
insert into spt_jdbc_datatype_info values
(62, 'double precision', 8, 15, null, 10, null, null, null,
null, 1, 0, 2, 0, 0, 0, 'double precision', 0,
 null, null, null, null, 10, null)

/* Local Smallmoney */
insert into spt_jdbc_datatype_info values
(122, 'smallmoney', 3, 10, 4, 10, null, '$', null, 
null, 1, 0, 2, 0, 1, 0, 'smallmoney', 0,
 4, 4, null, null, null, null)

/* Local Int */
insert into spt_jdbc_datatype_info values
(56, 'int', 4, 10, 0, 10, null, null, null, 
null, 1, 0, 2, 0, 0, 0, 'int', 0,
 null, null, null, null, null, null)

/* Local Money */
insert into spt_jdbc_datatype_info values
(60, 'money', 3, 19, 4, 10, null, '$', null, 
null, 1, 0, 2, 0, 1, 0, 'money', 0,
 4, 4, null, null, null, null)

/* Local Moneyn  sql server type is 'moneyn'*/ 
insert into spt_jdbc_datatype_info values
(110, 'moneyn', 3, 0, 4, 10, 0, '$', null, 
null, 1, 0, 2, 0, 1, 0, 'moneyn', null,
 4, 4, null, null, null, null)

/* Local Smallint */
insert into spt_jdbc_datatype_info values
(52, 'smallint', 5, 5, 0, 10, null, null, null, 
null, 1, 0, 2, 0, 0, 0, 'smallint', 0,
 null, null, null, null, null, null)

/* Local Text */
insert into spt_jdbc_datatype_info values
(35, 'text', -1, 2147483647, null, null, 2147483647, '''', '''', 
null, 1, @case, 1, null, 0, null, 'text', 0,
 null, null, null, null, null, null)

/* Local Unitext */
insert into spt_jdbc_datatype_info values
(174, 'unitext', -1, 2147483647, null, null, 2147483647, '''', '''',
null, 1, @case, 1, null, 0, null, 'unitext', 0,
 null, null, null, null, null, null)

/* Java Object for ASE 12 */
insert into spt_jdbc_datatype_info values
(36, 'java.lang.Object', 1111, 2147483647, null, null, 2147483647, '''', '''', 
null, 1, @case, 1, null, 0, null, 'java.lang.Object', 0,
 null, null, null, null, null, null)

/* Local Varbinary */
insert into spt_jdbc_datatype_info values
(37, 'varbinary', -3, null, null, null, null, '0x', null, 
'max length', 1, 0, 2, null, 0, null, 'varbinary', 0,
 null, null, null, null, null, null)

/* Local Tinyint */
insert into spt_jdbc_datatype_info values
(48, 'tinyint', -6, 3, 0, 10, null, null, null, 
null, 1, 0, 2, 1, 0, 0, 'tinyint', 0,
 null, null, null, null, null, null)

/* Local Varchar */
insert into spt_jdbc_datatype_info values
(39, 'varchar', 12, null, null, null, null, '''', '''', 
'max length', 1, @case, 3, null, 0, null, 'varchar', 0,
 null, null, null, null, null, null)

/* Local Univarchar */
insert into spt_jdbc_datatype_info values
(155, 'univarchar', 12, null, null, null, null, '''', '''',
'max length', 1, @case, 3, null, 0, null, 'univarchar', 0,
 null, null, null, null, null, null)

/* Local Image */
insert into spt_jdbc_datatype_info values
(34, 'image', -4, 2147483647, null, null, 2147483647, '0x', null, 
null, 1, 0, 1, null, 0, null, 'image', 0,
 null, null, null, null, null, null)

/* Don't delete the following line. It is the checkpoint for sed */
/* Values for bigint and unsigned types for >=15.0 server  here ADDPOINT_BIGINT_UNSIGNED_TYPES*/
/* INT8 ->191 - bigint */
insert into sybsystemprocs.dbo.spt_jdbc_datatype_info values
(191, 'bigint', -5, 19, 0, 10, null, null, null,
 null, 1, 0, 2, 0, 0, 0, 'bigint', 0,
 null, null, null, null, null, null) 

/* UINT2 ->65 - unsigned smallint    */
insert into sybsystemprocs.dbo.spt_jdbc_datatype_info values
(65, 'unsigned smallint', 5, 5, 0, 10, null, null, null,
 null, 1, 0, 0, 0, 0, 0, 'usmallint', 0,
 null, null, null, null, null, null)

/* UINT4 ->66 - unsigned int     */
 insert into sybsystemprocs.dbo.spt_jdbc_datatype_info values
 (66, 'unsigned int', 4, 10, 0, 10, null, null, null,
  null, 1, 0, 0, 0, 0, 0, 'uint', 0,
  null, null, null, null, null, null)

/* UINT8 ->67 - unsigned bigint    */
insert into sybsystemprocs.dbo.spt_jdbc_datatype_info values 
(67, 'unsigned bigint', -5, 20, 0, 10, null, null, null,
 null, 1, 0, 0, 0, 0, 0, 'ubigint', 0,
 null, null, null, null, null, null)

go

dump tran master with truncate_only
go

/*
**   End of spt_jdbc_datatype_info
*/



/*
**  sp_jdbc_escapeliteralforlike
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select *
	from sysobjects
		where name = 'sp_jdbc_escapeliteralforlike')
begin
	drop procedure sp_jdbc_escapeliteralforlike
end
go
/** SECTION END: CLEANUP **/


/*
** This is a utility procedure which takes an input string
** and places the escape character '\' before any symbol
** which needs to be a literal when used in a LIKE clause.
**
*/
create proc sp_jdbc_escapeliteralforlike @pString varchar(255) output
as
    declare @newString    varchar(255)
    declare @validEscapes varchar(255)
    declare @escapeChar   varchar(10)
    declare @pIndex       int
    declare @pLength      int
    declare @curChar      char(1)
    declare @escapeIndex  int
    declare @escapeLength int
    declare @boolEscapeIt int

    select @pLength = char_length(@pString)
    if (@pString is null) or (@pLength = 0)
    begin
        return
    end

    /*
    ** we will use the backslash as our escape 
    ** character
    */
    select @escapeChar = '\'
    
    /* 
    ** valid escape characters
    */
    select @validEscapes = '%_\[]'
    select @escapeLength = char_length(@validEscapes)

    /* start at the beginning of the string */
    select @pIndex = 1
    select @newString = ''

    while(@pIndex <= @pLength)
    begin
        /*
        ** get the next character of the string
        */
        select @curChar = substring(@pString, @pIndex, 1)
        
        /*
        ** loop through all of the escape characters and
        ** see if the character needs to be escaped
        */
        select @escapeIndex = 1
        select @boolEscapeIt = 0
        while(@escapeIndex <= @escapeLength)
        begin
            /* see if this is a match */
            if (substring(@validEscapes, @escapeIndex, 1) = 
                @curChar)
            begin
                select @boolEscapeIt = 1
                break
            end
            /* move on to the next escape character */
            select @escapeIndex = @escapeIndex + 1
        end
        
        /* build the string */
        if (@boolEscapeIt = 1)
        begin
            select @newString = @newString + @escapeChar + @curChar
        end
        else
        begin
            select @newString = @newString + @curChar
        end

        /* go on to the next character in our source string */
        select @pIndex = @pIndex + 1
    end
        
    /* return to new string to the caller */
    select @pString = ltrim(rtrim(@newString))
    return 0
go

exec sp_procxmode 'sp_jdbc_escapeliteralforlike', 'anymode'
go
grant execute on sp_jdbc_escapeliteralforlike to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_escapeliteralforlike
*/ 


/*Stored procedure to support CTS test suite  ADDPOINT_DATATYPE_INFO_CTS*/
/*
**  sp_jdbc_datatype_info_cts
*/

if exists (select * from sysobjects where name = 'sp_jdbc_datatype_info_cts')
    begin
	drop procedure sp_jdbc_datatype_info_cts
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_datatype_info_cts
as

declare @type_name 	varchar(32)
declare @data_type 	int
declare @precision	int
declare @literal_prefix	varchar(32)
declare @literal_suffix	varchar(32)
declare @create_params	varchar(32)
declare	@nullable	smallint
declare @case_sensitive	tinyint
declare @searchable	smallint
declare @unsigned_attribute	smallint
declare @fixed_prec_scale 	tinyint
declare @auto_increment		tinyint
declare	@local_type_name	varchar(32)
declare @minimum_scale	smallint
declare @maximum_scale	smallint
declare @sql_data_type	int
declare @sql_datetime_sub int
declare @num_prec_radix	int
declare @interval_precision int
declare @startedInTransaction       bit

if @@trancount = 0
begin
        set chained off
end

/* check if we're in a transaction, before we try any select statements */
if (@@trancount > 0)
  select @startedInTransaction = 1
else
  select @startedInTransaction = 0

set transaction isolation level 1

if (@startedInTransaction = 1)
   save transaction jdbc_keep_temptables_from_tx


/* this will make sure that all rows are sent even if
** the client "set rowcount" is differect
*/

set rowcount 0


create table #jdbc_datatype_info_cts
(
    TYPE_NAME    	varchar(32)	null,
    DATA_TYPE    	smallint	null,
    "PRECISION"    	int,
    LITERAL_PREFIX 	varchar(32)	null,
    LITERAL_SUFFIX  	varchar(32)	null,
    CREATE_PARAMS 	varchar(32)	null,
    NULLABLE      	smallint	null,
    CASE_SENSITIVE  	tinyint		null,
    SEARCHABLE     	smallint	null,
    UNSIGNED_ATTRIBUTE 	tinyint		null,
    FIXED_PREC_SCALE    tinyint		null,
    AUTO_INCREMENT     	tinyint		null, 
    LOCAL_TYPE_NAME    	varchar(32)	null,
    MINIMUM_SCALE      	smallint	null,
    MAXIMUM_SCALE     	smallint	null,
    SQL_DATA_TYPE     	int		null,
    SQL_DATETIME_SUB    int		null,
    NUM_PREC_RADIX     	int		null
    
)



    begin 
      declare jdbc_datatype_info_cursor1 cursor for
	select  /* Real SQL Server data types */
            case 
                when t.name = 'usmallint' then 'unsigned smallint'
                when t.name = 'uint' then 'unsigned int'
                when t.name = 'ubigint' then 'unsigned bigint'
            else
                t.name 
            end,
	      d.data_type ,
	      isnull(d.data_precision, convert(int,t.length)),
	      d.literal_prefix ,
	      d.literal_suffix ,
	      e.create_params ,
	      d.nullable ,
	      d.case_sensitive ,
	      d.searchable,
	      d.unsigned_attribute,
	      d.money,
	      d.auto_increment,
	      d.local_type_name,
	      d.minimum_scale,
	      d.maximum_scale,
	      d.sql_data_type,
	      d.sql_datetime_sub,
	      d.num_prec_radix,
	      d.interval_precision
	from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
	      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
	where d.ss_dtype = t.type and t.usertype *= e.user_type
	     /* restrict results to 'real' datatypes, exclude float, date and time*/
	      and t.name not in ('nchar','nvarchar','sysname','timestamp','longsysname', 'float',
                         'datetimn','floatn','intn','moneyn', 'unichar',
                         'univarchar', 'daten', 'timen', 'date', 'time','uintn')
			  and t.usertype < 100    /* No user defined types */
			  
      open jdbc_datatype_info_cursor1

      fetch jdbc_datatype_info_cursor1 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision

	/** start insert the rows by looping thru the cursors */
        while (@@sqlstatus = 0)
        begin
		insert into #jdbc_datatype_info_cts values(
		/* TYPE_NAME */
		@type_name,
		@data_type,
		@precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,	
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@fixed_prec_scale,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix)

      fetch jdbc_datatype_info_cursor1 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	end	
	
      deallocate cursor jdbc_datatype_info_cursor1
      declare jdbc_datatype_info_cursor2 cursor for
	select  /* SQL Server user data types */
            case 
                when t.name = 'usmallint' then 'unsigned smallint'
                when t.name = 'uint' then 'unsigned int'
                when t.name = 'ubigint' then 'unsigned bigint'
            else
                t.name 
            end,
	      d.data_type,
	      isnull(d.data_precision, convert(int,t.length)),
	      d.literal_prefix,
	      d.literal_suffix,
	      e.create_params,
	      d.nullable,
	      d.case_sensitive,
	      d.searchable,
	      d.unsigned_attribute,
	      d.money,
	      d.auto_increment,
	      t.name,
	      d.minimum_scale,
	      d.maximum_scale,
	      d.sql_data_type,
	      d.sql_datetime_sub,
	      d.num_prec_radix,
	      d.interval_precision
	from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
	      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where d.ss_dtype = t.type and t.usertype *= e.user_type
		/* Restrict to user defined types (value > 100)  and Sybase user defined 
		** types (listed)*/
	      and (t.name in ('nchar','nvarchar')
	      or t.usertype >= 100)      /* User defined types */

      open jdbc_datatype_info_cursor2

      fetch jdbc_datatype_info_cursor2 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	
	/** start insert the rows by looping thru the cursors */
        while (@@sqlstatus = 0)
        begin
		insert into #jdbc_datatype_info_cts values(
		/* TYPE_NAME */
		@type_name,
		@data_type,
		@precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,	
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@fixed_prec_scale,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix)

      fetch jdbc_datatype_info_cursor2 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	end	
	
      deallocate cursor jdbc_datatype_info_cursor2	
      declare jdbc_datatype_info_cursor3 cursor for
	select  /* ADD double precision which is floatn internally*/
	      'double precision',
	      8,
	      15,
	      d.literal_prefix,
	      d.literal_suffix,
	      e.create_params,
	      d.nullable,
	      d.case_sensitive,
	      d.searchable,
	      d.unsigned_attribute,
	      d.money,
	      d.auto_increment,
	      'double precision',
	      d.minimum_scale,      
	      d.maximum_scale,
	      d.sql_data_type,
	      d.sql_datetime_sub,
	      d.num_prec_radix,
	      d.interval_precision
		from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
		      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where d.ss_dtype = t.type   and t.usertype *= e.user_type
		      and t.name = 'floatn' and t.usertype < 100 
      open jdbc_datatype_info_cursor3

      fetch jdbc_datatype_info_cursor3 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	
	/** start insert the rows by looping thru the cursors */
        while (@@sqlstatus = 0)
        begin
		insert into #jdbc_datatype_info_cts values(
		/* TYPE_NAME */
		@type_name,
		@data_type,
		@precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,	
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@fixed_prec_scale,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix)

      fetch jdbc_datatype_info_cursor3 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	end	
	
      deallocate cursor jdbc_datatype_info_cursor3	
      declare jdbc_datatype_info_cursor4 cursor for
	select  
	      'float',
	      8,
	      8,
	      d.literal_prefix,
	      d.literal_suffix,
	      e.create_params,
	      d.nullable,
	      d.case_sensitive,
	      d.searchable,
	      d.unsigned_attribute,
	      d.money,
	      d.auto_increment,
	      'float',
	      d.minimum_scale,      
	      d.maximum_scale,
	      d.sql_data_type,
	      d.sql_datetime_sub,
	      d.num_prec_radix,
	      d.interval_precision
	from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
	      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
	where d.ss_dtype = t.type   and t.usertype *= e.user_type
	      and t.name = 'float' and t.usertype < 100  
	      
      open jdbc_datatype_info_cursor4

      fetch jdbc_datatype_info_cursor4 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	
	/** start insert the rows by looping thru the cursors */
        while (@@sqlstatus = 0)
        begin
		insert into #jdbc_datatype_info_cts values(
		/* TYPE_NAME */
		@type_name,
		@data_type,
		@precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,	
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@fixed_prec_scale,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix)

      fetch jdbc_datatype_info_cursor4 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	end	
	
      deallocate cursor jdbc_datatype_info_cursor4	
      declare jdbc_datatype_info_cursor5 cursor for
	select  /* Add date and time now. Special case because we want to use */
        /* d.sql_data_type for DATA_TYPE for these two types          */
            case 
                when t.name = 'usmallint' then 'unsigned smallint'
                when t.name = 'uint' then 'unsigned int'
                when t.name = 'ubigint' then 'unsigned bigint'
            else
                t.name 
            end,
      d.sql_data_type,
      isnull(d.data_precision, convert(int,t.length)),
      d.literal_prefix,
      d.literal_suffix,
      e.create_params,
      d.nullable,
      d.case_sensitive,
      d.searchable,
      d.unsigned_attribute,
      d.money,
      d.auto_increment,
      d.local_type_name,
      d.minimum_scale,
      d.maximum_scale,
      d.sql_data_type,
      d.sql_datetime_sub,
      d.num_prec_radix,
      d.interval_precision
	from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
	      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
	where d.ss_dtype = t.type and t.usertype *= e.user_type
	     /* restrict results to date and time*/
	      and t.name in ('date', 'time')
	      and t.usertype < 100    /* No user defined types */      
      open jdbc_datatype_info_cursor5

      fetch jdbc_datatype_info_cursor5 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	
	/** start insert the rows by looping thru the cursors */
        while (@@sqlstatus = 0)
        begin
		insert into #jdbc_datatype_info_cts values(
		/* TYPE_NAME */
		@type_name,
		@data_type,
		@precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,	
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@fixed_prec_scale,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix)

      fetch jdbc_datatype_info_cursor5 into
 	@type_name,
 	@data_type,
 	@precision,
 	@literal_prefix,
 	@literal_suffix,
 	@create_params,	
 	@nullable,
 	@case_sensitive,
 	@searchable,
 	@unsigned_attribute,
 	@fixed_prec_scale,
 	@auto_increment,
 	@local_type_name,
 	@minimum_scale,
 	@maximum_scale,
 	@sql_data_type,
	@sql_datetime_sub,
	@num_prec_radix,
	@interval_precision
	end	
	
      deallocate cursor jdbc_datatype_info_cursor5	
	      
end /* first begin */

select * from #jdbc_datatype_info_cts order by DATA_TYPE, TYPE_NAME
drop table #jdbc_datatype_info_cts

if (@startedInTransaction = 1)
  rollback transaction jdbc_keep_temptables_from_tx

return(0) 
go
exec sp_procxmode 'sp_jdbc_datatype_info_cts', 'anymode'
go
grant execute on sp_jdbc_datatype_info_cts to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_datatype_info_cts
*/


/*
**  sp_jdbc_datatype_info
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_datatype_info')
    begin
	drop procedure sp_jdbc_datatype_info
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_datatype_info
as

if @@trancount = 0
begin
        set chained off
end

set transaction isolation level 1

/* this will make sure that all rows are sent even if
** the client "set rowcount" is differect
*/

set rowcount 0

select  /* Real SQL Server data types */
    case
        when t.name = 'usmallint' then 'unsigned smallint'
        when t.name = 'uint' then 'unsigned int'
        when t.name = 'ubigint' then 'unsigned bigint'
    else
        t.name
    end as TYPE_NAME,
      d.data_type as DATA_TYPE,
      isnull(d.data_precision, convert(int,t.length)) as 'PRECISION',
      d.literal_prefix as LITERAL_PREFIX,
      d.literal_suffix as LITERAL_SUFFIX,
      e.create_params as CREATE_PARAMS,
      d.nullable as NULLABLE,
      d.case_sensitive as CASE_SENSITIVE,
      d.searchable as SEARCHABLE,
      d.unsigned_attribute as UNSIGNED_ATTRIBUTE,
      d.money as FIXED_PREC_SCALE,
      d.auto_increment as AUTO_INCREMENT,
      d.local_type_name as LOCAL_TYPE_NAME,
      d.minimum_scale as MINIMUM_SCALE,
      d.maximum_scale as MAXIMUM_SCALE,
      d.sql_data_type as SQL_DATA_TYPE,
      d.sql_datetime_sub as SQL_DATETIME_SUB,
      d.num_prec_radix as NUM_PREC_RADIX,
      d.interval_precision as INTERVAL_PRECISION
from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type and t.usertype *= e.user_type
     /* restrict results to 'real' datatypes, exclude float, date and time*/
      and t.name not in ('nchar','nvarchar','sysname','timestamp','longsysname', 'float',
                         'datetimn','floatn','intn','moneyn', 'unichar',
                         'univarchar', 'daten', 'timen', 'date', 'time','uintn')
      and t.usertype < 100    /* No user defined types */
UNION
select  /* SQL Server user data types */
    case
        when t.name = 'usmallint' then 'unsigned smallint'
        when t.name = 'uint' then 'unsigned int'
        when t.name = 'ubigint' then 'unsigned bigint'
    else
        t.name
    end as TYPE_NAME,
      d.data_type,
      isnull(d.data_precision, convert(int,t.length)) as 'PRECISION',
      d.literal_prefix, d.literal_suffix, e.create_params,      d.nullable,
      d.case_sensitive, d.searchable,     d.unsigned_attribute, d.money,
      d.auto_increment, t.name,           d.minimum_scale,      
      d.maximum_scale,  d.sql_data_type,  d.sql_datetime_sub,
      d.num_prec_radix, d.interval_precision
from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type and t.usertype *= e.user_type
/* Restrict to user defined types (value > 100)  and Sybase user defined 
** types (listed)*/
      and (t.name in ('nchar','nvarchar')
      or t.usertype >= 100)      /* User defined types */
UNION                                                  
select  /* ADD double precision which is floatn internally*/
      'double precision',8,                15,
      d.literal_prefix,  d.literal_suffix, e.create_params,      d.nullable,
      d.case_sensitive,  d.searchable,     d.unsigned_attribute, d.money,
      d.auto_increment, 'double precision',d.minimum_scale,      
      d.maximum_scale,   d.sql_data_type,  d.sql_datetime_sub,
      d.num_prec_radix,  d.interval_precision
from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type   and t.usertype *= e.user_type
      and t.name = 'floatn' and t.usertype < 100 
UNION   /* ADD float now */
select  
      'float',           8,                8,
      d.literal_prefix,  d.literal_suffix, e.create_params,      d.nullable,
      d.case_sensitive,  d.searchable,     d.unsigned_attribute, d.money,
      d.auto_increment, 'float',           d.minimum_scale,      
      d.maximum_scale,   d.sql_data_type,  d.sql_datetime_sub,
      d.num_prec_radix,  d.interval_precision
from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type   and t.usertype *= e.user_type
      and t.name = 'float' and t.usertype < 100 
UNION
select  /* Add date and time now. Special case because we want to use */
        /* d.sql_data_type for DATA_TYPE for these two types          */
    case
        when t.name = 'usmallint' then 'unsigned smallint'
        when t.name = 'uint' then 'unsigned int'
        when t.name = 'ubigint' then 'unsigned bigint'
    else
        t.name
    end as TYPE_NAME,
      d.sql_data_type,
      isnull(d.data_precision, convert(int,t.length)),
      d.literal_prefix,
      d.literal_suffix,
      e.create_params,
      d.nullable,
      d.case_sensitive,
      d.searchable,
      d.unsigned_attribute,
      d.money,
      d.auto_increment,
      d.local_type_name,
      d.minimum_scale,
      d.maximum_scale,
      d.sql_data_type,
      d.sql_datetime_sub,
      d.num_prec_radix,
      d.interval_precision
from  sybsystemprocs.dbo.spt_jdbc_datatype_info d,
      sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where d.ss_dtype = t.type and t.usertype *= e.user_type
     /* restrict results to date and time*/
      and t.name in ('date', 'time')
      and t.usertype < 100    /* No user defined types */
order by DATA_TYPE, TYPE_NAME

return(0) 
go
exec sp_procxmode 'sp_jdbc_datatype_info', 'anymode'
go
grant execute on sp_jdbc_datatype_info to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_datatype_info
*/


/*
**  sp_drv_column_default
**  Note: ASE 12.0 and earlier complain if this proc isn't created before
**        sp_jdbc_columns, because sp_jdbc_columns calls this proc. Therefore,
**        make sure this proc is created first at metadata install time. 
*/

/* 
** obtain a column's default value -- this is a utility proc called by
** sp_jdbc_columns
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go
 
if exists (select * from sysobjects where name = 'sp_drv_column_default')
begin
        drop procedure sp_drv_column_default
end
go
/** SECTION END: CLEANUP **/

create procedure sp_drv_column_default
/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ADDPOINT_COL_DEFAULT */
     (@obj_id int, @default_value varchar (1024) output)
as
    declare @text_count                      int
    declare @default_holder                  varchar (255)
    declare @rownum                          int
    declare @default_starts                  int
    declare @create_default_starts           int
    declare @actual_default_starts           int
    declare @as_starts                       int
    declare @length                          int
    declare @check_case_one                  int
    declare @lf_plus_null_chars              char (2)
    declare @last_two_chars                  char (2)
    declare @check_last_two_chars            int

    /* make sure @default_value starts out as empty */
    select @default_value = null

    /* initialize @check_case_one to false (0) */
    select @check_case_one = 0

    /* initialize @check_last_two_chars to false (0) */
    select @check_last_two_chars = 0

    /* initialize the @lf_plus_null_chars variable to linefeed + null */
    select @lf_plus_null_chars = char (10) + char (0)

    /* Find out how many rows there are in syscomments defining the 
       default. If there are none, then we return a null */
    select @text_count = count (*) from syscomments
        where id = @obj_id

    if @text_count = 0
    begin
        return 0
    end

    /* See if the object is hidden (SYSCOM_TEXT_HIDDEN will be set).
       If it is, best we can do is return null */
    if exists (select 1 from syscomments where (status & 1 = 1)
        and id = @obj_id)
    begin
        return 0
    end

    select @rownum = 1
    declare default_value_cursor cursor for
        select text from syscomments where id = @obj_id
        order by number, colid2, colid

    open default_value_cursor

    fetch default_value_cursor into @default_holder
 
    while (@@sqlstatus = 0)
    begin

        if @rownum = 1
        begin
            /* find the default value
            **  Note that ASE stores default values in more than one way:
            **    1. If a client declares the column default value in the
            **       table definition, ASE will store the word DEFAULT (in
            **       all caps) followed by the default value, exactly as the
            **       user entered it (meaning it will include quotes, if the
            **       value was a string constant). This DEFAULT word will
            **       be in all caps even if the user did something like this:
            **           create table foo (col1 varchar (10) DeFaULT 'bar')
            **    2. If a client does sp_bindefault to bind a default to
            **       a column, ASE will include the text of the create default
            **       command, as entered. So, if the client did the following:
            **           create DeFAULt foo aS 'bar'
            **       that is exactly what ASE will place in the text column
            **       of syscomments.
            **       In this case, too, we have to be careful because ASE
            **       will sometimes include a newline character followed by
            **       a null at the end of the create default statement. This
            **       can happen if a client uses C isql to type in the
            **       create default command (if it comes in through java, then
            **       the newline and null are not present).
            **  Because of this, we have to be careful when trying to parse out
            **  the default value. */

            select @length = char_length (@default_holder)
            select @create_default_starts =
                charindex ('create default', lower(@default_holder))
            select @as_starts = charindex(' as ', lower(@default_holder))
            select @default_starts = charindex ('DEFAULT', @default_holder)

            if (@create_default_starts != 0 and @as_starts != 0)
            begin

                /* If we get here, then we likely have case (2) above.
                ** However, it's still possible that the client did something
                ** like this:
                **     create table foo (col1 varchar (20) default
                **         'create default foo as bar')
                ** The following if block accounts for that possibility  */

                if (@default_starts != 0 and
                  @default_starts < @create_default_starts)
                begin
                    select @check_case_one = 1
                end
                else
                begin
                    select @actual_default_starts = @as_starts + 4
                    select @check_last_two_chars = 1

                    /* set @default_starts to 0 so we don't fall into the
                    ** next if block. This is important because we would
                    ** fall into the next if block if a client had used the
                    ** following sql:
                    **     CREATE DEFAULT foo as 'bar' */
                    select @default_starts = 0
                end
            end

            if (@default_starts != 0 or @check_case_one != 0)
                /* If we get here, then we have case (1) above */

                select @actual_default_starts = @default_starts + 7

            /* The ltrim removes any left-side blanks, because ASE appears
            ** to insert several blanks between the word DEFAULT and the
            ** start of the default vale */

            select @default_holder =
                ltrim(substring
                    (@default_holder, @actual_default_starts, @length))

        end

        select @default_value = @default_value + @default_holder
        select @rownum = @rownum + 1

        fetch default_value_cursor into @default_holder

    end /* while loop */

    close default_value_cursor

    /* trim off any right-side blanks */
    select @default_value = rtrim (@default_value)

    /* trim off the newline and null characters, if they're the last
    ** two characters in what remains */
    if (@check_last_two_chars = 1)
    begin

        select @length = char_length (@default_value)
        select @last_two_chars = substring (@default_value, (@length - 1), 2)
        if (@last_two_chars = @lf_plus_null_chars)
            select @default_value = substring (@default_value, 1, (@length - 2))
    end

    return 0


go
exec sp_procxmode 'sp_drv_column_default', 'anymode'
go
grant execute on sp_drv_column_default to public
go
dump transaction sybsystemprocs with truncate_only 
go

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ADDPOINT_DRIVERS_COMMON */
if exists (select *
        from sysobjects
                where sysstat & 7 = 4
                        and name = 'sp_drv_typeinfo')
begin
        drop procedure sp_drv_typeinfo
end
go


create procedure sp_drv_typeinfo(@sstype int)
as
        declare @curiso int
        select @curiso=@@isolation
        if @@isolation = 0
        begin
               
                set transaction isolation level 1
        end

        select literal_prefix, literal_suffix, case_sensitive, searchable, unsigned_attribute, num_prec_radix from sybsystemprocs.dbo.spt_datatype_info where ss_dtype = @sstype
        /*Not necessary, just for more clear logic */
        if @curiso = 0
        begin
                set transaction isolation level 0
        end


        return(0)
go

exec sp_procxmode 'sp_drv_typeinfo', 'anymode'
go
grant execute on sp_drv_typeinfo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


if exists (select *
        from sysobjects
                where sysstat & 7 = 4
                        and name = 'sp_localtypename')
begin
        drop procedure sp_localtypename
end
go

create procedure sp_localtypename(@sstype int)
as

        declare @curiso int
        select @curiso=@@isolation
        if @@isolation = 0
        begin
               
                set transaction isolation level 1
        end
        select local_type_name from sybsystemprocs.dbo.spt_datatype_info where ss_dtype = @sstype

        if @curiso = 0
        begin
                set transaction isolation level 0
        end
        return(0)
go

exec sp_procxmode 'sp_localtypename', 'anymode'
go
grant execute on sp_localtypename to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


/*
**  sp_jdbc_columns
*/

use sybsystemprocs 
go

/* create a 1-off version of sp_jdbc_columns that has the additional
** columns required for ODBC 2.0 and more columns required by
** JDBC (from ODBC 3.0?).
*/

/** SECTION BEGIN: CLEANUP **/
if exists (select * from sysobjects where name = 'sp_jdbc_columns')
    begin
	drop procedure sp_jdbc_columns
    end
go
/** SECTION END: CLEANUP **/


/* This is the version for servers which support UNION */

CREATE PROCEDURE sp_jdbc_columns (
    @table_name         varchar(771),
    @table_owner        varchar(32 ) = null,
    @table_qualifier    varchar(32 ) = null,
    @column_name        varchar(771) = null )
AS
/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_COLS */

    declare @o_uid              int
    declare @o_name             varchar (257)
    declare @d_data_type        smallint
    declare @d_aux              int
    declare @d_ss_dtype         tinyint
    declare @d_type_name        varchar (257)
    declare @d_data_precision   int
    declare @d_numeric_scale    smallint
    declare @d_numeric_radix    smallint
    declare @d_sql_data_type    smallint
    declare @c_name             varchar (257)
    declare @c_length           int
    declare @c_prec             tinyint
    declare @c_scale            tinyint
    declare @c_type             tinyint
    declare @c_colid            smallint
    declare @c_status           tinyint
    declare @c_cdefault         int
    declare @xtname             varchar (255)
    declare @ident              bit
  
    declare @msg              varchar(250)
    declare @full_table_name  varchar(1542)
    declare @table_id         int
    declare @char_bin_types   varchar(30)
    declare @uni_types        varchar (10)
    declare @column_default   varchar (1024)
    declare @startedInTransaction bit





    if (@@trancount = 0)
    begin
        set chained off
    end

    if (@@trancount > 0)
        select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

    set transaction isolation level 1

    if (@startedInTransaction = 1)
        save transaction jdbc_keep_temptables_from_tx

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    /* character and binary datatypes */
    select @char_bin_types =
        char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

    /* unichar, univarchar and unitext datatypes */
    /* Note that the actual type numbers are 155 (unichar), 135 (univarchar)
       and 174 (unitext), but because of issues that can arise when a server
       has utf-8 as the default charset and a non-binary sort order, we need
       to create a character string that is valid in utf-8. Therefore we 
       apply an offset of 60 to move the characters to be valid utf-8 chars.
       The stored proc later does a similar calculation to utilize these
       values properly */
    select @uni_types =
        char(95)+char(75)+char(114)

    if @column_name is null select @column_name = '%'
    
    if @table_qualifier is not null
    begin
        if db_name() != @table_qualifier
        begin	/* 
            ** If qualifier doesn't match current database: 18039
            ** Table qualifier must be name of current database
            */
            exec sp_getmessage 18039, @msg output
            raiserror 18039 @msg
            return (1)
        end
    end
    
    if @table_name is null
    begin	/*	If table name not supplied, match all */
        select @table_name = '%'
    end

    if @table_owner is null
    begin       /* If unqualified table name */
        SELECT @full_table_name = @table_name
        select @table_owner = '%'
    end
    else
    begin       /* Qualified table name */
        SELECT @full_table_name = @table_owner + '.' + @table_name
    end

    /* create the temp table to hold our results */

    create table #jdbc_columns (
        TABLE_CAT         varchar (32) null,
        TABLE_SCHEM       varchar (32) null,
        TABLE_NAME        varchar (257) null,
        COLUMN_NAME       varchar (257) null,
        DATA_TYPE         smallint null,
        TYPE_NAME         varchar (255) null,
        COLUMN_SIZE       int null,
        BUFFER_LENGTH     int null,
        DECIMAL_DIGITS    int null,
        NUM_PREC_RADIX    int null,
        NULLABLE          int null,
        REMARKS           varchar (255) null,
        COLUMN_DEF        varchar (512) null,
        SQL_DATA_TYPE     int null,
        SQL_DATETIME_SUB  int null,
        CHAR_OCTET_LENGTH int null,
        ORDINAL_POSITION  int null,
        IS_NULLABLE       varchar (10) null)


 
    /* Decide if we're going to take the branch where we are getting
       information on one table (first branch), or more than one */

    /* Get Object ID */
    SELECT @table_id = object_id(@full_table_name)
       /* If the table name parameter is valid, get the information */
    if ((charindex('%',@full_table_name) = 0) and
        (charindex('_',@full_table_name) = 0)  and
        (@table_id != 0))

    begin 

      declare jdbc_columns_cursor1 cursor for
        SELECT 
               c.cdefault,
               c.colid,
               c.length,
               c.name,
               c.prec,
               c.scale,
               c.status,
               c.type,
               d.aux, 
               d.data_precision,
               d.data_type,
               d.numeric_radix,
               d.numeric_scale,
               d.sql_data_type,
               d.ss_dtype,
               t.name,
               o.name,
               o.uid,
               xtname,
               convert(bit, (c.status & 0x80)) 

          FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdbc_datatype_info d,
            sysxtypes x,
            systypes t
        WHERE
            o.id = @table_id
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            AND t.type = d.ss_dtype
            and c.xtype *= x.xtid
            AND o.type != 'P'
            AND c.name like @column_name ESCAPE '\'
            AND d.ss_dtype IN (111, 109, 38, 110, 68)       /* Just *N types */
            AND c.usertype < 100

      open jdbc_columns_cursor1

      fetch jdbc_columns_cursor1 into
        @c_cdefault,
        @c_colid,
        @c_length,
        @c_name,
        @c_prec,
        @c_scale,
        @c_status,
        @c_type,
        @d_aux, 
        @d_data_precision,
        @d_data_type,
        @d_numeric_radix,
        @d_numeric_scale,
        @d_sql_data_type,
        @d_ss_dtype,
        @d_type_name,
        @o_name,
        @o_uid,
        @xtname,
        @ident 

        /* INTn, FLOATn, DATETIMEn and MONEYn types */

        while (@@sqlstatus = 0)
        begin

          exec sp_drv_column_default @c_cdefault, @column_default out
 
          INSERT INTO #jdbc_columns values (
            /* TABLE_CAT */
            DB_NAME(),

            /* TABLE_SCHEM */
            USER_NAME (@o_uid),

            /* TABLE_NAME */
            @o_name,

            /* COLUMN_NAME */
            @c_name,

            /* DATA_TYPE */
            @d_data_type+convert(smallint,
                        isnull(@d_aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                        -60)),

            /* TYPE_NAME */
            case
                when @ident = 1 then
                        case 
                            when @d_type_name = 'usmallint' then 'unsigned smallint identity'
                            when @d_type_name = 'uint' then 'unsigned int identity'
                            when @d_type_name = 'ubigint' then 'unsigned bigint identity'
                            else
                                    isnull(@xtname, rtrim(substring(@d_type_name,
                                    1+isnull(@d_aux,
                                    ascii(substring('III<<<MMMI<<A<A',
                                    2*(@d_ss_dtype%35+1)+2-8/@c_length,
                                    1))-60), 255)))+' identity'
                            end
                when @d_type_name = 'usmallint' then 'unsigned smallint'
                when @d_type_name = 'uint' then 'unsigned int'
                when @d_type_name = 'ubigint' then 'unsigned bigint'
                else
                    isnull(@xtname, rtrim(substring(@d_type_name,
                    1+isnull(@d_aux,
                    ascii(substring('III<<<MMMI<<A<A',
                    2*(@d_ss_dtype%35+1)+2-8/@c_length,
                    1))-60), 255)))
            end,

            /* COLUMN_SIZE */
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                             convert(int, @c_length)))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* BUFFER_LENGTH */
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                             convert(int, @c_length)))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* DECIMAL_DIGITS */ 
            isnull(convert(smallint, @c_scale), 
                       convert(smallint, @d_numeric_scale)) +
                        convert(smallint, isnull(@d_aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60)),

            /* NUM_PREC_RADIX */
            @d_numeric_radix,

            /* NULLABLE */
            /* set nullability from status flag */
            convert(smallint, convert(bit, @c_status&8)),

            /* REMARKS */
            convert(varchar(254),null),	/* Remarks are NULL */

            /* COLUMN_DEF */
            @column_default,

            /* SQL_DATA_TYPE */
            isnull(@d_sql_data_type,
                      @d_data_type+convert(smallint,
                      isnull(@d_aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                      -60))),

            /* SQL_DATATIME_SUB */
            NULL,

            /* CHAR_OCTET_LENGTH */
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (155, 135, 47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */
                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, 
                    substring('0111111', 
                        charindex(char(@c_type), @char_bin_types) +
                        charindex(char(@c_type-60), @uni_types) + 1, 1)) *
                /* calculate the precision */
                isnull(convert(int, @c_prec),
                    isnull(convert(int, @d_data_precision),
                        convert(int,@c_length)))
                    +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
       
            /* ORDINAL_POSITION */
            @c_colid,

            /* IS_NULLABLE */
            rtrim(substring('NO YES', convert(smallint, 
                convert(bit, @c_status&8)*3)+1, 3))
            ) /* close paren for values (*) */ 

          fetch jdbc_columns_cursor1 into
            @c_cdefault,
            @c_colid,
            @c_length,
            @c_name,
            @c_prec,
            @c_scale,
            @c_status,
            @c_type,
            @d_aux, 
            @d_data_precision,
            @d_data_type,
            @d_numeric_radix,
            @d_numeric_scale,
            @d_sql_data_type,
            @d_ss_dtype,
            @d_type_name,
            @o_name,
            @o_uid,
            @xtname,
            @ident
 
      end

      deallocate cursor jdbc_columns_cursor1

      declare jdbc_columns_cursor2 cursor for
        SELECT 
               c.cdefault,
               c.colid,
               c.length,
               c.name,
               c.prec,
               c.scale,
               c.status,
               c.type,
               d.aux, 
               d.data_precision,
               d.data_type,
               d.numeric_radix,
               d.numeric_scale,
               d.sql_data_type,
               d.ss_dtype,
               t.name,
               o.name,
               o.uid,
               xtname,
               convert(bit, (c.status & 0x80)) 
        FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdbc_datatype_info d,
	    sysxtypes x,
            systypes t
        WHERE
            o.id = @table_id
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106 
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            /*
            ** We need a equality join with 
            ** sybsystemprocs.dbo.spt_jdbc_datatype_info here so that
            ** there is only one qualified row returned from 
            ** sybsystemprocs.dbo.spt_jdbc_datatype_info, thus avoiding
            ** duplicates.
            */
            AND t.type = d.ss_dtype
	    and c.xtype *= x.xtid
            AND o.type != 'P'
            AND c.name like @column_name ESCAPE '\'
            AND (d.ss_dtype NOT IN (111, 109, 38, 110, 68) /* No *N types */
                OR c.usertype >= 100) /* User defined types */

      open jdbc_columns_cursor2

      fetch jdbc_columns_cursor2 into
          @c_cdefault,
          @c_colid,
          @c_length,
          @c_name,
          @c_prec,
          @c_scale,
          @c_status,
          @c_type,
          @d_aux, 
          @d_data_precision,
          @d_data_type,
          @d_numeric_radix,
          @d_numeric_scale,
          @d_sql_data_type,
          @d_ss_dtype,
          @d_type_name,
          @o_name,
          @o_uid,
          @xtname,
          @ident

      while (@@sqlstatus = 0)
      begin
 
          exec sp_drv_column_default @c_cdefault, @column_default out
          
          /* All other types including user data types */

          INSERT INTO #jdbc_columns values (
            
            /* TABLE_CAT */ 
            DB_NAME(),

            /* TABLE_SCHEM */
            USER_NAME(@o_uid),

            /* TABLE_NAME */
            @o_name,

            /*COLUMN_NAME*/
            @c_name,

            /* DATA_TYPE */
            @d_data_type+convert(smallint,
                        isnull(@d_aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                        -60)),
 
            /* TYPE_NAME */
            case
                when @ident = 1 then
                        case 
                            when @d_type_name = 'usmallint' then 'unsigned smallint identity'
                            when @d_type_name = 'uint' then 'unsigned int identity'
                            when @d_type_name = 'ubigint' then 'unsigned bigint identity'
                            else
                            isnull(@xtname, rtrim(substring(@d_type_name,
                            1+isnull(@d_aux,
                            ascii(substring('III<<<MMMI<<A<A',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,
                            1))-60), 255)))+' identity'
                        end
                when @d_type_name = 'usmallint' then 'unsigned smallint'
                when @d_type_name = 'uint' then 'unsigned int'
                when @d_type_name = 'ubigint' then 'unsigned bigint'
                else
                        isnull(@xtname, rtrim(substring(@d_type_name,
                        1+isnull(@d_aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60), 255)))
            end, 

            /* COLUMN_SIZE */  
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                        convert(int,@c_length / (1 +
                           (convert(smallint,
                            substring('011',
                        charindex(char(@c_type-60 ), @uni_types)+1, 1)))))))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
    
            /* BUFFER_LENGTH */ 
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                             convert(int, @c_length)))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* DECIMAL_DIGITS */ 
            isnull(convert(smallint, @c_scale),
                       convert(smallint, @d_numeric_scale)) +
                        convert(smallint, isnull(@d_aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60)),

            /* NUM_PREC_RADIX */
            @d_numeric_radix,

            /* NULLABLE */
            convert(smallint, convert(bit, @c_status&8)),

            /* REMARKS */
            convert(varchar(254),null),

            /* COLUMN_DEF */
            @column_default,

            /* SQL_DATA_TYPE */
            isnull(@d_sql_data_type,
                      @d_data_type+convert(smallint,
                      isnull(@d_aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                      -60))),

            /* SQL_DATETIME_SUB */
            NULL,

            /* CHAR_OCTET_LENGTH */
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (155, 135, 47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */

                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, substring('0111111', 
                    charindex(char(@c_type), @char_bin_types) +
                    charindex(char(@c_type-60), @uni_types) + 1, 1)) *
                /* calculate the precision */
                isnull(convert(int, @c_prec),
                    isnull(convert(int, @d_data_precision),
                        convert(int,@c_length)))
                    +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* ORDINAL_POSITION */
            @c_colid,

            /* IS_NULLABLE */
            rtrim(substring('NO YES', convert(smallint, 
                convert(bit, @c_status&8)*3)+1, 3))
  
          ) /* close paren for values (*) */
 
          fetch jdbc_columns_cursor2 into
              @c_cdefault,
              @c_colid,
              @c_length,
              @c_name,
              @c_prec,
              @c_scale,
              @c_status,
              @c_type,
              @d_aux, 
              @d_data_precision,
              @d_data_type,
              @d_numeric_radix,
              @d_numeric_scale,
              @d_sql_data_type,
              @d_ss_dtype,
              @d_type_name,
              @o_name,
              @o_uid,
              @xtname,
              @ident

        end /* while loop */

      deallocate cursor jdbc_columns_cursor2

    end   /* if we have just one table */
 
    else
    begin

      /* We'll be iterating over more than one table */

      declare jdbc_columns_cursor3 cursor for
        select
               c.cdefault,
               c.colid,
               c.length,
               c.name,
               c.prec,
               c.scale,
               c.status,
               c.type,
               d.aux, 
               d.data_precision,
               d.data_type,
               d.numeric_radix,
               d.numeric_scale,
               d.sql_data_type,
               d.ss_dtype,
               t.name,
               o.name,
               o.uid,
               xtname,
               convert(bit, (c.status & 0x80))

          FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdbc_datatype_info d,
            sysxtypes x,
            systypes t

        WHERE
            o.name like @table_name ESCAPE '\'
            AND user_name(o.uid) like @table_owner ESCAPE '\'
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            AND t.type = d.ss_dtype
            AND o.type != 'P'
            and c.xtype *= x.xtid
            AND c.name like @column_name ESCAPE '\'
            AND d.ss_dtype IN (111, 109, 38, 110, 68)       /* Just *N types */
            AND c.usertype < 100

        open jdbc_columns_cursor3

        fetch jdbc_columns_cursor3 into
          @c_cdefault,
          @c_colid,
          @c_length,
          @c_name,
          @c_prec,
          @c_scale,
          @c_status,
          @c_type,
          @d_aux, 
          @d_data_precision,
          @d_data_type,
          @d_numeric_radix,
          @d_numeric_scale,
          @d_sql_data_type,
          @d_ss_dtype,
          @d_type_name,
          @o_name,
          @o_uid,
          @xtname,
          @ident


        /* INTn, FLOATn, DATETIMEn and MONEYn types */

        while (@@sqlstatus = 0)
        begin

          exec sp_drv_column_default @c_cdefault, @column_default out
 
          INSERT INTO #jdbc_columns values (
            /* TABLE_CAT */
            DB_NAME(),

            /* TABLE_SCHEM */
            USER_NAME(@o_uid),

            /* TABLE_NAME */
            @o_name,

            /* COLUMN_NAME */
            @c_name,

            /* DATA_TYPE */
            @d_data_type+convert(smallint,
                        isnull(@d_aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                        -60)),

            /* TYPE_NAME */
            case
                when @ident = 1 then
                        case 
                            when @d_type_name = 'usmallint' then 'unsigned smallint identity'
                            when @d_type_name = 'uint' then 'unsigned int identity'
                            when @d_type_name = 'ubigint' then 'unsigned bigint identity'
                            else
                            isnull(@xtname, rtrim(substring(@d_type_name,
                            1+isnull(@d_aux,
                            ascii(substring('III<<<MMMI<<A<A',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,
                            1))-60), 255)))+' identity'
                        end
                when @d_type_name = 'usmallint' then 'unsigned smallint'
                when @d_type_name = 'uint' then 'unsigned int'
                when @d_type_name = 'ubigint' then 'unsigned bigint'
                else
                        isnull(@xtname, rtrim(substring(@d_type_name,
                        1+isnull(@d_aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60), 255)))
            end,

            /* COLUMN_SIZE */
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                             convert(int, @c_length)))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* BUFFER_LENGTH */
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                             convert(int, @c_length)))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* DECIMAL_DIGITS */ 
            isnull(convert(smallint, @c_scale), 
                       convert(smallint, @d_numeric_scale)) +
                        convert(smallint, isnull(@d_aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60)),

            /* NUM_PREC_RADIX */
            @d_numeric_radix,

            /* NULLABLE */
            /* set nullability from status flag */
            convert(smallint, convert(bit, @c_status&8)),

            /* REMARKS */
            convert(varchar(254),null),	/* Remarks are NULL */

            /* COLUMN_DEF */
            @column_default,

            /* SQL_DATA_TYPE */
            isnull(@d_sql_data_type,
                      @d_data_type+convert(smallint,
                      isnull(@d_aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                      -60))),

            /* SQL_DATATIME_SUB */
            NULL,

            /* CHAR_OCTET_LENGTH */
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (155, 135, 47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */

                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, 
                    substring('0111111', 
                        charindex(char(@c_type), @char_bin_types) +
                        charindex(char(@c_type-60), @uni_types) + 1, 1)) *
                /* calculate the precision */
                isnull(convert(int, @c_prec),
                    isnull(convert(int, @d_data_precision),
                        convert(int,@c_length)))
                    +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
       
            /* ORDINAL_POSITION */
            @c_colid,

            /* IS_NULLABLE */
            rtrim(substring('NO YES', convert(smallint, 
                convert(bit, @c_status&8)*3)+1, 3))

          ) /* right paren for values (*) */
          
          fetch jdbc_columns_cursor3 into
              @c_cdefault,
              @c_colid,
              @c_length,
              @c_name,
              @c_prec,
              @c_scale,
              @c_status,
              @c_type,
              @d_aux, 
              @d_data_precision,
              @d_data_type,
              @d_numeric_radix,
              @d_numeric_scale,
              @d_sql_data_type,
              @d_ss_dtype,
              @d_type_name,
              @o_name,
              @o_uid,
              @xtname,
              @ident

        end /* while loop */

        deallocate cursor jdbc_columns_cursor3

        declare jdbc_columns_cursor4 cursor for
        SELECT 
               c.cdefault,
               c.colid,
               c.length,
               c.name,
               c.prec,
               c.scale,
               c.status,
               c.type,
               d.aux, 
               d.data_precision,
               d.data_type,
               d.numeric_radix,
               d.numeric_scale,
               d.sql_data_type,
               d.ss_dtype,
               t.name,
               o.name,
               o.uid,
               xtname,
               convert(bit, (c.status & 0x80))
        FROM
            syscolumns c,
            sysobjects o,
            sybsystemprocs.dbo.spt_jdbc_datatype_info d,
	    sysxtypes x,
            systypes t
        WHERE
            o.name like @table_name ESCAPE '\'
            AND user_name(o.uid) like @table_owner ESCAPE '\'
	    and c.xtype *= x.xtid 
            AND o.id = c.id
            /*
            ** We use syscolumn.usertype instead of syscolumn.type
            ** to do join with systypes.usertype. This is because
            ** for a column which allows null, type stores its
            ** Server internal datatype whereas usertype still
            ** stores its user defintion datatype.  For an example,
            ** a column of type 'decimal NULL', its usertype = 26,
            ** representing decimal whereas its type = 106 
            ** representing decimaln. nullable in the select list
            ** already tells user whether the column allows null.
            ** In the case of user defining datatype, this makes
            ** more sense for the user.
            */
            AND c.usertype = t.usertype
            /*
            ** We need a equality join with 
            ** sybsystemprocs.dbo.spt_jdbc_datatype_info here so that
            ** there is only one qualified row returned from 
            ** sybsystemprocs.dbo.spt_jdbc_datatype_info, thus avoiding
            ** duplicates.
            */
            AND t.type = d.ss_dtype
            AND o.type != 'P'
            AND c.name like @column_name ESCAPE '\'
            AND (d.ss_dtype NOT IN (111, 109, 38, 110, 68) /* No *N types */
                OR c.usertype >= 100) /* User defined types */

          open jdbc_columns_cursor4

          fetch jdbc_columns_cursor4 into
              @c_cdefault,
              @c_colid,
              @c_length,
              @c_name,
              @c_prec,
              @c_scale,
              @c_status,
              @c_type,
              @d_aux, 
              @d_data_precision,
              @d_data_type,
              @d_numeric_radix,
              @d_numeric_scale,
              @d_sql_data_type,
              @d_ss_dtype,
              @d_type_name,
              @o_name,
              @o_uid,
              @xtname,
              @ident


        while (@@sqlstatus = 0)
        begin
          exec sp_drv_column_default @c_cdefault, @column_default out

          /* All other types including user data types */
          INSERT INTO #jdbc_columns values (

            /* TABLE_CAT */ 
            DB_NAME(),

            /* TABLE_SCHEM */
            USER_NAME(@o_uid),

            /* TABLE_NAME */
            @o_name,

            /*COLUMN_NAME*/
            @c_name,

            /* DATA_TYPE */
            @d_data_type+convert(smallint,
                        isnull(@d_aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                        -60)),
 
            /* TYPE_NAME */
            case
                when @ident = 1 then
                        case 
                            when @d_type_name = 'usmallint' then 'unsigned smallint identity'
                            when @d_type_name = 'uint' then 'unsigned int identity'
                            when @d_type_name = 'ubigint' then 'unsigned bigint identity'
                            else
                            isnull(@xtname, rtrim(substring(@d_type_name,
                            1+isnull(@d_aux,
                            ascii(substring('III<<<MMMI<<A<A',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,
                            1))-60), 255)))+' identity'
                        end
                when @d_type_name = 'usmallint' then 'unsigned smallint'
                when @d_type_name = 'uint' then 'unsigned int'
                when @d_type_name = 'ubigint' then 'unsigned bigint'
                else
                        isnull(@xtname, rtrim(substring(@d_type_name,
                        1+isnull(@d_aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60), 255)))
            end, 

            /* COLUMN_SIZE */  
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                        convert(int,@c_length / (1 +
                           (convert(smallint,
                            substring('011',
                        charindex(char(@c_type-60), @uni_types)+1, 1)))))))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
    
            /* BUFFER_LENGTH */ 
            isnull(convert(int, @c_prec),
                      isnull(convert(int, @d_data_precision),
                             convert(int, @c_length)))
                        +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* DECIMAL_DIGITS */ 
            isnull(convert(smallint, @c_scale),
                       convert(smallint, @d_numeric_scale)) +
                        convert(smallint, isnull(@d_aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(@d_ss_dtype%35+1)+2-8/@c_length,
                        1))-60)),

            /* NUM_PREC_RADIX */
            @d_numeric_radix,

            /* NULLABLE */
            convert(smallint, convert(bit, @c_status&8)),

            /* REMARKS */
            convert(varchar(254),null),

            /* COLUMN_DEF */
            @column_default,

            /* SQL_DATA_TYPE */
            isnull(@d_sql_data_type,
                      @d_data_type+convert(smallint,
                      isnull(@d_aux,
                      ascii(substring('666AAA@@@CB??GG',
                      2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
                      -60))),

            /* SQL_DATETIME_SUB */
            NULL,

            /* CHAR_OCTET_LENGTH */
            /*
            ** if the datatype is of type CHAR or BINARY
            ** then set char_octet_length to the same value
            ** assigned in the "prec" column.
            **
            ** The first part of the logic is:
            **
            **   if(c.type is in (155, 135, 47, 39, 45, 37, 35, 34))
            **       set char_octet_length = prec;
            **   else
            **       set char_octet_length = 0;
            */

                /*
                ** check if in the list
                ** if so, return a 1 and multiply it by the precision 
                ** if not, return a 0 and multiply it by the precision
                */
                convert(smallint, substring('0111111', 
                    charindex(char(@c_type), @char_bin_types) +
                    charindex(char(@c_type-60), @uni_types) + 1, 1)) *
                /* calculate the precision */
                isnull(convert(int, @c_prec),
                    isnull(convert(int, @d_data_precision),
                        convert(int,@c_length)))
                    +isnull(@d_aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                            2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),

            /* ORDINAL_POSITION */
            @c_colid,

            /* IS_NULLABLE */
            rtrim(substring('NO YES', convert(smallint, convert(bit, @c_status&8)*3)+1, 3))
  
          ) /* close paren for values (*) */

          fetch jdbc_columns_cursor4 into
              @c_cdefault,
              @c_colid,
              @c_length,
              @c_name,
              @c_prec,
              @c_scale,
              @c_status,
              @c_type,
              @d_aux, 
              @d_data_precision,
              @d_data_type,
              @d_numeric_radix,
              @d_numeric_scale,
              @d_sql_data_type,
              @d_ss_dtype,
              @d_type_name,
              @o_name,
              @o_uid,
              @xtname,
              @ident

         end /* while loop */ 
         
         deallocate cursor jdbc_columns_cursor4

    end           

    SELECT * FROM #jdbc_columns
        ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION

    drop table #jdbc_columns

    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx 
 
    return(0)


go
exec sp_procxmode 'sp_jdbc_columns', 'anymode'
go
grant execute on sp_jdbc_columns to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_columns
*/


/*
**  sp_jdbc_tables
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_tables')
begin
	drop procedure sp_jdbc_tables
end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_tables
    @table_name       varchar(771)  = null,
    @table_owner      varchar(32 )  = null,
    @table_qualifier  varchar(32 )  = null,
    @table_type       varchar(100) = null
as
    declare @msg varchar(90)
    declare @searchstr varchar(255)

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0



    /* temp table */
   /* Adding tempdb check here depending on the ASE version ADDTEMPDB */

   if (@table_name like '#%' and db_name() != db_name(tempdb_id()))
    begin
        /*
        ** Can return data about temp. tables only in tempdb
        */
        exec sp_getmessage 17676, @msg out
        raiserror 17676 @msg
        return(1)
    end
        if @table_qualifier is not null
        begin
            if db_name() != @table_qualifier
            begin
            exec sp_getmessage 18039, @msg out
            raiserror 18039 @msg
            return 1
        end
    end

    if @table_name is null select @table_name = '%'
    if @table_owner is null select @table_owner = '%'

    select @searchstr = ''
    if (patindex('%''SYSTEM%',upper(@table_type)) > 0)
        select @searchstr = @searchstr + 'S'

    if (patindex('%''TABLE''%',upper(@table_type)) > 0)
        select @searchstr = @searchstr +'U'
    
    if (patindex('%''VIEW''%',upper(@table_type)) > 0) 
        select @searchstr = @searchstr +'V' 
    
    if @table_type is null 
        select @searchstr = 'SUV'
    if ((@table_type is not null) and (@searchstr=''))
    begin
        exec sp_getmessage 17301, @msg output
        raiserror 17301 @msg, @table_type
        return(3)
    end

    /*
    ** Just return an empty result set with properly named columns
    ** if (select count(*) from sysobjects where user_name(uid) like @table_owner
    **    	            and name like @table_name
    ** 		    and charindex(substring(type,1,1),@searchstr)! = 0) = 0 
    ** begin
    ** 	exec sp_getmessage 17674, @msg output
    ** 	raiserror 17674 @msg
    ** 	return(1)
    ** end
    */

    select
        TABLE_CAT =  rtrim(db_name()),
        TABLE_SCHEM= rtrim(user_name(uid)),
        TABLE_NAME = rtrim(name),
        rtrim(substring('SYSTEM TABLE            TABLE       VIEW       ',
        (ascii(type)-83)*12+1,12)) as TABLE_TYPE,
        REMARKS=     convert(varchar(254),null)
    from sysobjects 
    where name like @table_name ESCAPE '\'
        and user_name(uid) like @table_owner ESCAPE '\'
        and charindex(substring(type,1,1),@searchstr)! = 0
    order by TABLE_TYPE, TABLE_SCHEM, TABLE_NAME
go
exec sp_procxmode 'sp_jdbc_tables', 'anymode'
go
grant execute on sp_jdbc_tables to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_tables
*/


/*
**  spt_jdbc_table_types
*/


/** SECTION BEGIN: CLEANUP **/
use master
go

if (exists (select * from sysobjects
                where name = 'spt_jdbc_table_types'))
    drop table spt_jdbc_table_types
go
/** SECTION END: CLEANUP **/
 

create table spt_jdbc_table_types (TABLE_TYPE char(15))
go
    insert into spt_jdbc_table_types values('TABLE')
    insert into spt_jdbc_table_types values('SYSTEM TABLE')
    insert into spt_jdbc_table_types values('VIEW')
go
 
commit
go
 
grant select on spt_jdbc_table_types to public
go

/*
**  End of spt_jdbc_table_types
*/


/*
**  spt_mda
*/


/** SECTION BEGIN: CLEANUP **/
use master
go

if exists (select * from sysobjects where name = 'spt_mda')
begin
    drop table spt_mda
end
go
/** SECTION END: CLEANUP **/

/*
** querytype: 1 == RPC, 2 == LANGUAGE, 3 == NOT_SUPPORTED,
**            4 == LITERAL (boolean), 5 == LITERAL (integer),
**            6 == LITERAL (string), 7 == LITERAL (string, not tokenizable)
**
** note: querytypes 4 through 6 were added in version level 4 
**       of the metadata access.
** note: querytype 7 was added in version level 5 of the metadata access
**	 to fix 168844
** note: sp_mda version does NOT refer to the jConnect version!!
*/
create table spt_mda (mdinfo varchar(255), querytype tinyint, 
    query varchar(255) null, mdaver_start tinyint, mdaver_end tinyint, 
    srvver_start int, srvver_end int)
go

create unique nonclustered index spt_mda_ind 
    on spt_mda (mdinfo, mdaver_end, srvver_end)
go

grant select on spt_mda to public
go

insert spt_mda values ('CLASSFORNAME', 1, 'sp_jdbc_class_for_name(?)', 1, 7, 12000, -1)
insert spt_mda values ('JARFORCLASS', 1, 'sp_jdbc_jar_for_class(?)', 1, 7, 12000, -1)
insert spt_mda values ('JARBYNAME', 1, 'sp_jdbc_jar_by_name(?)', 1, 7, 12000, -1)
insert spt_mda values ('CLASSESINJAR', 1, 'sp_jdbc_classes_in_jar(?)', 1, 7, 12000, -1)
insert spt_mda values ('CANRETURNJARS', 4, '0', 4, 7, 0, 11950)
insert spt_mda values ('CANRETURNJARS', 2, 'select 0', 1, 3, 0, 11950)
insert spt_mda values ('CANRETURNJARS', 4, '1', 4, 7, 12000, -1)
insert spt_mda values ('CANRETURNJARS', 2, 'select 1', 1, 3, 12000, -1)

insert spt_mda values ('FUNCTIONCALL', 1, 'sp_jdbc_function_escapes', 1, 7, 0, -1)
insert spt_mda values ('TYPEINFO', 1, 'sp_jdbc_datatype_info', 1, 7, 0, -1)
insert spt_mda values ('TYPEINFO_CTS', 1, 'sp_jdbc_datatype_info_cts', 1, 7, 0, -1)
insert spt_mda values ('TABLES', 1, 'sp_jdbc_tables(?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('COLUMNS', 1, 'sp_jdbc_columns(?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('BULK_INSERT', 1, 'sp_drv_bcpmetadata(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('IMPORTEDKEYS', 1, 'sp_jdbc_importkey(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('EXPORTEDKEYS', 1, 'sp_jdbc_exportkey(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('PRIMARYKEYS', 1, 'sp_jdbc_primarykey(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('PRODUCTNAME', 2, 'select substring (@@version, 1, charindex(''/'',@@version)-1)', 1, 7, 0, -1) 
insert spt_mda values ('ISREADONLY', 2, 'select 0', 1, 3, 0, -1)
insert spt_mda values ('ISREADONLY', 4, '0', 4, 7, 0, -1)
insert spt_mda values ('ALLPROCSCALLABLE', 2, 'select 0', 1, 3, 0, -1)
insert spt_mda values ('ALLPROCSCALLABLE', 4, '0', 4, 7, 0, -1)
insert spt_mda values ('ALLTABLESSELECTABLE', 2, 'select 0', 1, 3, 0, -1)
insert spt_mda values ('ALLTABLESSELECTABLE', 4, '0', 4, 7, 0, -1)
insert spt_mda values ('COLUMNALIASING', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('COLUMNALIASING', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('IDENTIFIERQUOTE', 2, 'select ''"''', 1, 3, 0, -1)
insert spt_mda values ('IDENTIFIERQUOTE', 6, '"', 4, 7, 0, -1)
insert spt_mda values ('ALTERTABLESUPPORT', 2, 'select 1, 1', 1, 3, 0, -1)
insert spt_mda values ('ALTERTABLESUPPORT', 4, '1, 1', 4, 7, 0, -1)
insert spt_mda values ('CONNECTCONFIG', 2, 'set quoted_identifier on set textsize 2147483647', 1, 7, 0, -1)
insert spt_mda values ('CONVERTSUPPORT', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('CONVERTSUPPORT', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('CONVERTMAP', 1, 'sp_jdbc_convert_datatype(?,?)', 1, 7, 0, -1)
insert spt_mda values ('LIKEESCAPECLAUSE', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('LIKEESCAPECLAUSE', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('MULTIPLERESULTSETS', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('MULTIPLERESULTSETS', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('MULTIPLETRANSACTIONS', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('MULTIPLETRANSACTIONS', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('NONNULLABLECOLUMNS', 2, 'select 1', 1, 3, 0, -1) 
insert spt_mda values ('NONNULLABLECOLUMNS', 4, '1', 4, 7, 0, -1) 
insert spt_mda values ('POSITIONEDDELETE', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('POSITIONEDDELETE', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('POSITIONEDUPDATE', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('POSITIONEDUPDATE', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('STOREDPROCEDURES', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('STOREDPROCEDURES', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('PROCEDURES', 1, 'sp_jdbc_stored_procedures(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('SELECTFORUPDATE', 2, 'select 1', 1, 3, 0, -1) 
insert spt_mda values ('SELECTFORUPDATE', 4, '1', 4, 7, 0, -1) 
insert spt_mda values ('CURSORTRANSACTIONS', 2, 'select 1, 1', 1, 3, 0, -1)
insert spt_mda values ('CURSORTRANSACTIONS', 4, '1, 1', 4, 7, 0, -1)
insert spt_mda values ('STATEMENTTRANSACTIONS', 2, 'select 1, 1', 1, 3, 0, -1)
insert spt_mda values ('STATEMENTTRANSACTIONS', 4, '1, 1', 4, 7, 0, -1)
insert spt_mda values ('TRANSACTIONSUPPORT', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('TRANSACTIONSUPPORT', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('SAVEPOINTSUPPORT', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('SAVEPOINTSUPPORT', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('JDBCMAJORVERSION', 5, '3', 4, 7, 0, -1)
insert spt_mda values ('JDBCMINORVERSION', 5, '0', 4, 7, 0, -1)
/* 
 *Set this to 1 if 'exec <dbname>..<storedProcName>' is allowed
 */
insert spt_mda values ('PREPEND_DB_NAME', 2, 'select 1', 1, 3, 0, -1) 
insert spt_mda values ('PREPEND_DB_NAME', 5, '1', 4, 7, 0, -1) 

-- note - transaction levels here match Connection.TRANSACTION
insert spt_mda values ('TRANSACTIONLEVELS', 1, 'sp_jdbc_getisolationlevels',1 ,7, 0, -1) 
insert spt_mda values ('TRANSACTIONLEVELDEFAULT', 2, 'select 2', 1, 3, 0, -1)
insert spt_mda values ('TRANSACTIONLEVELDEFAULT', 5, '2', 4, 7, 0, -1)
insert spt_mda values ('SET_ISOLATION', 2, 'set transaction isolation level ', 1, 7, 0, -1)
insert spt_mda values ('GET_ISOLATION', 2, 'select @@isolation ', 1, 7, 0, -1)
insert spt_mda values ('SET_ROWCOUNT', 2, 'set rowcount ?', 1, 7, 0, -1)
insert spt_mda values ('GET_AUTOCOMMIT', 2, 'select @@tranchained ', 1, 7, 0, -1)
insert spt_mda values ('SET_AUTOCOMMIT_ON', 2, 'set CHAINED off', 1, 7, 0, -1)
insert spt_mda values ('SET_AUTOCOMMIT_OFF', 2, 'set CHAINED on', 1, 7, 0, -1)
insert spt_mda values ('BEGIN_TRAN', 2, 'if @@trancount < 1 begin tran', 1, 7, 0, -1)
insert spt_mda values ('SAVEPOINT', 2, 'save tran', 1, 7, 0, -1)
insert spt_mda values ('ROLL_TO_SAVEPOINT', 2, 'rollback tran', 1, 7, 0, -1)
insert spt_mda values ('USERNAME', 2, 'select user_name()', 1, 7, 0, -1)
insert spt_mda values ('SET_READONLY_TRUE', 3, '', 1, 7, 0, -1)
insert spt_mda values ('SET_READONLY_FALSE', 3, '', 1, 7, 0, -1)
insert spt_mda values ('SET_CATALOG', 2, 'use ?', 1, 7, 0, -1)
insert spt_mda values ('GET_CATALOG', 2, 'select db_name()', 1, 7, 0, -1)
insert spt_mda values ('NULLSORTING', 2, 'select 0, 1, 0, 0', 1, 3, 0, -1)
insert spt_mda values ('NULLSORTING', 4, '0, 1, 0, 0', 4, 7, 0, -1)
insert spt_mda values ('PRODUCTVERSION', 2, 'select @@version', 1, 7, 0, -1)
insert spt_mda values ('FILEUSAGE', 2, 'select 0, 0', 1, 3, 0, -1)
insert spt_mda values ('FILEUSAGE', 4, '0, 0', 4, 7, 0, -1)
if ('a'='A')  	/* Case insensitive */
    begin
        insert spt_mda values ('IDENTIFIERCASES', 2, 'select 0, 0, 0, 1, 1, 0, 0, 1', 1, 3, 0, -1)
        insert spt_mda values ('IDENTIFIERCASES', 4, '0, 0, 0, 1, 1, 0, 0, 1', 4, 7, 0, -1)
    end
else 		/* case sensitive */
    begin
        insert spt_mda values ('IDENTIFIERCASES', 2, 'select 1, 0, 0, 0, 1, 0, 0, 0', 1, 3, 0, -1)
        insert spt_mda values ('IDENTIFIERCASES', 4, '1, 0, 0, 0, 1, 0, 0, 0', 4, 7, 0, -1)
    end
insert spt_mda values ('SQLKEYWORDS', 2, 'select value from master.dbo.spt_jtext where mdinfo = ''SQLKEYWORDS''', 1, 7, 0, -1)
insert spt_mda values ('NUMERICFUNCTIONLIST', 2, 'select ''abs,acos,asin,atan,atan2,ceiling,cos,cot,degrees,exp,floor,log,log10,pi,power,radians,rand,round,sign,sin,sqrt,tan''', 1, 4, 0, -1)
insert spt_mda values ('NUMERICFUNCTIONLIST', 7, 'abs,acos,asin,atan,atan2,ceiling,cos,cot,degrees,exp,floor,log,log10,pi,power,radians,rand,round,sign,sin,sqrt,tan', 5, 7, 0, -1)
insert spt_mda values ('STRINGFUNCTIONLIST', 2, 'select ''ascii,char,concat,difference,insert,length,lcase,ltrim,repeat,right,rtrim,soundex,space,substring,ucase''', 1, 4, 0, -1)
insert spt_mda values ('STRINGFUNCTIONLIST', 7, 'ascii,char,concat,difference,insert,length,lcase,ltrim,repeat,right,rtrim,soundex,space,substring,ucase', 5, 7, 0, -1)
insert spt_mda values ('SYSTEMFUNCTIONLIST', 2, 'select ''database,ifnull,user,convert''', 1, 4, 0, -1)
insert spt_mda values ('SYSTEMFUNCTIONLIST', 7, 'database,ifnull,user,convert', 5, 7, 0, -1)
insert spt_mda values ('TIMEDATEFUNCTIONLIST', 2, 'select ''curdate,curtime,dayname,dayofmonth,dayofweek,dayofyear,hour,minute,month,monthname,now,quarter,second,timestampadd,timestampdiff,week,year''', 1,4, 0, -1)
insert spt_mda values ('TIMEDATEFUNCTIONLIST', 7, 'curdate,curtime,dayname,dayofmonth,dayofweek,dayofyear,hour,minute,month,monthname,now,quarter,second,timestampadd,timestampdiff,week,year', 5, 7, 0, -1)  
insert spt_mda values ('NULLPLUSNONNULL', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('NULLPLUSNONNULL', 4, '1', 4, 7, 0, -1)
insert spt_mda values ('EXTRANAMECHARS', 2, 'select ''@#$''', 1, 3, 0, -1)
insert spt_mda values ('EXTRANAMECHARS', 6, '@#$', 4, 7, 0, -1)
insert spt_mda values ('MAXBINARYLITERALLENGTH', 2, 'select 255', 1, 3, 0, -1)
insert spt_mda values ('MAXBINARYLITERALLENGTH', 5, '255', 4, 7, 0, -1)
insert spt_mda values ('MAXCHARLITERALLENGTH', 2, 'select 255', 1, 3, 0, -1)
insert spt_mda values ('MAXCHARLITERALLENGTH', 5, '255', 4, 7, 0, -1)
go
insert spt_mda values ('MAXLONGVARBINARYLENGTH', 2, 'select 2147483647', 1, 3, 0, 12000)
insert spt_mda values ('MAXLONGVARBINARYLENGTH', 5, '2147483647', 4, 7, 0, 12000)
insert spt_mda values ('MAXLONGVARBINARYLENGTH', 2, 'select 16384', 1, 3, 12500, -1)
insert spt_mda values ('MAXLONGVARBINARYLENGTH', 5, '16384', 4, 7, 12500, -1)
insert spt_mda values ('MAXLONGVARCHARLENGTH', 2, 'select 2147483647', 1, 3, 0, 12000)
insert spt_mda values ('MAXLONGVARCHARLENGTH', 5, '2147483647', 4, 7, 0, 12000)
insert spt_mda values ('MAXLONGVARCHARLENGTH', 2, 'select 16384', 1, 3, 12500, -1)
insert spt_mda values ('MAXLONGVARCHARLENGTH', 5, '16384', 4, 7, 12500, -1)
insert spt_mda values ('SCHEMAS', 1, 'sp_jdbc_getschemas', 1, 7, 0, -1)
insert spt_mda values ('SCHEMAS_CTS', 1, 'sp_jdbc_getschemas_cts', 1, 7, 0, -1)
insert spt_mda values ('COLUMNPRIVILEGES', 1, 'sp_jdbc_getcolumnprivileges(?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('TABLEPRIVILEGES', 1, 'sp_jdbc_gettableprivileges(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('ROWIDENTIFIERS', 1, 'sp_jdbc_getbestrowidentifier(?,?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('VERSIONCOLUMNS', 1, 'sp_jdbc_getversioncolumns(?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('KEYCROSSREFERENCE', 1, 'sp_jdbc_getcrossreferences(?,?,?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('INDEXINFO', 1, 'sp_jdbc_getindexinfo(?,?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('PROCEDURECOLUMNS', 1, 'sp_jdbc_getprocedurecolumns(?,?,?,?)', 1, 7, 0, -1)
insert spt_mda values ('CATALOGS', 1, 'sp_jdbc_getcatalogs', 1, 7, 0, -1)
insert spt_mda values ('CATALOGS_CTS', 1, 'sp_jdbc_getcatalogs_cts', 1, 7, 0, -1)
insert spt_mda values ('TABLETYPES', 2, 'select TABLE_TYPE from master.dbo.spt_jdbc_table_types', 1, 7, 0, -1)
insert spt_mda values ('SEARCHSTRING', 2, 'select ''\''', 1, 3, 0, -1)
insert spt_mda values ('SEARCHSTRING', 6, '\', 4, 7, 0, -1)
/*
supportsIntegrityEnhancementFacility: true
*/
insert spt_mda values ('INTEGRITYENHANCEMENT', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('INTEGRITYENHANCEMENT', 4, '1', 4, 7, 0, -1)

/* 
supportsOuterJoins: true
supportsFullOuterJoins: false
supportsLimitedOuterJoins: true
supports the syntax of the body of an oj escape without further
processing: false for Version < 12
*/
insert spt_mda values ('OUTERJOINS', 2, 'select 1, 0, 1, 0', 1, 3, 0, 11950)
insert spt_mda values ('OUTERJOINS', 4, '1, 0, 1, 0', 4, 7, 0, 11950)
insert spt_mda values ('OUTERJOINS', 2, 'select 1, 0, 1, 1', 1, 3, 11950, -1)
insert spt_mda values ('OUTERJOINS', 4, '1, 0, 1, 1', 4, 7, 11950, -1)
go

/* 
isCatalogAtStart: true
*/
insert spt_mda values ('CATALOGATSTART', 2, 'select 1', 1, 3, 0, -1)
insert spt_mda values ('CATALOGATSTART', 4, '1', 4, 7, 0, -1)

/* 
same with catalog
*/
insert spt_mda values ('CATALOGSUPPORT', 2, 'select 1, 1, 1, 1, 0', 1, 3, 0, -1)
insert spt_mda values ('CATALOGSUPPORT', 4, '1, 1, 1, 1, 0', 4, 7, 0, -1)

/* 
supportsSubqueriesInComparisons: true
supportsSubqueriesInExists: true
supportsSubqueriesInIns: true
supportsSubqueriesInQuantifieds: true
supportsCorrelatedSubqueries: true
*/
insert spt_mda values ('SUBQUERIES', 2, 'select 1, 1, 1, 1, 1', 1, 3, 0, -1)
insert spt_mda values ('SUBQUERIES', 4, '1, 1, 1, 1, 1', 4, 7, 0, -1)

/*
supportsTableCorrelationNames: true
supportsDifferentTableCorrelationNames: false
*/
insert spt_mda values ('CORRELATIONNAMES', 2, 'select 1, 0', 1, 3, 0, -1)
insert spt_mda values ('CORRELATIONNAMES', 4, '1, 0', 4, 7, 0, -1)

/*
supportsExpressionsInOrderBy: true
supportsOrderByUnrelated: true
*/
insert spt_mda values ('ORDERBYSUPPORT', 2, 'select 1, 1', 1, 3, 0, -1)
insert spt_mda values ('ORDERBYSUPPORT', 4, '1, 1', 4, 7, 0, -1)

/* 
supportsGroupBy: true
supportsGroupByUnrelated: true
supportsGroupByBeyondSelect: true
*/
insert spt_mda values ('GROUPBYSUPPORT', 2, 'select 1, 1, 1', 1, 3, 0, -1)
insert spt_mda values ('GROUPBYSUPPORT', 4, '1, 1, 1', 4, 7, 0, -1)

/* 
supportsMinimumSQLGrammar: true
supportsCoreSQLGrammar: false
supportsExtendedSQLGrammar: false
*/
insert spt_mda values ('SQLGRAMMAR', 2, 'select 1, 0, 0', 1, 3, 0, -1)
insert spt_mda values ('SQLGRAMMAR', 4, '1, 0, 0', 4, 7, 0, -1)

/* 
supportsANSI92EntryLevelSQL: true
supportsANSI92IntermediateSQL: false
supportsANSI92FullSQL: false
*/
insert spt_mda values ('ANSI92LEVEL', 2, 'select 1, 0, 0', 1, 3, 0, -1)
insert spt_mda values ('ANSI92LEVEL', 4, '1, 0, 0', 4, 7, 0, -1)
go

/* 
SQL Server's terms for 'schema', 'procedure' and 'catalog' 
and how to separate them
*/
insert spt_mda values ('SCHEMATERM', 2, 'select ''owner''', 1, 3, 0, -1)
insert spt_mda values ('SCHEMATERM', 6, 'owner', 4, 7, 0, -1)
insert spt_mda values ('PROCEDURETERM', 2, 'select ''stored procedure''', 1, 3, 0, -1)
insert spt_mda values ('PROCEDURETERM', 6, 'stored procedure', 4, 7, 0, -1)
insert spt_mda values ('CATALOGTERM', 2, 'select ''database''', 1, 3, 0, -1)
insert spt_mda values ('CATALOGTERM', 6, 'database', 4, 7, 0, -1)
insert spt_mda values ('CATALOGSEPARATOR', 2, 'select ''.''', 1, 3, 0, -1)
insert spt_mda values ('CATALOGSEPARATOR', 6, '.', 4, 7, 0, -1)

/* 
supportsSchemasInDataManipulation: true
supportsSchemasInProcedureCalls: true
supportsSchemasInTableDefinitions: true
supportsSchemasInIndexDefinitions: true
supportsSchemasInPrivilegeDefinitions: false
*/
insert spt_mda values ('SCHEMASUPPORT', 2, 'select 1, 1, 1, 1, 0', 1, 3, 0, -1)
insert spt_mda values ('SCHEMASUPPORT', 4, '1, 1, 1, 1, 0', 4, 7, 0, -1)

/* 
supportsUnion: true
supportsUnionAll: true
*/
insert spt_mda values ('UNIONSUPPORT', 2, 'select 1, 1', 1, 3, 0, -1)
insert spt_mda values ('UNIONSUPPORT', 4, '1, 1', 4, 7, 0, -1)

/* 
supportsDataDefinitionAndDataManipulationTransactions: true
supportsDataManipulationTransactionsOnly: false
dataDefinitionCausesTransactionCommit: false
dataDefinitionIgnoredInTransactions: false
*/
insert spt_mda values ('TRANSACTIONDATADEFINFO', 2, 'select 1, 0, 0, 0', 1, 3, 0, -1)
insert spt_mda values ('TRANSACTIONDATADEFINFO', 4, '1, 0, 0, 0', 4, 7, 0, -1)

/*
max column name length, max columns in group by,
max columns in index, max columns in order by,
max columns in select, max columns in table
XXX max columns in index is only 15 for B1
server.  Will that be a separate script?  Can we
detect whether this is B1 server?
XXX max columns in select is unlimited, so I'm
returning 0 -- the spec I'm looking at
doesn't actually say what to do in such a case
*/
insert spt_mda values ('COLUMNINFO', 2, 'select 30, 16, 16, 16, 0, 250', 1, 3, 0, -1)
insert spt_mda values ('COLUMNINFO', 5, '30, 16, 16, 16, 0, 250', 4, 7, 0, -1)
insert spt_mda values ('MAXCONNECTIONS', 2, 'select @@max_connections', 1, 7, 0, -1)
insert spt_mda values ('MAXINDEXLENGTH', 2, 'select 255', 1, 3, 0, -1)
insert spt_mda values ('MAXINDEXLENGTH', 5, '255', 4, 7, 0, -1)
/*
max cursor name length, max user name length,
max schema name length, max procedure name length,
max catalog name length
*/
insert spt_mda values ('MAXNAMELENGTHS', 2, 'select 30, 30, 30, 30, 30', 1, 3, 0, -1)
insert spt_mda values ('MAXNAMELENGTHS', 5, '30, 30, 30, 30, 30', 4, 7, 0, -1)
/*
** max bytes in a row is 1962, 0 is for 'no, that doesn't include blobs'
** ROWINFO cannot be converted into a LITERAL type since it contains 
** different types for each column:  int, boolean
*/
insert spt_mda values ('ROWINFO', 2, 'select 1962, 0', 1, 7, 0, -1)
/*
max length of a statement, max number of open statements
both are unlimited
*/
insert spt_mda values ('STATEMENTINFO', 2, 'select 0, 0', 1, 3, 0, -1)
insert spt_mda values ('STATEMENTINFO', 5, '0, 0', 4, 7, 0, -1)
/*
max table name length, max tables in a select
*/
insert spt_mda values ('TABLEINFO', 2, 'select 30, 256', 1, 3, 0, -1)
insert spt_mda values ('TABLEINFO', 5, '30, 256', 4, 7, 0, -1)
go
/*
RSMDA.getColumnTypeName
*/
insert spt_mda values ('COLUMNTYPENAME', 1, 'sp_sql_type_name(?,?)', 1, 7, 0, -1)
go
/*
Get the Data source specific DEFAULT CHARACTER SET
*/
insert spt_mda values ('DEFAULT_CHARSET', 1, 'sp_default_charset', 1, 7, 0, -1)
go
/*
ownUpdatesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('OWNUPDATESAREVISIBLE', 4, '1, 0, 0', 6, 7, 0, -1)
go
/*
ownDeletesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('OWNDELETESAREVISIBLE', 4, '1, 0, 0', 6, 7, 0, -1)
go
/*
ownInsertsAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('OWNINSERTSAREVISIBLE', 4, '0, 0, 0', 6, 7, 0, -1)
go
/*
othersUpdatesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('OTHERSUPDATESAREVISIBLE', 4, '1, 0, 0', 6, 7, 0, -1)
go
/*
othersDeletesAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('OTHERSDELETESAREVISIBLE', 4, '1, 0, 0', 6, 7, 0, -1)
go
/*
othersInsertsAreVisible (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('OTHERSINSERTSAREVISIBLE', 4, '1, 0, 0', 6, 7, 0, -1)
go
/*
updatesAreDetected (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('UPDATESAREDETECTED', 4, '0, 0, 0', 6, 7, 0, -1)
go
/*
deletesAreDetected (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('DELETESAREDETECTED', 4, '0, 0, 0', 6, 7, 0, -1)
go
/*
insertsAreDetected (JDBC 2.0)
TYPE_FORWARD_ONLY: false
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('INSERTSAREDETECTED', 4, '0, 0, 0', 6, 7, 0, -1)
go
/*
supportsBatchUpdates: true (JDBC 2.0)
*/
insert spt_mda values ('SUPPORTSBATCHUPDATES', 4, '1', 6, 7, 0, -1)
go
/*
execBatchUpdatesInLoop: false 
*/
insert spt_mda values ('EXECBATCHUPDATESINLOOP', 4, '0', 6, 7, 0, -1)
go

/*
 * ASE can always execute parameterized batches. Therefore, we do NOT have
 * to execute parameterized batches in a loop.
 */
insert spt_mda values ('EXECPARAMETERIZEDBATCHINLOOP', 4, '0', 6, 7, 0, -1)
go

/*
 * Batches with large numbers of parameters in parameterized batches must
 * be broken up into sub-batches or the server will complain (and the batch
 * won't run)
 */
insert spt_mda values ('MAXBATCHPARAMS', 5, '255', 6, 7, 0, 12000)
insert spt_mda values ('MAXBATCHPARAMS', 5, '2048', 6, 7, 12500, -1)
go


/*
supportsResultSetType (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: true
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('SUPPORTSRESULTSETTYPE', 4, '1, 1, 0', 6, 7, 0, -1)
go
/*
supportsResultSetConcurrency(CONCUR_READ_ONLY) (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: true
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('READONLYCONCURRENCY', 4, '1, 1, 0', 6, 7, 0, -1)
go
/*
supportsResultSetConcurrency(CONCUR_UPDATABLE) (JDBC 2.0)
TYPE_FORWARD_ONLY: true
TYPE_SCROLL_INSENSITIVE: false
TYPE_SCROLL_SENSITIVE: false
*/
insert spt_mda values ('UPDATABLECONCURRENCY', 4, '1, 0, 0', 6, 7, 0, -1)
go
/*
getUDTs (JDBC 2.0)
*/  
insert spt_mda values ('UDTS', 1, 'sp_jdbc_getudts(?,?,?,?)', 6, 7, 0, -1)
go
/*
isCaseSensitive
*/
insert spt_mda values ('ISCASESENSITIVE', 2, 'if exists (select 1 where ''A'' = ''a'') select 0 else select 1', 6, 7, 0, -1)
go

/*
 JTA support for JDBC 2.0 extensions

 XACOORDINATORTYPE returns the type of the distributed transaction
 coordinator.  It is up to jConnect to manufacture an XAResource object
 that can interact with that type of coordinator.

 When ASE 12.0 implements CR 203610 we will use
 that accessor. ASE pre 12.0 returns a dummy resultset.
*/
insert spt_mda values ('XACOORDINATORTYPE', 2, 'select TxnStyle=0, RequiredRole=NULL, Status=0, UniqueID=NULL', 6, 7, 0, 11950)
insert spt_mda values ('XACOORDINATORTYPE', 1, 'sp_jdbc_getxacoordinator', 6, 7, 12000, -1)

commit
go
dump tran sybsystemprocs with truncate_only 
go

/*
**  End of spt_mda
*/


/*
**  spt_jtext
*/

/** SECTION BEGIN: CLEANUP **/
use master
go

if exists (select * from sysobjects where name = 'spt_jtext')
begin
    drop table spt_jtext
end
go
/** SECTION END: CLEANUP **/

create table spt_jtext (mdinfo varchar(30) unique, value text)
go

grant select on spt_jtext to public
go

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_SQL_KEYWORDS */


/*
 * To populate the spt_jtext table in 12.5, we need to use a temporary stored
 * procedure. This is because the values we want are stored in a table, and
 * we'd like to parse them into a comma-separated list and then place them
 * in the spt_jtext table so they're all ready and waiting when the jdbc
 * client calls for them. They need to be in the format of a comma-separated
 * list, because that is what is called for in the jdbc spec.
 */

if exists (select * from sysobjects where name = 'sp_jdbc_temp_sqlkeyword_proc')
begin
    drop proc sp_jdbc_temp_sqlkeyword_proc
end

go

create proc sp_jdbc_temp_sqlkeyword_proc
as
    declare @keywords    varchar (1900)  /* we want this as big as possible to
                                            handle future additions to the
                                            keyword table.  */
    declare @word        varchar (255)

    declare @first       bit             /* a flag */

    select @first = 1

    declare keyword_cursor cursor for
        select upper(name) from master.dbo.spt_values
          where type = 'W' and ansi_w = 0 order by name

    open keyword_cursor

    fetch keyword_cursor into @word

    while (@@sqlstatus != 2)
    begin
        if (@first = 1)
        begin
            select @keywords = @word
            select @first = 0
        end
    
        else
        begin
            select @keywords = @keywords + ',' + @word
        end

        fetch keyword_cursor into @word
    end

    close keyword_cursor

    /* Now that we've built up our comma-separated list, stick this into
       the already-created spt_jtext table */

    insert master.dbo.spt_jtext values ('SQLKEYWORDS', @keywords)

go

/* Now, we want to execute the temporary stored proc to populate the spt_jtext
   table */

exec sp_jdbc_temp_sqlkeyword_proc
go

/* Now that it's served its purpose, remove the proc */
if exists (select * from sysobjects where name = 'sp_jdbc_temp_sqlkeyword_proc')
begin
    drop proc sp_jdbc_temp_sqlkeyword_proc
end

go




commit
go
dump tran sybsystemprocs with truncate_only
go


/*
**  End of spt_jtext
*/


/*
**  spt_jdbc_conversion
*/


/** SECTION BEGIN: CLEANUP **/
use master
go

/*
** create table with conversion information
*/
if exists (select * from sysobjects
	where name = 'spt_jdbc_conversion')
begin
    drop table spt_jdbc_conversion
end
go
/** SECTION END: CLEANUP **/

create table spt_jdbc_conversion (datatype int, conversion char(20))
go

grant select on spt_jdbc_conversion to public
go

/*Values based on the table info from the SQL Server Ref Man Chapter 4*/
/*bit*/
insert into spt_jdbc_conversion values(0,'11111110111111110001')
/*integers+numerics*/
insert into spt_jdbc_conversion values(1,'11111100011111110000')
insert into spt_jdbc_conversion values(2,'11111100011111110000')
insert into spt_jdbc_conversion values(9,'11111100011111110000')
insert into spt_jdbc_conversion values(10,'11111100011111110000')
insert into spt_jdbc_conversion values(11,'11111100011111110000')
insert into spt_jdbc_conversion values(12,'11111100011111110000')
insert into spt_jdbc_conversion values(13,'11111100011111110000')
insert into spt_jdbc_conversion values(14,'11111100011111110000')
insert into spt_jdbc_conversion values(15,'11111100011111110000')
/*Binaries*/
insert into spt_jdbc_conversion values(5,'11111110111111111111')
insert into spt_jdbc_conversion values(4,'11111110111111111111')
insert into spt_jdbc_conversion values(3,'11111110111111111111')
/*Characters*/
insert into spt_jdbc_conversion values(6,'00011110100000001111')
insert into spt_jdbc_conversion values(8,'00011110100000001111')
insert into spt_jdbc_conversion values(19,'00011110100000001111')
/*Dates*/
insert into spt_jdbc_conversion values(16,'00000010000000001110')
insert into spt_jdbc_conversion values(17,'00000010000000001110')
insert into spt_jdbc_conversion values(18,'00000010000000001110')
/*NULL*/
insert into spt_jdbc_conversion values(7,'00000000000000000000')
go
commit
go
dump tran sybsystemprocs with truncate_only 
go

/*
**  End of spt_jdbc_conversion
*/


/*
**  sp_mda
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs
go

/*
** create the well-known sp_mda procedure for accessing the data
*/
if exists (select * from sysobjects where name = 'sp_mda')
begin
    drop procedure sp_mda
end
go
/** SECTION END: CLEANUP **/


/*
** requesttype 0 == Returns the mdinfo:MDAVERSION and mdinfo:MDARELEASEID rows.
** requesttype 1 == JDBC
** requesttype 2 == JDBC - but only send back the minimal frequently used info.
** 
** mdaversion 
*/
create procedure sp_mda(@requesttype int, @requestversion int, @clientversion int = 0) as
begin

    declare @min_mdaversion int, @max_mdaversion int
    declare @mda_version int
    declare @srv_version int
    declare @mdaver_querytype tinyint
    declare @mdaver_query varchar(255)
    declare @orginal_isolation_level int
    
    select @min_mdaversion = 1
    select @max_mdaversion = 7
    select @mda_version = @requestversion
    
    
    if @@trancount = 0
    begin
    	set chained off
    end
    select @orginal_isolation_level=@@isolation 
    set transaction isolation level 1
 
    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    /* get the Server version */
    /* Server dependent select ADDPOINT_ASEVERSION*/
        select @srv_version=@@version_as_integer

    /*
    ** if the client is requesting a version too old
    ** then we return our lowest version supported
    **
    ** the client needs to be able to just handle this
    */
    if (@requestversion < @min_mdaversion)
        begin
            select @mda_version = @min_mdaversion
        end
        
    /*
    ** if the client is requesting a version too new
    ** we will return our highest version available
    */
    if (@mda_version > @max_mdaversion)
        begin
            select @mda_version = @max_mdaversion
        end
        
    /*
    ** if the client's requested version is between 1 and 3, 
    ** then the mda version returned needs to be 1.  The reason
    ** for this is the jConnect driver would pass in it's own 
    ** major version number as the @requestversion.  We need to
    ** keep older version's of the driver working ok since 
    ** they expect a '1' to be returned.
    */
    if (@mda_version < 4)
        begin
            select @mda_version = 1
            select @mdaver_querytype = 2
            select @mdaver_query = 'select 1'
        end
    else
        begin
            select @mdaver_querytype = 5
            select @mdaver_query = convert(varchar(255), @mda_version)
        end

    /*
    ** process the @requesttype
    */
    if (@requesttype = 0)
        begin
            select "mdinfo" = convert(varchar(30),'MDAVERSION'), 
                   "querytype" = @mdaver_querytype,
                   "query" = @mdaver_query
            union
            select mdinfo, querytype, query 
            from master..spt_mda
    	    where mdinfo in (
                'MDARELEASEID'
    	        )
        end
    else if (@requesttype = 1)
        begin
            select "mdinfo" = convert(varchar(30),'MDAVERSION'), 
                   "querytype" = @mdaver_querytype,
                   "query" = @mdaver_query
            union
            select mdinfo, querytype, query
            from master..spt_mda
            where @mda_version >= mdaver_start
              and @mda_version <= mdaver_end
              and ((@srv_version >= srvver_start) 
                      and (@srv_version <= srvver_end 
                      or srvver_end = -1))
        end
    else if (@requesttype = 2)
        begin
            select "mdinfo" = convert(varchar(30),'MDAVERSION'), 
                   "querytype" = @mdaver_querytype,
                   "query" = @mdaver_query
            union
            select mdinfo, querytype, query 
            from master..spt_mda
    	    where mdinfo in (
                'CONNECTCONFIG', 
       		'SET_CATALOG',
       		'SET_AUTOCOMMIT_ON',
       		'SET_AUTOCOMMIT_OFF',
       		'SET_ISOLATION',
       		'SET_ROWCOUNT',
                'DEFAULT_CHARSET'
    	        )
            and @mda_version >= mdaver_start
            and @mda_version <= mdaver_end
            and ((@srv_version >= srvver_start) 
                    and (@srv_version <= srvver_end 
                    or srvver_end = -1))
        end

    -- default isolation level for ASE is 1    
    if (@orginal_isolation_level = 0)
    begin
        set transaction isolation level 0
    end
    if (@orginal_isolation_level = 2)
    begin
        set transaction isolation level 2
    end
    if (@orginal_isolation_level = 3)
    begin
        set transaction isolation level 3
    end
end
go

exec sp_procxmode 'sp_mda', 'anymode'
go
grant execute on sp_mda to public
go
dump transaction sybsystemprocs with truncate_only
go

/*
**  End of sp_mda
*/


/*
**  jdbc_function_escapes
*/


/* 
** This script creates a table which is used by jdbcCONNECT to
** obtain information on this specific server types implementation
** of the various static functions for which JDBC provides escape
** sequences.
**
** Each row has two columns.  Escape_name is the name of the
** static function escape.  Map_string is a string showing how the
** function call should be sent to the server.  %i is a placeholder
** for the i'th argument to the escape.  This numbering is used
** to support skipping arguments.  Reordering of arguments is NOT
** supported.  Thus, a map string of 'foo(%2)' is ok (skips first
** argument); 'foo(%2, %1)' is not ok, at least until the driver
** changes to support this.
**
** Don't include rows for unsupported functions.
**
** Three escapes, convert, timestampadd, and timestampdiff, have
** one argument which takes special constant values.  These constants
** may also need to be mapped.  Therefore, include one row for each
** possible constant value, using the concatenation of the function name
** and the constant value as the escape_name column.  E.g.: 
** convertsql_binary, convertsql_bit, convertsql_char, etc.
** DO count the constant in figuring argument numbers.  Thus,
** timestampadd(sql_tsi_second, ts, ts) gets the map string
** 'dateadd(ss, %2, %3)')
**
** Use lower case for the escape name.  Use whatever case you
** need to for the map string.
**
*/

/** SECTION BEGIN: CLEANUP **/
use master
go

if exists (select * from sysobjects
    where name = 'jdbc_function_escapes')
    begin
        drop table jdbc_function_escapes
    end
go
/** SECTION END: CLEANUP **/

create table jdbc_function_escapes (escape_name varchar(40),
    map_string varchar(80))
go

grant select on jdbc_function_escapes to public
go

/* don't bother inserting rows for unsupported functions
** insert jdbc_function_escapes values ('mod', null)
** insert jdbc_function_escapes values ('truncate', null)
** insert jdbc_function_escapes values ('left', null)
** insert jdbc_function_escapes values ('replace', null)
** insert jdbc_function_escapes values (timestampdiffsql_tsi_frac_second, null)
** insert jdbc_function_escapes values (timestampaddsql_tsi_frac_second, null)
** insert jdbc_function_escapes values ('convertsql_bigint', null)
*/
insert jdbc_function_escapes values ('abs', 'abs(%1)')
go
insert jdbc_function_escapes values ('acos', 'acos(%1)')
go
insert jdbc_function_escapes values ('asin', 'asin(%1)')
go
insert jdbc_function_escapes values ('atan', 'atan(%1)')
go
insert jdbc_function_escapes values ('atan2', 'atn2(%1, %2)')
go
insert jdbc_function_escapes values ('ceiling', 'ceiling(%1)')
go
insert jdbc_function_escapes values ('cos', 'cos(%1)')
go
insert jdbc_function_escapes values ('cot', 'cot(%1)')
go
insert jdbc_function_escapes values ('degrees', 'degrees(%1)')
go
insert jdbc_function_escapes values ('exp', 'exp(%1)')
go
insert jdbc_function_escapes values ('floor', 'floor(%1)')
go
insert jdbc_function_escapes values ('locate', 'charindex ((convert (varchar, %1)), (convert (varchar, %2)))')
go
insert jdbc_function_escapes values ('log', 'log(%1)')
go
insert jdbc_function_escapes values ('log10', 'log10(%1)')
go
insert jdbc_function_escapes values ('pi', 'pi()')
go
insert jdbc_function_escapes values ('power', 'power(%1, %2)')
go
insert jdbc_function_escapes values ('radians', 'radians(%1)')
go
insert jdbc_function_escapes values ('rand', 'rand(%1)')
go
insert jdbc_function_escapes values ('round', 'round(%1, %2)')
go
insert jdbc_function_escapes values ('sign', 'sign(%1)')
go
insert jdbc_function_escapes values ('sin', 'sin(%1)')
go
insert jdbc_function_escapes values ('sqrt', 'sqrt(%1)')
go
insert jdbc_function_escapes values ('tan', 'tan(%1)')
go
insert jdbc_function_escapes values ('ascii', 'ascii(%1)')
go
insert jdbc_function_escapes values ('char', 'char(%1)')
go
insert jdbc_function_escapes values ('concat', '%1 + %2')
go
insert jdbc_function_escapes values ('difference', 'difference(%1, %2)')
go
insert jdbc_function_escapes values ('insert', 'stuff(%1, %2, %3, %4)')
go
insert jdbc_function_escapes values ('length', 'char_length(%1)')
go
insert jdbc_function_escapes values ('lcase', 'lower(%1)')
go
insert jdbc_function_escapes values ('ltrim', 'ltrim(%1)')
go
insert jdbc_function_escapes values ('repeat', 'replicate(%1, %2)')
go
insert jdbc_function_escapes values ('right', 'right(%1, %2)')
go
insert jdbc_function_escapes values ('rtrim', 'rtrim(%1)')
go
insert jdbc_function_escapes values ('soundex', 'soundex(%1)')
go
insert jdbc_function_escapes values ('space', 'space(%1)')
go
insert jdbc_function_escapes values ('substring', 'substring(%1, %2, %3)')
go
insert jdbc_function_escapes values ('ucase', 'upper(%1)')
go
insert jdbc_function_escapes values ('curdate', 'getdate()')
go
insert jdbc_function_escapes values ('curtime', 'getdate()')
go
insert jdbc_function_escapes values ('dayname', 'datename(dw, %1)')
go
insert jdbc_function_escapes values ('dayofmonth', 
    'datepart(dd, %1)')
go
insert jdbc_function_escapes values ('dayofweek', 
    'datepart(dw, %1)')
go
insert jdbc_function_escapes values ('dayofyear', 
    'datepart(dy, %1)')
go
insert jdbc_function_escapes values ('hour', 'datepart(hh, %1)')
go
insert jdbc_function_escapes values ('minute', 'datepart(mi, %1)')
go
insert jdbc_function_escapes values ('month', 'datepart(mm, %1)')
go
insert jdbc_function_escapes values ('monthname',    
    'datename(mm, %1)')
go
insert jdbc_function_escapes values ('now', 'getdate()')
go
insert jdbc_function_escapes values ('quarter', 'datepart(qq, %1)')
go
insert jdbc_function_escapes values ('second', 'datepart(ss, %1)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_second',
	'dateadd(ss, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_minute',
	'dateadd(mi, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_hour',
	'dateadd(hh, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_day',
	'dateadd(dd, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_week',
	'dateadd(wk, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_month',
	'dateadd(mm, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_quarter',
	'dateadd(qq, %2, %3)')
go
insert jdbc_function_escapes values ('timestampaddsql_tsi_year',
	'dateadd(yy, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_second',
	'datediff(ss, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_minute',
	'datediff(mi, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_hour',
	'datediff(hh, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_day',
	'datediff(dd, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_week',
	'datediff(wk, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_month',
	'datediff(mm, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_quarter',
	'datediff(qq, %2, %3)')
go
insert jdbc_function_escapes values ('timestampdiffsql_tsi_year',
	'datediff(yy, %2, %3)')
go
insert jdbc_function_escapes values ('week', 'datepart(wk, %1)')
go
insert jdbc_function_escapes values ('year', 'datepart(yy, %1)')
go
insert jdbc_function_escapes values ('database', 'db_name()')
go
insert jdbc_function_escapes values ('ifnull', 'isnull(%1, %2)')
go
insert jdbc_function_escapes values ('user', 'user_name()')
go
insert jdbc_function_escapes values ('convertsql_binary',
	'convert(varbinary(255), %1)')
go
insert jdbc_function_escapes values ('convertsql_bit', 
    'convert(bit, %1)')
go
insert jdbc_function_escapes values ('convertsql_char',
	'convert(varchar(255), %1)')
go
insert jdbc_function_escapes values ('convertsql_date',
	'convert(datetime, %1)')
go
insert jdbc_function_escapes values ('convertsql_decimal',
	'convert(decimal(36, 18), %1)')
go
insert jdbc_function_escapes values ('convertsql_double',
	'convert(float, %1)')
go
insert jdbc_function_escapes values ('convertsql_float',
	'convert(float, %1)')
go
insert jdbc_function_escapes values ('convertsql_integer',
	'convert(int, %1)')
go
insert jdbc_function_escapes values ('convertsql_longvarbinary',
	'convert(varbinary(255), %1)')
go
insert jdbc_function_escapes values ('convertsql_longvarchar',
	'convert(varchar(255), %1)')
go
insert jdbc_function_escapes values ('convertsql_real',
	'convert(real, %1)')
go
insert jdbc_function_escapes values ('convertsql_smallint',
	'convert(smallint, %1)')
go
insert jdbc_function_escapes values ('convertsql_time',
	'convert(datetime, %1)')
go
insert jdbc_function_escapes values ('convertsql_timestamp',
	'convert(datetime, %1)')
go
insert jdbc_function_escapes values ('convertsql_tinyint',
	'convert(tinyint, %1)')
go
insert jdbc_function_escapes values ('convertsql_varbinary',
	'convert(varbinary(255), %1)')
go
insert jdbc_function_escapes values ('convertsql_varchar',
	'convert(varchar(255), %1)')
go

/*
**  End of jdbc_function_escapes
*/



/*
**  sp_jdbc_convert_datatype
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_convert_datatype')
    begin
        drop procedure sp_jdbc_convert_datatype
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_convert_datatype (
					@source int,
					@destination int)
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

	/* Make source non-negative */
	select @source = @source + 7
	/* Put the strange date numbers into this area between 0-19*/
	if (@source > 90)
		select @source = @source - 82

	/*Convert destination the same way*/
	/* Put the strange date numbers into this area between 0-19*/
	if (@destination > 90)
		select @destination = @destination - 82

	/* Need 8 added instead of 7 because substring starts at 1 instead */
	/* of 0 */
	select @destination = @destination + 8

	/* Check the conversion. If the bit string in the table has a 1 
	** on the place's number of the destination's value we have to 
	** return true, else false
	*/
	if ((select substring(conversion,@destination,1)
        from master.dbo.spt_jdbc_conversion
        where datatype = @source) = '1')

		select 1
	else 
		select 0
go

exec sp_procxmode 'sp_jdbc_convert_datatype', 'anymode'
go

grant execute on sp_jdbc_convert_datatype to public
go

commit
go

/*
**  End of sp_jdbc_convert_datatype
*/


/*
**  sp_jdbc_function_escapes
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_function_escapes')
    begin
        drop procedure sp_jdbc_function_escapes
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_function_escapes
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    select * 
    from master.dbo.jdbc_function_escapes

go

exec sp_procxmode 'sp_jdbc_function_escapes', 'anymode'
go

grant execute on sp_jdbc_function_escapes to public
go

/*
**  End of sp_jdbc_function_escapes
*/



/*
**  sp_jdbc_fkeys
*/

/* The following code is taken from the ODBC handling of 
 * primary keys, and foreign keys, and modified slightly 
 * for JDBC compliance.
 * ODBC sp_fkeys --> sp_jdbc_fkeys
 *      sp_pkeys --> sp_jdbc_pkeys
 *      #pid     --> #jpid
 *      #fid     --> #fid
 */


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select *
        from sysobjects
                where sysstat & 7 = 4
                        and name = 'sp_jdbc_fkeys')
begin
        drop procedure sp_jdbc_fkeys
end
go
/** SECTION END: CLEANUP **/

/*
** parameters: @pktable_name - table name for primary key
**             @pktable_owner - (schema) a schema name pattern; "" retrieves 
**		those without a schema
**             @pktable_qualifier - (catalog name) a catalog name; "" retrieves
**              those without a catalog; null means drop catalog name from the
**                  selection criteria 
**             @fktable_name - table name for foreign key
**             @fktable_owner - (schema) a schema name pattern; "" retrieves 
**		those  without a schema
**             @fktable_qualifier - (catalog name) a catalog name; "" retrieves
**              those without a catalog; null means drop catalog name from the
**              selection criteria 
**
** note: there is one raiserror message: 18040
**
** messages for 'sp_jdbc_fkeys'               18039, 18040
**
** 17461, 'Object does not exist in this database.'
** 18040, 'Catalog procedure %1! can not be run in a transaction.', sp_jdbc_fkeys
** 18043 ' Primary key table name or foreign key table name or both must be
** given'
** 18044, '%1! table qualifier must be name of current database.' [Primary
** key | Foreign key]
**
*/

CREATE PROCEDURE sp_jdbc_fkeys
    @pktable_name       varchar(300) = null,
    @pktable_owner      varchar(32 ) = null,
    @pktable_qualifier  varchar(32 ) = null,
    @fktable_name       varchar(300) = null,
    @fktable_owner      varchar(32 ) = null,
    @fktable_qualifier  varchar(32 ) = null
AS
/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_FKEYS */
    declare @ftabid int, @ptabid int, @constrid int, @keycnt int, @primkey int
    declare @fokey1 int, @fokey2 int,  @fokey3 int,  @fokey4 int, @fokey5  int
    declare @fokey6 int, @fokey7 int,  @fokey8 int,  @fokey9 int, @fokey10 int
    declare @fokey11 int,@fokey12 int, @fokey13 int, @fokey14 int,@fokey15 int
    declare @refkey1 int,@refkey2 int, @refkey3 int, @refkey4 int,@refkey5  int
    declare @refkey6 int,@refkey7 int, @refkey8 int, @refkey9 int,@refkey10 int
    declare @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
    declare @refkey15 int, @refkey16 int, @fokey16 int, @status int, @i int
    declare @msg varchar(255)
    declare @msg2 varchar(50)
    declare @export int, @import int
    declare @notDeferrable int 
    declare @startedInTransaction bit 

    if (@@trancount = 0)
    begin
        set chained off
    end

    /* check if we're in a transaction before we execute any selects */
    if (@@trancount > 0)
        select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0


    select @notDeferrable = 7       
    select @import = 0
    select @export = 0
    
    /* if table_owner is null, include all in search */
    if (@fktable_owner is null) select @fktable_owner = '%'
    if (@pktable_owner is null) select @pktable_owner = '%'

    set nocount on

    set transaction isolation level 1

    if (@startedInTransaction = 1)
        save transaction jdbc_keep_temptables_from_tx 

    if (@pktable_name is null) and (@fktable_name is null)
    begin
        /* If neither primary key nor foreign key table names given */
        /*
        ** 18043 'Primary key table name or foreign key table name
        ** or both must be given'
        */
        exec  sp_getmessage 18043, @msg output
        raiserror 18043 @msg
        return (1)
    end
        else
        begin
                if (substring(@pktable_name,1,1)= '#') or
                   (substring(@fktable_name,1,1)='#')  
                begin
                        /* We won't allow temptables here
                        ** 
                        ** Error 177: cannot create a temporary object (with
                        ** '#' as the first character name.
                        */
                        exec sp_getmessage 17676, @msg out
                        raiserror 17676 @msg
                        return(1)
                end
        end
    if @fktable_qualifier is not null
    begin
        if db_name() != @fktable_qualifier
        begin
            exec sp_getmessage 18039, @msg out
            raiserror 18039 @msg
            return (1)
        end
    end
    else
    begin
        /*
        ** Now make sure that foreign table qualifier is pointing to the
        ** current database in case it is not specified.
        */
        select @fktable_qualifier = db_name()
    end

    if @pktable_qualifier is not null
    begin
        if db_name() != @pktable_qualifier
        begin
            exec sp_getmessage 18039, @msg output
            raiserror 18039 @msg
            return (1)
        end
    end
    else
    begin
        /*
        ** Now make sure that primary table qualifier is pointing to the
        ** current database in case it is not specified.
        */
        select @pktable_qualifier = db_name()
    end

    create table #jpid (pid int, uid int, name varchar(32))
    create table #jfid (fid int, uid int, name varchar(32))

    if @pktable_name is not null
    begin
                select @export = 1
                if ((select count(*) from sysobjects 
            where name = @pktable_name
            and user_name(uid) like @pktable_owner ESCAPE '\'
            and type in ('S', 'U')) = 0)
        begin
            exec sp_getmessage 17674, @msg output
            raiserror 17674 @msg
            return (1)
        end
        
        insert into #jpid
        select id, uid, name
        from sysobjects
        where name = @pktable_name
        and user_name(uid) like @pktable_owner ESCAPE '\'
        and type in ('S', 'U')
    end
    else
    begin
        insert into #jpid
        select id, uid, name
        from sysobjects 
        where type in ('S', 'U')
        and user_name(uid) like @pktable_owner ESCAPE '\'
    end

    if @fktable_name is not null
    begin
        select @import = 1
        if ((select count(*)
            from sysobjects
            where name = @fktable_name
            and type in ('S', 'U')
            and user_name(uid) like @fktable_owner ESCAPE '\') = 0)
        begin
            exec sp_getmessage 17674, @msg output
            raiserror 17674 @msg
            return (1)
        end
        insert into #jfid
        select id, uid, name
            from sysobjects
            where name = @fktable_name
            and type in ('S', 'U')
            and user_name(uid) like @fktable_owner ESCAPE '\'
    end
    else
    begin
        insert into #jfid
        select id, uid, name
            from sysobjects where
            type in ('S', 'U')
            and user_name(uid) like @fktable_owner ESCAPE '\'
    end

    create table #jfkey_res( 
        PKTABLE_CAT        varchar(32) null,
        PKTABLE_SCHEM      varchar(32) null,
        PKTABLE_NAME       varchar(257) null,
        PKCOLUMN_NAME      varchar(257) null,
        FKTABLE_CAT        varchar(32) null,
        FKTABLE_SCHEM      varchar(32) null,
        FKTABLE_NAME       varchar(257) null,
        FKCOLUMN_NAME      varchar(257) null,
        KEY_SEQ            smallint,
        UPDATE_RULE        smallint,
        DELETE_RULE        smallint,
        FK_NAME            varchar(257),
        PK_NAME            varchar(257) null)
    create table #jpkeys(seq int, keys varchar(32) null)
    create table #jfkeys(seq int, keys varchar(32) null)

    /*
    ** Since there are possibly multiple rows in sysreferences
    ** that describe foreign and primary key relationships among
    ** two tables, so we declare a cursor on the selection from
    ** sysreferences and process the output at row by row basis.
    */

    declare jcurs_sysreferences cursor
        for
        select tableid, reftabid, constrid, keycnt,
            fokey1, fokey2, fokey3, fokey4, fokey5, fokey6, fokey7, fokey8,
            fokey9, fokey10, fokey11, fokey12, fokey13, fokey14, fokey15,
            fokey16, refkey1, refkey2, refkey3, refkey4, refkey5,
            refkey6, refkey7, refkey8, refkey9, refkey10, refkey11,
            refkey12, refkey13, refkey14, refkey15, refkey16
            from sysreferences
            where tableid in (
                    select fid from #jfid)
            and reftabid in (
                    select pid from #jpid)
            and frgndbname is NULL and pmrydbname is NULL
            for read only

    open  jcurs_sysreferences

    fetch  jcurs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt,
        @fokey1, @fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8,
        @fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15,
        @fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6,
        @refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12,
        @refkey13, @refkey14, @refkey15, @refkey16

    while (@@sqlstatus = 0)
    begin
        /*
        ** For each row of sysreferences which describes a foreign-
        ** primary key relationship, do the following.
        */
        
        /*
        ** First store the column names that belong to primary keys
        ** in table #pkeys for later retrieval.
        */
        
        delete #jpkeys
        insert #jpkeys values(1, col_name(@ptabid,@refkey1))
        insert #jpkeys values(2, col_name(@ptabid,@refkey2))
        insert #jpkeys values(3, col_name(@ptabid,@refkey3))
        insert #jpkeys values(4, col_name(@ptabid,@refkey4))
        insert #jpkeys values(5, col_name(@ptabid,@refkey5))
        insert #jpkeys values(6, col_name(@ptabid,@refkey6))
        insert #jpkeys values(7, col_name(@ptabid,@refkey7))
        insert #jpkeys values(8, col_name(@ptabid,@refkey8))
        insert #jpkeys values(9, col_name(@ptabid,@refkey9))
        insert #jpkeys values(10, col_name(@ptabid,@refkey10))
        insert #jpkeys values(11, col_name(@ptabid,@refkey11))
        insert #jpkeys values(12, col_name(@ptabid,@refkey12))
        insert #jpkeys values(13, col_name(@ptabid,@refkey13))
        insert #jpkeys values(14, col_name(@ptabid,@refkey14))
        insert #jpkeys values(15, col_name(@ptabid,@refkey15))
        insert #jpkeys values(16, col_name(@ptabid,@refkey16))
        
        /*
        ** Second store the column names that belong to foreign keys
        ** in table #jfkeys for later retrieval.
        */
        
        delete #jfkeys
        insert #jfkeys values(1, col_name(@ftabid,@fokey1))
        insert #jfkeys values(2, col_name(@ftabid,@fokey2))
        insert #jfkeys values(3, col_name(@ftabid,@fokey3))
        insert #jfkeys values(4, col_name(@ftabid,@fokey4))
        insert #jfkeys values(5, col_name(@ftabid,@fokey5))
        insert #jfkeys values(6, col_name(@ftabid,@fokey6))
        insert #jfkeys values(7, col_name(@ftabid,@fokey7))
        insert #jfkeys values(8, col_name(@ftabid,@fokey8))
        insert #jfkeys values(9, col_name(@ftabid,@fokey9))
        insert #jfkeys values(10, col_name(@ftabid,@fokey10))
        insert #jfkeys values(11, col_name(@ftabid,@fokey11))
        insert #jfkeys values(12, col_name(@ftabid,@fokey12))
        insert #jfkeys values(13, col_name(@ftabid,@fokey13))
        insert #jfkeys values(14, col_name(@ftabid,@fokey14))
        insert #jfkeys values(15, col_name(@ftabid,@fokey15))
        insert #jfkeys values(16, col_name(@ftabid,@fokey16))
        
        /*
        ** For each column of the current foreign-primary key relation,
        ** create a row into result table: #jfkey_res.
        */
        
        select @i = 1
        while (@i <= @keycnt)
        begin
            insert into #jfkey_res
                select @pktable_qualifier,
                (select user_name(uid) from #jpid where 
                    pid = @ptabid),
                object_name(@ptabid), 
                (select keys from #jpkeys where seq = @i),
                    @fktable_qualifier,
                (select user_name(uid) from #jfid where 
                    fid = @ftabid),
                object_name(@ftabid),
                (select keys from #jfkeys where seq = @i), 
                @i, 1, 1,
                /*Foreign key name*/ 
                object_name(@constrid),
                /* Primary key name */
                (select name from sysindexes where id = @ftabid
                    and status > 2048 and status < 32768)
            select @i = @i + 1
        end
        
        /*
        ** Go to the next foreign-primary key relationship if any.
        */
        
        fetch  jcurs_sysreferences into @ftabid, @ptabid, @constrid, 
            @keycnt,@fokey1, @fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, 
            @fokey7, @fokey8, @fokey9, @fokey10, @fokey11, @fokey12, 
            @fokey13, @fokey14, @fokey15, @fokey16, @refkey1, @refkey2, 
            @refkey3, @refkey4, @refkey5, @refkey6, @refkey7, @refkey8, 
            @refkey9, @refkey10, @refkey11, @refkey12, @refkey13, @refkey14,
            @refkey15, @refkey16
    end

    close jcurs_sysreferences
    deallocate cursor jcurs_sysreferences

    /*
    ** Everything is now in the result table #jfkey_res, so go ahead
    ** and select from the table now.
    */
    if (@export = 1) and (@import = 0)
    begin
       select  PKTABLE_CAT,
               PKTABLE_SCHEM,
               PKTABLE_NAME,
               PKCOLUMN_NAME,
               FKTABLE_CAT, 
               FKTABLE_SCHEM, 
               FKTABLE_NAME, 
               FKCOLUMN_NAME,
               KEY_SEQ, 
               UPDATE_RULE, 
               DELETE_RULE,
               FK_NAME,
               PK_NAME, 
               @notDeferrable  as DEFERRABILITY
      from #jfkey_res 
      where PKTABLE_SCHEM like @pktable_owner ESCAPE '\'
      order by FKTABLE_CAT,FKTABLE_SCHEM,FKTABLE_NAME,KEY_SEQ
    end

    if (@export = 0) and (@import = 1)
    begin
        select  PKTABLE_CAT,
                PKTABLE_SCHEM,
                PKTABLE_NAME,
                PKCOLUMN_NAME,
                FKTABLE_CAT, 
                FKTABLE_SCHEM, 
                FKTABLE_NAME, 
                FKCOLUMN_NAME,
                KEY_SEQ, 
                UPDATE_RULE, 
                DELETE_RULE,
                FK_NAME,
                PK_NAME, 
                @notDeferrable  as DEFERRABILITY
        from #jfkey_res 
        where FKTABLE_SCHEM like @fktable_owner ESCAPE '\'
          order by PKTABLE_CAT,PKTABLE_SCHEM,PKTABLE_NAME,KEY_SEQ
    end

    if (@export = 1) and (@import = 1)
    begin
        select  PKTABLE_CAT,
                PKTABLE_SCHEM,
                PKTABLE_NAME,
                PKCOLUMN_NAME,
                FKTABLE_CAT, 
                FKTABLE_SCHEM, 
                FKTABLE_NAME, 
                FKCOLUMN_NAME,
                KEY_SEQ, 
                UPDATE_RULE, 
                DELETE_RULE,
                FK_NAME,
                PK_NAME, 
                @notDeferrable  as DEFERRABILITY
        from #jfkey_res 
        where PKTABLE_SCHEM like @pktable_owner ESCAPE '\'
        and FKTABLE_SCHEM like @fktable_owner ESCAPE '\'
          order by FKTABLE_CAT,FKTABLE_SCHEM,FKTABLE_NAME,KEY_SEQ
    end

    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx 

       
go

exec sp_procxmode 'sp_jdbc_fkeys', 'anymode'
go

/*
**  End of sp_jdbc_fkeys
*/


/* 
**  sp_jdbc_exportkey
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_exportkey')
    begin
        drop procedure sp_jdbc_exportkey
    end
go
/** SECTION END: CLEANUP **/


CREATE PROCEDURE sp_jdbc_exportkey (
				 @table_qualifier	varchar(32 ) = null,
				 @table_owner		varchar(32 ) = null,
				 @table_name		varchar(255))
as
    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    exec sp_jdbc_fkeys 
        @table_name, @table_owner, @table_qualifier, NULL, NULL, NULL
go
exec sp_procxmode 'sp_jdbc_exportkey', 'anymode'
go

grant execute on sp_jdbc_exportkey to public
go

/* 
**  End of sp_jdbc_exportkey
*/


/* 
** sp_jdbc_importkey
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_importkey')
    begin
        drop procedure sp_jdbc_importkey
    end
go
/** SECTION END: CLEANUP **/

CREATE PROCEDURE sp_jdbc_importkey (
				 @table_qualifier	varchar(32 ) = null,
				 @table_owner		varchar(32 ) = null,
				 @table_name		varchar(255))
as

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    exec sp_jdbc_fkeys
        NULL, NULL, NULL, @table_name, @table_owner, @table_qualifier
go

exec sp_procxmode 'sp_jdbc_importkey', 'anymode'
go

grant execute on sp_jdbc_importkey to public
go

/* 
** End of sp_jdbc_importkey
*/



/*
**  sp_jdbc_getcrossreferences
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects
		where name = 'sp_jdbc_getcrossreferences')
begin
	drop procedure sp_jdbc_getcrossreferences
end
go
/** SECTION END: CLEANUP **/


CREATE PROCEDURE sp_jdbc_getcrossreferences
			   @pktable_qualifier	varchar(32 ) = null,
			   @pktable_owner	varchar(32 ) = null,
			   @pktable_name	varchar(255),
			   @fktable_qualifier	varchar(32 ) = null ,
			   @fktable_owner	varchar(32 ) = null,
			   @fktable_name	varchar(255)
as
    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0


    exec sp_jdbc_fkeys 
        @pktable_name, @pktable_owner, @pktable_qualifier,
        @fktable_name, @fktable_owner, @fktable_qualifier
go

exec sp_procxmode 'sp_jdbc_getcrossreferences', 'anymode'
go
grant execute on sp_jdbc_getcrossreferences to public
go
commit
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_getcrossreferences
*/


/* 
**  sp_jdbc_getschemas
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go
/*Stored procedure to support BCP implementation ADDPOINT_BULK_INSERT*/

/** SECTION BEGIN: CLEANUP **/
if exists (select * from sysobjects where name = 'sp_drv_bcpmetadata')
    begin
	drop procedure sp_drv_bcpmetadata
    end
go
/** SECTION END: CLEANUP **/


CREATE PROCEDURE sp_drv_bcpmetadata (
@table_name  varchar(771),
@table_owner        varchar(32 ) = null,
@table_qualifier    varchar(32 ) = null
)
AS


    declare @msg              varchar(250)
    declare @full_table_name  varchar(1542)
    declare @table_id         int
    declare @sysstat2	      int
    declare @table_lock_scheme    bit
    declare @checktemptable    int
	
    
    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0


    if @table_qualifier is not null
    begin
        if db_name() != @table_qualifier
        begin	
            /* 
            ** If qualifier doesn't match current database: 18039
            ** Table qualifier must be name of current database
            */
            exec sp_getmessage 18039, @msg output
            raiserror 18039 @msg
            return (1)
        end
    end

    SELECT @checktemptable = charindex('#',@table_name)
    /*
     **  if its a #temp table, assign @table_qualifier to the
     **  the temp db assigned to the user
    */

    if @checktemptable = 1
    begin
        select @table_qualifier = db_name(@@tempdbid)
    end
    
    if @table_owner is null
    begin       /* If unqualified table name */
        SELECT @full_table_name = @table_name
        select @table_owner = '%'
    end
    else
    begin       /* Qualified table name */
        SELECT @full_table_name = @table_owner + '.' + @table_name
    end

    select @table_id=object_id(@full_table_name) 
    if @checktemptable = 1
    begin
        declare @cmd varchar(1000)
        select @cmd = 'SELECT @sysstat2 = (sysstat2 & 57344) from '+@table_qualifier+'..sysobjects where id = @table_id'
        execute(@cmd)
    end
    else
    begin
        SELECT @sysstat2 = (sysstat2 & 57344) from sysobjects where id = @table_id
    end

    if ( @sysstat2 = 8192 or @sysstat2 = 0)
    begin
    /* Lock scheme is Allpages */
	select @table_lock_scheme = 0
    end
    if ( @sysstat2 = 16384 or @sysstat2 = 32768)
    begin
    /* Lock scheme is Data only */
       select @table_lock_scheme = 1
    end

    if (@table_id != 0)
    begin 
        if @checktemptable = 1
        begin
        select @cmd = 'select count(*),@table_qualifier from '+@table_qualifier+'..syscolumns where id=@table_id '
        select @cmd = @cmd + ' SELECT 
            COLID=colid,
            COLUMN_NAME=name, 
            DATA_TYPE=type,
            USERTYPE=usertype,
            COLUMN_SIZE=length,
            PRECISION=isnull(prec,0),
            SCALE=isnull(scale,0),
            NULLABLE=convert(bit, (status & 8)),
            COLUMN_DEF=(select text from syscomments where id=c.cdefault),
            IDENTITY_COL=convert(bit, (status & 0x80)),
            TABLE_LOCK_SCHEME=@table_lock_scheme,
            PAGESIZE=@@maxpagesize 
        FROM '+@table_qualifier+'..syscolumns c 
        where id=@table_id
        ORDER BY colid'
        execute(@cmd)
        end
        else
        begin
        select count(*),@table_qualifier from syscolumns where id=@table_id
        SELECT 
            COLID=colid,
            COLUMN_NAME=name, 
            DATA_TYPE=type,
            USERTYPE=usertype,
            COLUMN_SIZE=length,
            'PRECISION'=isnull(prec,0),
            SCALE=isnull(scale,0),
            NULLABLE=convert(bit, (status & 8)),
            COLUMN_DEF=(select text from syscomments where id=c.cdefault),
            IDENTITY_COL=convert(bit, (status & 0x80)),
            TABLE_LOCK_SCHEME=@table_lock_scheme,
            PAGESIZE=@@maxpagesize 
        FROM syscolumns c 
        where id=@table_id
        ORDER BY colid
        end
    end
    return(0)
go
exec sp_procxmode 'sp_drv_bcpmetadata', 'anymode'
go
grant execute on sp_drv_bcpmetadata to public
go
dump transaction sybsystemprocs with truncate_only 
go
/*Stored procedure to support CTS test suite  ADDPOINT_GETSCHEMAS_CTS*/
/*
**  sp_jdbc_getschemas_cts
*/

if exists (select * from sysobjects where name = 'sp_jdbc_getschemas_cts')
    begin
        drop procedure sp_jdbc_getschemas_cts
    end
go
/** SECTION END: CLEANUP **/


CREATE PROCEDURE sp_jdbc_getschemas_cts
as
declare @schemaname varchar(32 )
declare @startedInTransaction       bit

    if @@trancount = 0
    begin
        set chained off
    end
    /* check if we're in a transaction, before we try any select statements */
    if (@@trancount > 0)
      select @startedInTransaction = 1
    else
      select @startedInTransaction = 0  

    set transaction isolation level 1

    if (@startedInTransaction = 1)
       save transaction jdbc_keep_temptables_from_tx

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    create table #tmpschemas
    ( TABLE_SCHEM  varchar (32) null)

    DECLARE jcurs_getschemas CURSOR
    FOR
    select name from sysusers where suid >= -2
    FOR READ ONLY
    OPEN  jcurs_getschemas
    FETCH jcurs_getschemas INTO @schemaname
    while (@@sqlstatus = 0)
    begin
        insert into #tmpschemas values(@schemaname)
        FETCH jcurs_getschemas INTO @schemaname
    end

    close jcurs_getschemas
    deallocate cursor jcurs_getschemas

    select TABLE_SCHEM  from #tmpschemas order by TABLE_SCHEM
    drop table #tmpschemas
    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx
go

exec sp_procxmode 'sp_jdbc_getschemas_cts', 'anymode'
go

grant execute on sp_jdbc_getschemas_cts to public
go

/*
**  End of sp_jdbc_getschemas
*/

if exists (select * from sysobjects where name = 'sp_jdbc_getschemas')
    begin
        drop procedure sp_jdbc_getschemas
    end
go
/** SECTION END: CLEANUP **/


CREATE PROCEDURE sp_jdbc_getschemas 
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1
    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    select TABLE_SCHEM=name  from sysusers where suid >= -2 order by name
go

exec sp_procxmode 'sp_jdbc_getschemas', 'anymode'
go

grant execute on sp_jdbc_getschemas to public
go

commit 
go
dump transaction sybsystemprocs with truncate_only 
go

/* 
**  End of sp_jdbc_getschemas
*/

/*
**  sp_jdbc_getcolumnprivileges 
*/

use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_getcolumnprivileges')
    begin
        drop procedure sp_jdbc_getcolumnprivileges
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_getcolumnprivileges (
    @table_qualifier varchar(32 ) = null,
    @table_owner varchar(32 ) = null,
    @table_name varchar(300)= null,
    @column_name varchar(255) = null)
AS        

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_COLPRIVS */
    declare @grantor_name       varchar (32)    
    declare @grantee_name       varchar (32)    
    declare @col_count          smallint        
    declare @grantee            int
    declare @action             smallint  
    declare @columns            varbinary (133)
    declare @protecttype        tinyint
    declare @grantor            int
    declare @grp_id             int
    declare @grant_type         tinyint
    declare @revoke_type        tinyint
    declare @select_action      smallint
    declare @update_action      smallint
    declare @reference_action   smallint
    declare @insert_action      smallint
    declare @delete_action      smallint
    declare @public_select      varbinary (133)  
    declare @public_reference   varbinary (133)
    declare @public_update      varbinary (133)
    declare @public_insert      tinyint
    declare @public_delete      tinyint
    declare @grp_select         varbinary (133)  
    declare @grp_update         varbinary (133)  
    declare @grp_reference      varbinary (133)  
    declare @grp_delete         tinyint
    declare @grp_insert         tinyint
    declare @inherit_select     varbinary (133)
    declare @inherit_update     varbinary (133)  
    declare @inherit_reference  varbinary (133)  
    declare @inherit_insert     tinyint
    declare @inherit_delete     tinyint
    declare @select_go          varbinary (133)
    declare @update_go          varbinary (133)
    declare @reference_go       varbinary (133)
    declare @insert_go          tinyint
    declare @delete_go          tinyint
    declare @prev_grantor       int
    declare @col_pos            smallint
    declare @owner_id           int
    declare @dbid               smallint
    declare @grantable          varchar (3) 
    declare @is_printable       tinyint
    declare @curr_column        varchar (771)    
    declare @save_column_name varchar(771)
    declare @msg             varchar (255)
    declare @actual_table_name varchar(771)
    declare @searchstr       char(3)
    declare @tab_id          int
    declare @startedInTransaction bit

    if (@@trancount = 0)
    begin
        set chained off
    end

    /* check if we're in a transaction, before we try an select statements */
    if (@@trancount > 0)
        select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    select @grant_type = 1
    select @revoke_type = 2
    select @select_action = 193
    select @reference_action = 151
    select @update_action = 197
    select @delete_action = 196
    select @insert_action = 195
    select @searchstr = 'SUV' /* Only search for SYSTEM USER and VIEW tables */

    set nocount on
 
    set transaction isolation level 1

    if (@startedInTransaction = 1) 
        save transaction jdbc_keep_temptables_from_tx 

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in the tempdb)
    */
    if (@table_name like '#%' and db_name() != 'tempdb')
    begin
        /* 
        ** 17676, 'This may be a temporary object. Please execute 
        ** procedure from tempdb.'
        */
        exec sp_getmessage 17676, @msg out
        raiserror 17676 @msg
        return (1)
    end
 
    /*
    ** The table_qualifier should be same as the database name. Do the sanity 
    ** check if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
        /* set the table qualifier name */
        select @table_qualifier = db_name ()
    else
    begin
        if db_name() != @table_qualifier
        begin
             exec sp_getmessage 18039, @msg out
             raiserror 18039 @msg
             return (1)
        end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name 
    ** prefixed by the owner id
    */
    
    /*
    ** NOTE: SQL Server allows an underscore '_' in the table owner, even 
    **       though '_' is a single character wildcard.
    */
    if (charindex('%',@table_owner) > 0)
        begin
          exec sp_getmessage 17993, @msg output
          raiserror 17993 @msg, @table_owner
          return(1)
        end

    if (@table_owner is null)
    begin
        exec sp_getmessage 17993, @msg output
        raiserror 17993 @msg, 'NULL'
        return(1)
    end
    else
    begin
        exec sp_jdbc_escapeliteralforlike @table_owner output
    end

    if (@table_name is null) 
        begin
          exec sp_getmessage 17993, @msg output
          raiserror 17993 @msg, 'NULL'
          return(1)
        end

    select @actual_table_name = @table_name
    exec sp_jdbc_escapeliteralforlike @table_name output

    
    if (select count(*) from sysobjects 
        where user_name(uid) like @table_owner ESCAPE '\'
        and name like @table_name ESCAPE '\'
        AND charindex(substring(type,1,1),@searchstr) != 0
        ) = 0
    begin
        exec sp_getmessage 17674, @msg output
        raiserror 17674 @msg
        return 1
    end

    create table #sysprotects
        (uid            int,
         action         smallint,
         protecttype    tinyint,
         columns        varbinary (133) NULL,
         grantor        int)

/*
** This table contains all the groups including PUBLIC that users, who
** have been granted privilege on this table, belong to. Also it includes
** groups that have been explicitly granted privileges on the table object
*/
    create table #useful_groups
        (grp_id         int)

/*
** create a table that contains the list of grantors for the object requested.
** We will do a cartesian product of this table with sysusers in the
** current database to capture all grantor/grantee tuples
*/

    create table #distinct_grantors
        (grantor        int)

/*
** We need to create a table which will contain a row for every object
** privilege to be returned to the client.  
*/

    create table #column_privileges 
        (grantee_gid    int,
         grantor        int,
         grantee        int,
         insertpriv     tinyint,
         insert_go      tinyint NULL,
         deletepriv     tinyint,
         delete_go      tinyint NULL,
         selectpriv     varbinary (133) NULL,
         select_go      varbinary (133) NULL,
         updatepriv     varbinary (133) NULL,
         update_go      varbinary (133) NULL,
         referencepriv  varbinary (133) NULL,
         reference_go   varbinary (133) NULL)

/*
** Results Table
*/
    create table #results_table
         (TABLE_CAT             varchar (32),
          TABLE_SCHEM           varchar (32),
          TABLE_NAME            varchar (257),
          COLUMN_NAME           varchar (257) NULL,
          GRANTOR               varchar (32),
          GRANTEE               varchar (32),
          PRIVILEGE             varchar (32),
          IS_GRANTABLE          varchar (3))
/*
** this cursor scans the distinct grantor, group_id pairs
*/
    declare grp_cursor cursor for
        select distinct grp_id, grantor 
        from #useful_groups, #distinct_grantors
        order by grantor

/* 
** this cursor scans all the protection tuples that represent
** grant/revokes to users only
*/
    declare user_protect cursor for
        select uid, action, protecttype, columns, grantor
        from   #sysprotects
        where  (uid != 0) and
               ((uid >= @@minuserid and uid < @@mingroupid) or
               (uid > @@maxgroupid and uid <= @@maxuserid))


/*
** this cursor is used to scan #column_privileges table to output results
*/
    declare col_priv_cursor cursor for
        select grantor, grantee, insertpriv, insert_go, deletepriv, delete_go,
            selectpriv, select_go, updatepriv, update_go, referencepriv, 
            reference_go
        from #column_privileges

    DECLARE jcurs_tab_id CURSOR  FOR
        select id from sysobjects 
        where user_name(uid) like @table_owner ESCAPE '\'
        and name like @table_name ESCAPE '\'
        and (charindex(substring(type,1,1),@searchstr) != 0)

    OPEN  jcurs_tab_id

    FETCH jcurs_tab_id INTO @tab_id

    while (@@sqlstatus = 0)
    begin
        if @column_name is null
            select @column_name = '%'
        else
        begin
            if not exists (select * from syscolumns
               where (id = @tab_id) and (name like @column_name ESCAPE '\' ))
            begin
                exec sp_getmessage 17563, @msg output
                raiserror 17563 @msg, @column_name
                return (1)
            end
        end                     
        select @save_column_name = @column_name
        /* 
        ** compute the table owner id
        */
    
        select @owner_id = uid
        from   sysobjects
        where  id = @tab_id
     
        /*
        ** get table owner name
        */
    
        select @table_owner = name 
                from sysusers 
                where uid = @owner_id
/*
** column count is needed for privilege bit-map manipulation
*/
    select @col_count = count (*) 
    from   syscolumns
    where  id = @tab_id


/* 
** populate the temporary sysprotects table #sysprotects
*/
        insert into #sysprotects 
            select uid, action, protecttype, columns, grantor
            from sysprotects
            where (id = @tab_id) and ((action = @select_action) or
                (action = @update_action) or (action = @reference_action) or
                (action = @insert_action) or (action = @delete_action))
/* 
** insert privilege tuples for the table owner. There is no explicit grants
** of these privileges to the owner. So these tuples are not there in 
** sysprotects table
*/
    insert into #sysprotects 
        values (@owner_id, @select_action, 0, 0x01, @owner_id)
    insert into #sysprotects
        values (@owner_id, @update_action, 0, 0x01, @owner_id)
    insert into #sysprotects 
        values (@owner_id, @reference_action, 0, 0x01, @owner_id)
    insert into #sysprotects
        values (@owner_id, @insert_action, 0, 0x00, @owner_id)
    insert into #sysprotects
        values (@owner_id, @delete_action, 0, 0x00, @owner_id)
/* 
** populate the #distinct_grantors table with all grantors that have granted
** the privilege to users or to gid or to public on the table_name
*/
    insert into #distinct_grantors 
        select distinct grantor from #sysprotects
/* 
** Populate the #column_privilegs table as a cartesian product of the table
** #distinct_grantors and all the users, other than groups, in the current 
** database
*/


    insert into #column_privileges
        select gid, g.grantor, su.uid, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00
        from sysusers su, #distinct_grantors g
        where  (su.uid != 0) and
               ((su.uid >= @@minuserid and su.uid < @@mingroupid) or
               (su.uid > @@maxgroupid and su.uid <= @@maxuserid)) 
               
               

/*
** populate #useful_groups with only those groups whose members have been 
** granted/revoked privilges on the @tab_id in the current database. It also 
** contains those groups that have been granted/revoked privileges explicitly
*/
    insert into #useful_groups
        select distinct gid
        from   sysusers su, #sysprotects sp
        where  (su.uid = sp.uid) 

    open grp_cursor
    fetch grp_cursor into @grp_id, @grantor

    /* 
    ** This loop computes all the inherited privilegs of users due
    ** their membership in a group
    */

    while (@@sqlstatus != 2)
    begin

         /* 
         ** initialize variables 
         */
         select @public_select = 0x00
         select @public_update = 0x00
         select @public_reference = 0x00
         select @public_delete = 0
         select @public_insert = 0


         /* get the select privileges granted to PUBLIC */

         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @select_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_select = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @select_action)
         end


         /* get the update privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @update_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_update = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @update_action)
         end

         /* get the reference privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @reference_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_reference = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @reference_action)
         end


         /* get the delete privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @delete_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_delete = 1
         end

         /* get the insert privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @insert_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_insert = 1
         end


         /*
         ** initialize group privileges 
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** if the group id is other than PUBLIC, we need to find the grants to
         ** the group also 
         */

         if (@grp_id <> 0)
         begin
                /* find select privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @select_action)
                end

                /* find update privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @update_action)
                end

                /* find reference privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @reference_action)
                end

                /* find delete privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @delete_action)))
                begin

                        select @grp_delete = 1
                end

                /* find insert privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @insert_action)))
                begin

                        select @grp_insert = 1

                end

         end

/* at this stage we have computed all the grants to PUBLIC as well as
** the group by a specific grantor that we are interested in. Now we will
** use this info to compute the overall inherited privilegs by the users
** due to their membership to the group or to PUBLIC 
*/

         exec sybsystemprocs.dbo.syb_aux_privunion @public_select, @grp_select,
             @col_count, @inherit_select output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_update, @grp_update,
             @col_count, @inherit_update output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_reference, 
             @grp_reference, @col_count, @inherit_reference output

         select @inherit_insert = @public_insert + @grp_insert
         select @inherit_delete = @public_delete + @grp_delete

         /*
         ** initialize group privileges to store revokes
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** now we need to find if there are any revokes on the group under
         ** consideration. We will subtract all privileges that are revoked  
         ** from the group from the inherited privileges
         */

         if (@grp_id <> 0)
         begin
             /* check if there is a revoke row for select privilege*/
             if (exists (select * from #sysprotects 
                         where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @select_action)))
             begin
                 select @grp_select = columns
                 from #sysprotects
                 where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @select_action)
             end
                /* check if there is a revoke row for update privileges */
             if (exists (select * from #sysprotects 
                         where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @update_action)))
             begin
                 select @grp_update = columns
                 from #sysprotects
                 where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @update_action)
             end

             /* check if there is a revoke row for reference privilege */
             if (exists (select * from #sysprotects 
                         where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @reference_action)))
             begin
                 select @grp_reference = columns
                 from #sysprotects
                 where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @reference_action)
             end

                /* check if there is a revoke row for delete privilege */
             if (exists (select * from #sysprotects 
                         where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @delete_action)))
             begin
                 select @grp_delete = 1
             end

                /* check if there is a revoke row for insert privilege */
             if (exists (select * from #sysprotects 
                         where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @insert_action)))
             begin
                 select @grp_insert = 1
             end


                /* 
                ** now subtract the revoked privileges from the group
                */

             exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                        @grp_select, @col_count, @inherit_select output

             exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                        @grp_update, @col_count, @inherit_update output

             exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference,
                        @grp_reference, @col_count, @inherit_reference output

             if (@grp_delete = 1)
                 select @inherit_delete = 0

             if (@grp_insert = 1)
                 select @inherit_insert = 0

         end

         /*
         ** now update all the tuples in #column_privileges table for this
         ** grantor and group id
         */

         update #column_privileges
         set
                insertpriv      = @inherit_insert,
                deletepriv      = @inherit_delete,
                selectpriv      = @inherit_select,
                updatepriv      = @inherit_update,
                referencepriv   = @inherit_reference
         where (grantor     = @grantor) and
               (grantee_gid = @grp_id)

         /*
         ** the following update updates the privileges for those users
         ** whose groups have not been explicitly granted privileges by the
         ** grantor. So they will all have all the privileges of the PUBLIC
         ** that were granted by the current grantor
         */

         select @prev_grantor = @grantor         
         fetch grp_cursor into @grp_id, @grantor

         if ((@prev_grantor <> @grantor) or (@@sqlstatus = 2))
         begin
         /* Either we are at the end of the fetch or we are switching to
         ** a different grantor. 
         */

               update #column_privileges 
               set
                        insertpriv      = @public_insert,
                        deletepriv      = @public_delete,
                        selectpriv      = @public_select,
                        updatepriv      = @public_update,
                        referencepriv   = @public_reference
                from #column_privileges cp
                where (cp.grantor = @prev_grantor) and
                      (not EXISTS (select * 
                                   from #useful_groups ug
                                   where ug.grp_id = cp.grantee_gid))
         end
    end
    close grp_cursor

    /* 
    ** At this stage, we have populated the #column_privileges table with
    ** all the inherited privileges
    ** Now we will go through each user grant or revoke in table #sysprotects
    ** and update the privileges in #column_privileges table
    */
    open user_protect

    fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor

    while (@@sqlstatus != 2)
    begin
/*
** In this loop, we can find grant row, revoke row or grant with grant option
** row. We use protecttype to figure that. If it is grant, then the user 
** specific privileges are added to the user's inherited privileges. If it 
** is a revoke,then the revoked privileges are subtracted from the inherited 
** privileges. If it is a grant with grant option, we just store it as is 
** because privileges can only be granted with grant option to individual users
*/

/* 
** for select action
*/
        if (@action = @select_action)
        begin
            /* get the inherited select privilege */
            select @inherit_select = selectpriv
            from   #column_privileges
            where  (grantee = @grantee) and
                   (grantor = @grantor)

            if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
            exec sybsystemprocs.dbo.syb_aux_privunion @inherit_select, 
                @columns, @col_count, @inherit_select output

            else 
            if (@protecttype = @revoke_type)
                /* it is a revoke row */
                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select, 
                @columns, @col_count, @inherit_select output

            else
                     /* it is a grant with grant option */
                select @select_go = @columns
                    /* modify the privileges for this user */
            if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
            begin
                update #column_privileges
                set selectpriv = @inherit_select
                where (grantor = @grantor) and
                      (grantee = @grantee)
            end
            else
            begin
                update #column_privileges
                set select_go = @select_go
                where (grantor = @grantor) and
                      (grantee = @grantee)
            end
        end
        /*
        ** update action
        */
        if (@action = @update_action)
        begin
             /* find out the inherited update privilege */
             select @inherit_update = updatepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* user has an individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_update,
                    @columns, @col_count, @inherit_update output

             else 
                if (@protecttype = @revoke_type)
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                       @columns, @col_count, @inherit_update output

                else
                     /* it is a grant with grant option */
                     select @update_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set updatepriv = @inherit_update
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set update_go = @update_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /* it is the reference privilege */
        if (@action = @reference_action)
        begin
             select @inherit_reference = referencepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_reference,
                     @columns, @col_count, @inherit_reference output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor
                       @inherit_reference, @columns, @col_count,
                       @inherit_reference output

                else
                     /* it is a grant with grant option */
                     select @reference_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set referencepriv = @inherit_reference
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set reference_go = @reference_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /*
        ** insert action
        */

        if (@action = @insert_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_insert = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_insert = 0
                 else
                      select @insert_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set insertpriv = @inherit_insert
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set insert_go = @insert_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /* 
        ** delete action
        */

        if (@action = @delete_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_delete = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_delete = 0
                 else
                      select @delete_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set deletepriv = @inherit_delete
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set delete_go = @delete_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        fetch user_protect into @grantee,@action,@protecttype,@columns,@grantor
    end

    close user_protect

    open col_priv_cursor
    fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
                 @inherit_delete, @delete_go, @inherit_select, @select_go,
                 @inherit_update, @update_go, @inherit_reference, @reference_go

    while (@@sqlstatus != 2)
    begin

        /* 
        ** name of the grantor/grantee
        */
        select @grantor_name = name from sysusers where  uid = @grantor
        select @grantee_name = name from sysusers where  uid = @grantee

        if (@column_name = '%')
        begin
            select @col_pos = 1
            while (@col_pos <= @col_count)
            begin
                select @curr_column = col_name (@tab_id, @col_pos)
                /* 
                ** check for insert privileges
                */
                exec sybsystemprocs.dbo.syb_aux_printprivs 
                     1, @col_pos, @inherit_insert,@insert_go,
                     0x00, 0x00, 0, @grantable output, @is_printable output
                if (@is_printable = 1)
                begin
                    insert into #results_table
                    values (@table_qualifier, @table_owner, @actual_table_name, 
                            @curr_column, @grantor_name, @grantee_name, 
                            'INSERT', @grantable)
                end

                /* 
                ** check for select privileges
                */
                exec sybsystemprocs.dbo.syb_aux_printprivs 
                     1, @col_pos, 0, 0, @inherit_select, 
                     @select_go, 1, @grantable output, @is_printable output

                if (@is_printable = 1)
                begin
                    insert into #results_table
                    values (@table_qualifier, @table_owner, @actual_table_name, 
                            @curr_column, @grantor_name,@grantee_name,'SELECT',
                            @grantable)
                end
                /* 
                ** check for update privileges
                */
                exec sybsystemprocs.dbo.syb_aux_printprivs 
                     1, @col_pos, 0, 0, @inherit_update, 
                     @update_go, 1, @grantable output, @is_printable output
                if (@is_printable = 1)
                begin
                    insert into #results_table
                    values (@table_qualifier, @table_owner, @actual_table_name, 
                            @curr_column, @grantor_name, @grantee_name, 
                            'UPDATE', @grantable)
                end
                /*
                ** check for reference privs
                */

                exec sybsystemprocs.dbo.syb_aux_printprivs 
                     1, @col_pos, 0, 0, @inherit_reference, 
                     @reference_go, 1, @grantable output, @is_printable output
                if (@is_printable = 1)
                begin
                    insert into #results_table
                    values (@table_qualifier, @table_owner, @actual_table_name, 
                            @curr_column, @grantor_name, @grantee_name, 
                            'REFERENCE', @grantable)
                end
                select @col_pos = @col_pos + 1
            end
        end
        else
        begin
           /* 
           ** At this point, we are either printing privilege information for a
           ** a specific column or for table_privileges
           */
            select @col_pos = colid
            from syscolumns
            where (id = @tab_id) and
                (name = @column_name)

            /* 
            ** check for insert privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                1, @col_pos, @inherit_insert, @insert_go, 
                0x00, 0x00, 0, @grantable output, @is_printable output
            if (@is_printable = 1)
            begin
                insert into #results_table
                values (@table_qualifier,@table_owner,@actual_table_name,
                        @column_name, @grantor_name, @grantee_name, 'INSERT',
                        @grantable)
            end

            /* 
            ** check for delete privileges
            */

            exec sybsystemprocs.dbo.syb_aux_printprivs 
                1, @col_pos, @inherit_delete, @delete_go,
                0x00, 0x00, 0, @grantable output, @is_printable output
            if (@is_printable = 1)
            begin
                insert into #results_table
                values (@table_qualifier, @table_owner, @actual_table_name, 
                        @column_name, @grantor_name, @grantee_name, 
                        'DELETE', @grantable)
            end

            /* 
            ** check for select privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                1, @col_pos, 0, 0, @inherit_select, 
                @select_go, 1, @grantable output, @is_printable output
            if (@is_printable = 1)
            begin
               insert into #results_table
               values (@table_qualifier, @table_owner, @actual_table_name, 
                       @column_name, @grantor_name, @grantee_name, 'SELECT', 
                       @grantable)
            end
            /* 
            ** check for update privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                1, @col_pos, 0, 0, @inherit_update,  
                @update_go, 1, @grantable output, @is_printable output
            if (@is_printable = 1)
            begin
                insert into #results_table
                values (@table_qualifier, @table_owner, @actual_table_name, 
                        @column_name, @grantor_name, @grantee_name, 'UPDATE', 
                        @grantable)
            end
            /*
            ** check for reference privs
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                1, @col_pos, 0, 0, @inherit_reference, 
                @reference_go, 1, @grantable output, @is_printable output
            if (@is_printable = 1)
            begin
                insert into #results_table
                values (@table_qualifier, @table_owner, @actual_table_name, 
                        @column_name, @grantor_name, @grantee_name, 
                        'REFERENCE', @grantable)
            end
        end

        fetch col_priv_cursor into @grantor, @grantee, @inherit_insert,
            @insert_go, @inherit_delete, @delete_go, @inherit_select,
            @select_go, @inherit_update, @update_go, @inherit_reference, 
            @reference_go
        end
        close col_priv_cursor
        FETCH jcurs_tab_id INTO @tab_id
    end
    
/*
** Outputting the results table
*/
        /* Changed to get the requested output order*/
        select distinct TABLE_CAT, TABLE_SCHEM,
               TABLE_NAME, COLUMN_NAME , 
               GRANTOR, GRANTEE, 
               PRIVILEGE, IS_GRANTABLE 
        from #results_table
        where COLUMN_NAME like @save_column_name
        order by COLUMN_NAME, PRIVILEGE

    set nocount off

    if (@startedInTransaction = 1) 
        rollback transaction jdbc_keep_temptables_from_tx 

    return(0)


go

exec sp_procxmode 'sp_jdbc_getcolumnprivileges', 'anymode'
go

grant execute on sp_jdbc_getcolumnprivileges to public
go

dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_getcolumnprivileges 
*/


/*
**  sp_jdbc_gettableprivileges 
*/

/*
** sp_jdbc_gettableprivileges requires one auxiliary stored procedure/ 
** We do the cleanup and then load that proc first
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_gettableprivileges')
    begin
        drop procedure sp_jdbc_gettableprivileges
    end
go

if exists (select * from sysobjects where name = 'sp_jdbc_computeprivs')
    begin
        drop procedure sp_jdbc_computeprivs
    end
go

/** SECTION END: CLEANUP **/

/*
** The results_table, sysprotects, useful_groups, distinct_grantors and
** column_privileges tables need to be created so that sp_jdbc_computeprivs
** has a temp table to reference when the procedure is compiled.
** Otherwise, the calling stored procedure will create the temp tables for
** sp_jdbc_computeprivs. Note that it was necessary to put the table creation
** in the calling stored procedure because in transactions, when you nest
** stored procs, the inner proc cannot create temp tables because they
** get lost when the procedure exits (and thus, a rollback could not be
** executed if one was desired). That caused a server error.
*/
create table #results_table
        (table_qualifier        varchar (32 ),
         table_owner            varchar (32 ),
         table_name             varchar (255),
         column_name            varchar (255) NULL,
         grantor                varchar (32 ),
         grantee                varchar (32 ),
         privilege              varchar (32 ),
         is_grantable           varchar (3))
go

create table #sysprotects
        (uid            int,
         action         smallint,
         protecttype    tinyint,
         columns        varbinary (133) NULL,
         grantor        int)
go

create table #useful_groups
        (grp_id         int)
go

create table #distinct_grantors
        (grantor        int)
go

create table #column_privileges
        (grantee_gid    int,
         grantor        int,
         grantee        int,
         insertpriv     tinyint,
         insert_go      tinyint NULL,
         deletepriv     tinyint,
         delete_go      tinyint NULL,
         selectpriv     varbinary (133) NULL,
         select_go      varbinary (133) NULL,
         updatepriv     varbinary (133) NULL,
         update_go      varbinary (133) NULL,
         referencepriv  varbinary (133) NULL,
         reference_go   varbinary (133) NULL)
go


create procedure sp_jdbc_computeprivs (
                        @table_name             varchar(255),
                        @table_owner            varchar(32 ),
                        @table_qualifier        varchar(32 ),
                        @column_name            varchar(255),
                        @calledfrom_colpriv     tinyint,
                        @tab_id                 int)

AS

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_COMPUTE_PRIVS */
    declare @grantor_name       varchar (32)    /* the ascii name of grantor.
                                                   used for output */
    declare @grantee_name       varchar (32)    /* the ascii name of grantee.
                                                   used for output */
    declare @col_count          smallint        /* number of columns in
                                                   @table_name */
    declare @grantee            int             /* id of the grantee */
    declare @action             smallint        /* action refers to select,
                                                   update...*/
    declare @columns            varbinary (133) /* bit map of column
                                                   privileges */
    declare @protecttype        tinyint         /* grant/revoke or grant with
                                                   grant option */
    declare @grantor            int             /* id of the grantor of the
                                                   privilege */
    declare @grp_id             int             /* the group a user belongs
                                                   to */
    declare @grant_type         tinyint         /* used as a constant */
    declare @revoke_type        tinyint         /* used as a constant */
    declare @select_action      smallint        /* used as a constant */
    declare @update_action      smallint        /* used as a constant */
    declare @reference_action   smallint        /* used as a constant */
    declare @insert_action      smallint        /* used as a constant */
    declare @delete_action      smallint        /* used as a constant */
    declare @public_select      varbinary (133) /* stores select column bit map
                                                   for public */
    declare @public_reference   varbinary (133) /* stores reference column bit
                                                   map for public */
    declare @public_update      varbinary (133) /* stores update column bit map
                                                   for public */
    declare @public_insert      tinyint         /* stores if insert has been
                                                   granted to public */
    declare @public_delete      tinyint         /* store if delete has been
                                                   granted to public */
    declare @grp_select         varbinary (133) /* stores select column bit map
                                                   for group */
    declare @grp_update         varbinary (133) /* stores update column bit map
                                                   for group */
    declare @grp_reference      varbinary (133) /* stores reference column bit
                                                   map for group */
    declare @grp_delete         tinyint         /* if group hs been granted
                                                   delete privilege */
    declare @grp_insert         tinyint         /* if group has been granted
                                                   insert privilege */
    declare @inherit_select     varbinary (133) /* stores select column bit map
                                                   for inherited privs*/
    declare @inherit_update     varbinary (133) /* stores update column bit map
                                                   for inherited privs */
    declare @inherit_reference  varbinary (133) /* stores reference column bit
                                                   map for inherited privs */
    declare @inherit_insert     tinyint         /* inherited insert priv */
    declare @inherit_delete     tinyint         /* inherited delete priv */
    declare @select_go          varbinary (133) /* user column bit map of
                                                   select with grant */
    declare @update_go          varbinary (133) /* user column bit map of
                                                   update with grant */
    declare @reference_go       varbinary (133) /* user column bitmap of
                                                   reference with grant */
    declare @insert_go          tinyint         /* user insert priv with
                                                   grant option */
    declare @delete_go          tinyint         /* user delete priv with grant
                                                   option  */
    declare @prev_grantor       int             /* used to detect if the
                                                   grantor has changed between
                                                   two consecutive tuples */
    declare @col_pos            smallint        /* col_pos of the column we are
                                                   interested in. It is used to
                                                   find the col-bit in the
                                                   bitmap */
    declare @owner_id           int             /* id of the owner of the
                                                   table */
    declare @dbid               smallint        /* dbid for the table */
    declare @grantable          varchar (3)     /* 'YES' or 'NO' if the
                                                   privilege is grantable or
                                                   not */
    declare @is_printable       tinyint         /* 1, if the privilege info is
                                                   to be outputted */

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

/* 
** Initialize all constants to be used in this procedure
*/

    select @grant_type = 1

    select @revoke_type = 2
   
    select @select_action = 193

    select @reference_action = 151

    select @update_action = 197

    select @delete_action = 196

    select @insert_action = 195

/*
** compute the table owner id
*/

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id

/*
** note that the temp tables referred to by this stored proc must be created
** in the calling proc
*/

/*
** this cursor scans the distinct grantor, group_id pairs
*/
    declare grp_cursor cursor for
        select distinct grp_id, grantor 
        from #useful_groups, #distinct_grantors
        order by grantor

/* 
** this cursor scans all the protection tuples that represent
** grant/revokes to users only
*/
    declare user_protect cursor for
        select uid, action, protecttype, columns, grantor
        from   #sysprotects
        where  (uid != 0) and
               ((uid >= @@minuserid and uid < @@mingroupid) or 
               (uid > @@maxgroupid and uid <= @@maxuserid)) 


/*
** this cursor is used to scan #column_privileges table to output results
*/
    declare col_priv_cursor cursor for
          select grantor, grantee, insertpriv, insert_go, deletepriv,
              delete_go, selectpriv, select_go, updatepriv, update_go,
              referencepriv, reference_go
          from #column_privileges



/*
** column count is needed for privilege bit-map manipulation
*/
    select @col_count = count (*) 
    from   syscolumns
    where  id = @tab_id


/* 
** populate the temporary sysprotects table #sysprotects
*/

        insert into #sysprotects 
                select uid, action, protecttype, columns, grantor
                from sysprotects
                where (id = @tab_id)               and
                      ((action = @select_action)   or
                      (action = @update_action)    or
                      (action = @reference_action) or
                      (action = @insert_action)    or
                      (action = @delete_action))

/* 
** insert privilege tuples for the table owner. There is no explicit grants
** of these privileges to the owner. So these tuples are not there in
** sysprotects table
*/

if not exists (select * from #sysprotects where (action = @select_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @select_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @update_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @update_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @reference_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @reference_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @insert_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @insert_action, 0, NULL, @owner_id)
end

if not exists (select * from #sysprotects where (action = @delete_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @delete_action, 0, NULL, @owner_id)
end


/* 
** populate the #distinct_grantors table with all grantors that have granted
** the privilege to users or to gid or to public on the table_name
*/

    insert into #distinct_grantors 
          select distinct grantor from #sysprotects

/* 
** Populate the #column_privilegs table as a cartesian product of the table
** #distinct_grantors and all the users, other than groups, in the current
** database
*/


    insert into #column_privileges
          select gid, g.grantor, su.uid, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00,
              0x00, 0x00
          from sysusers su, #distinct_grantors g
        where  (su.uid != 0) and
               ((su.uid >= @@minuserid and su.uid < @@mingroupid) or
               (su.uid > @@maxgroupid and su.uid <= @@maxuserid)) 

/*
** populate #useful_groups with only those groups whose members have been
** granted/revoked privileges on the @tab_id in the current database. It also
** contains those groups that have been granted/revoked privileges explicitly
*/

    insert into #useful_groups
        select distinct gid
        from   sysusers su, #sysprotects sp
        where  (su.uid = sp.uid) 


    open grp_cursor

    fetch grp_cursor into @grp_id, @grantor

    /* 
    ** This loop computes all the inherited privilegs of users due
    ** their membership in a group
    */

    while (@@sqlstatus != 2)
   
    begin

         /* 
         ** initialize variables 
         */
         select @public_select = 0x00
         select @public_update = 0x00
         select @public_reference = 0x00
         select @public_delete = 0
         select @public_insert = 0


         /* get the select privileges granted to PUBLIC */

         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @select_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_select = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @select_action)
         end


         /* get the update privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @update_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_update = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @update_action)
         end

         /* get the reference privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @reference_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_reference = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @reference_action)
         end


         /* get the delete privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @delete_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_delete = 1
         end

         /* get the insert privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @insert_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_insert = 1
         end


         /*
         ** initialize group privileges 
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** if the group id is other than PUBLIC, we need to find the grants to
         ** the group also 
         */

         if (@grp_id <> 0)
         begin
                /* find select privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @select_action)
                end

                /* find update privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @update_action)
                end

                /* find reference privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @reference_action)
                end

                /* find delete privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @delete_action)))
                begin

                        select @grp_delete = 1
                end

                /* find insert privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @insert_action)))
                begin

                        select @grp_insert = 1

                end

         end

         /* at this stage we have computed all the grants to PUBLIC as well as
         ** the group by a specific grantor that we are interested in. Now we
         ** will use this info to compute the overall inherited privileges by
         ** the users due to their membership to the group or to PUBLIC 
         */


         exec sybsystemprocs.dbo.syb_aux_privunion @public_select, @grp_select,
             @col_count, @inherit_select output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_update, @grp_update, 
             @col_count, @inherit_update output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_reference,
             @grp_reference, @col_count, @inherit_reference output

         select @inherit_insert = @public_insert + @grp_insert
         select @inherit_delete = @public_delete + @grp_delete

         /*
         ** initialize group privileges to store revokes
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** now we need to find if there are any revokes on the group under
         ** consideration. We will subtract all privileges that are revoked
         ** from the group from the inherited privileges
         */

         if (@grp_id <> 0)
         begin
                /* check if there is a revoke row for select privilege*/
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @select_action)
                end

                /* check if there is a revoke row for update privileges */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @update_action)
                end

                /* check if there is a revoke row for reference privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @reference_action)
                end

                /* check if there is a revoke row for delete privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @delete_action)))
                begin
                        select @grp_delete = 1
                end

                /* check if there is a revoke row for insert privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @insert_action)))
                begin
                        select @grp_insert = 1

                end


                /* 
                ** now subtract the revoked privileges from the group
                */

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                                                 @grp_select,
                                                 @col_count,
                                                 @inherit_select output

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                                                 @grp_update,
                                                 @col_count,
                                                 @inherit_update output

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference,
                                                 @grp_reference,
                                                 @col_count,
                                                 @inherit_reference output

                if (@grp_delete = 1)
                        select @inherit_delete = 0

                if (@grp_insert = 1)
                        select @inherit_insert = 0

         end

         /*
         ** now update all the tuples in #column_privileges table for this
         ** grantor and group id
         */

         update #column_privileges
         set
                insertpriv      = @inherit_insert,
                deletepriv      = @inherit_delete,
                selectpriv      = @inherit_select,
                updatepriv      = @inherit_update,
                referencepriv   = @inherit_reference

         where (grantor     = @grantor) and
               (grantee_gid = @grp_id)


         /*
         ** the following update updates the privileges for those users
         ** whose groups have not been explicitly granted privileges by the
         ** grantor. So they will all have all the privileges of the PUBLIC
         ** that were granted by the current grantor
         */

         select @prev_grantor = @grantor         
         fetch grp_cursor into @grp_id, @grantor

         if ((@prev_grantor <> @grantor) or (@@sqlstatus = 2))

         begin
         /* Either we are at the end of the fetch or we are switching to
         ** a different grantor. 
         */

               update #column_privileges 
               set
                        insertpriv      = @public_insert,
                        deletepriv      = @public_delete,
                        selectpriv      = @public_select,
                        updatepriv      = @public_update,
                        referencepriv   = @public_reference
                from #column_privileges cp
                where (cp.grantor = @prev_grantor) and
                      (not EXISTS (select * 
                                   from #useful_groups ug
                                   where ug.grp_id = cp.grantee_gid))

         end
    end


    close grp_cursor


    /* 
    ** At this stage, we have populated the #column_privileges table with
    ** all the inherited privileges
    */
    /*
    ** update #column_privileges to give all access to the table owner that way
    ** if there are any revoke rows in sysprotects, then the calculations will
    ** be done correctly.  There will be no revoke rows for table owner if
    ** privileges are revoked from a group that the table owner belongs to.
    */
    update #column_privileges
    set
        insertpriv      = 0x01, 
        deletepriv      = 0x01, 
        selectpriv      = 0x01,
        updatepriv      = 0x01,
        referencepriv   = 0x01

        where grantor = grantee
          and grantor = @owner_id

    
    /* 
    ** Now we will go through each user grant or revoke in table #sysprotects
    ** and update the privileges in #column_privileges table
    */
    open user_protect

    fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor

    while (@@sqlstatus != 2)
    begin
        /*
        ** In this loop, we can find grant row, revoke row or grant with grant
        ** option row. We use protecttype to figure that. If it is grant, then
        ** the user specific privileges are added to the user's inherited
        ** privileges. If it is a revoke, then the revoked privileges are
        ** subtracted from the inherited privileges. If it is a grant with
        ** grant option, we just store it as is because privileges can
        ** only be granted with grant option to individual users
        */

        /* 
        ** for select action
        */
        if (@action = @select_action)
        begin
             /* get the inherited select privilege */
             select @inherit_select = selectpriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)

             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_select,
                    @columns, @col_count, @inherit_select output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                         @columns, @col_count, @inherit_select output

                else
                     /* it is a grant with grant option */

                     select @select_go = @columns

             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set selectpriv = @inherit_select
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin

                  update #column_privileges
                  set select_go = @select_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /*
        ** update action
        */
        if (@action = @update_action)
        begin
             /* find out the inherited update privilege */
             select @inherit_update = updatepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* user has an individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_update,
                    @columns, @col_count, @inherit_update output

             else 
                if (@protecttype = @revoke_type)
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                         @columns, @col_count, @inherit_update output

                else
                     /* it is a grant with grant option */
                     select @update_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set updatepriv = @inherit_update
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set update_go = @update_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /* it is the reference privilege */
        if (@action = @reference_action)
        begin
             select @inherit_reference = referencepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_reference,
                    @columns, @col_count, @inherit_reference output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor
                        @inherit_reference, @columns, @col_count,
                        @inherit_reference output

                else
                     /* it is a grant with grant option */
                     select @reference_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set referencepriv = @inherit_reference
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set reference_go = @reference_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /*
        ** insert action
        */

        if (@action = @insert_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_insert = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_insert = 0
                 else
                      select @insert_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set insertpriv = @inherit_insert
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set insert_go = @insert_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /* 
        ** delete action
        */

        if (@action = @delete_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_delete = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_delete = 0
                 else
                      select @delete_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set deletepriv = @inherit_delete
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set delete_go = @delete_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        fetch user_protect into @grantee, @action, @protecttype, @columns,
            @grantor
    end

    close user_protect

open col_priv_cursor
fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
                         @inherit_delete, @delete_go, @inherit_select,
                         @select_go, @inherit_update, @update_go,
                         @inherit_reference, @reference_go

while (@@sqlstatus != 2)
begin

      /* 
      ** name of the grantor
      */
      select @grantor_name = name 
      from   sysusers
      where  uid = @grantor


      /*
      ** name of the grantee
      */

      select @grantee_name = name
      from   sysusers
      where  uid = @grantee

      /* 
      ** At this point, we are either printing privilege information for a
      ** a specific column or for table_privileges
      */

            select @col_pos = 0

            if (@calledfrom_colpriv = 1)
            begin
            /* 
            ** find the column position
            */
                 select @col_pos = colid
                 from syscolumns
                 where (id = @tab_id) and
                       (name = @column_name)
            end

            /* 
            ** check for insert privileges
            */
            /* insert privilege is only a table privilege */
            if (@calledfrom_colpriv = 0)
            begin
                    exec sybsystemprocs.dbo.syb_aux_printprivs 
                        @calledfrom_colpriv, @col_pos, @inherit_insert,
                        @insert_go, 0x00, 0x00, 0, @grantable output,
                        @is_printable output

                    if (@is_printable = 1)
                    begin
                          insert into #results_table
                               values (@table_qualifier, @table_owner,
                                       @table_name, @column_name,
                                       @grantor_name, @grantee_name, 'INSERT',
                                       @grantable)
                    end
            end

            /* 
            ** check for delete privileges
            */

            if (@calledfrom_colpriv = 0)
            /* delete privilege need only be printed if called from
               sp_table_privileges */
            begin
                    exec sybsystemprocs.dbo.syb_aux_printprivs 
                         @calledfrom_colpriv, @col_pos, @inherit_delete,
                         @delete_go, 0x00, 0x00, 0, @grantable output,
                         @is_printable output

                    if (@is_printable = 1)
                    begin
                        insert into #results_table
                                values (@table_qualifier, @table_owner,
                                        @table_name, @column_name,
                                        @grantor_name, @grantee_name, 'DELETE',
                                        @grantable)
                    end
            end

            /* 
            ** check for select privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                        @calledfrom_colpriv, @col_pos, 0, 0, @inherit_select,
                        @select_go, 1, @grantable output, @is_printable output


            if (@is_printable = 1)
            begin
                  insert into #results_table
                         values (@table_qualifier, @table_owner, @table_name,
                                 @column_name, @grantor_name, @grantee_name,
                                 'SELECT', @grantable)
            end
            /* 
            ** check for update privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                @calledfrom_colpriv, @col_pos, 0, 0, @inherit_update,
                @update_go, 1, @grantable output, @is_printable output

            if (@is_printable = 1)
            begin
                  insert into #results_table
                        values (@table_qualifier, @table_owner, @table_name,
                                @column_name, @grantor_name, @grantee_name,
                                'UPDATE', @grantable)
            end
            /*
            ** check for reference privs
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                @calledfrom_colpriv, @col_pos, 0, 0, @inherit_reference,
                @reference_go, 1, @grantable output, @is_printable output

            if (@is_printable = 1)
            begin
                insert into #results_table
                        values (@table_qualifier, @table_owner, @table_name,
                                @column_name, @grantor_name, @grantee_name,
                                'REFERENCE', @grantable)
            end



      fetch col_priv_cursor into @grantor, @grantee, @inherit_insert,
          @insert_go, @inherit_delete, @delete_go, @inherit_select, @select_go,
          @inherit_update, @update_go, @inherit_reference, @reference_go
end

close col_priv_cursor


go

/*
** Drop temp tables used for creation of sp_jdbc_computeprivs
*/
drop table #results_table
go
drop table #column_privileges
go
drop table #distinct_grantors
go
drop table #sysprotects
go
drop table #useful_groups
go

exec sp_procxmode 'sp_jdbc_computeprivs', 'anymode'
go

grant execute on sp_jdbc_computeprivs to public
go

create procedure sp_jdbc_gettableprivileges (
    @table_qualifier    varchar(32 ),
    @table_owner        varchar(32 ) = null,
    @table_name         varchar(771)= null)
AS       

    declare @tab_name                   varchar(771)
    declare @tab_owner                  varchar(32 )
    declare @table_id 			int	    /* object id of the
                                                       table specified */
    declare @startedInTransaction       bit


    if (@@trancount = 0)
    begin
        set chained off
    end

    /* check if we're in a transaction, before we try any select statements */
    if (@@trancount > 0)
        select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

    set nocount on

    set transaction isolation level 1

    if (@startedInTransaction = 1)
        save transaction jdbc_keep_temptables_from_tx

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    if (@table_qualifier is null) or (@table_qualifier = '')
	/* set the table qualifier name */
	select @table_qualifier = db_name ()

    if (@table_owner is null) or (@table_owner = '')
        select @table_owner = '%'

    if (@table_name is null)
    begin
        select @table_name = '%'
    end

    /* Now, create a temporary table to hold a list of all the possible
       tables that we could get with the trio of table name, table owner and
       table catalog. Then, populate that table. */

    create table #jdbc_tprivs
        (tab_id         int primary key,
         tab_name       varchar (255),
         tab_owner      varchar (32 ) null,
         uid            int,
         type           varchar (10))

    insert #jdbc_tprivs 
        SELECT id, name, user_name(uid), uid, type 
        FROM sysobjects s 
        WHERE name LIKE @table_name ESCAPE '\'
            AND user_name (uid) LIKE @table_owner ESCAPE '\'
            AND charindex(substring(type,1,1), 'SUV') != 0

    /* Create temp table to store results from sp_jdbc_computeprivs */
    create table #results_table
	 (TABLE_CAT		varchar (32 ),
	  TABLE_SCHEM		varchar (32 ),
	  TABLE_NAME		varchar (255),
	  column_name		varchar (255) NULL,
	  GRANTOR		varchar (32 ),
	  GRANTEE 		varchar (32 ),
	  PRIVILEGE		varchar (32 ),
	  IS_GRANTABLE		varchar (3))


    declare tpriv_cursor cursor for
        select tab_name, tab_owner, tab_id from #jdbc_tprivs

    open tpriv_cursor
   
    fetch tpriv_cursor into @tab_name, @tab_owner, @table_id
 
    while (@@sqlstatus != 2)
    begin

        /*
        ** The following four temp tables used to be created in 
        ** sp_jdbc_computeprivs, but to avoid errors when this proc was
        ** run in a transaction, we had to move the creation of the
        ** temp tables here. Note that this repeated creation and 
        ** destruction of the temp tables is no less efficient than 
        ** what was being done previously, since these tables were being
        ** created and destroyed with each call to computeprivs in the while
        ** loop
        */

        /*
        ** create a temporary sysprotects table that only has grant/revoke
        ** tuples for the requested table. This is done as an optimization
        ** as the sysprotects table may need to be traversed several times
        */

        create table #sysprotects
            (uid            int,
             action         smallint,
             protecttype    tinyint,
             columns        varbinary (133) NULL,
             grantor        int)

        /*
        ** This table contains all the groups including PUBLIC that users, who
        ** have been granted privilege on this table, belong to. Also it
        ** includes groups that have been explicitly granted privileges on the
        ** table object
        */
        create table #useful_groups
            (grp_id         int)

        /*
        ** create a table that contains the list of grantors for the object
        ** requested. We will do a cartesian product of this table with
        ** sysusers in the current database to capture all grantor/grantee
        ** tuples
        */

        create table #distinct_grantors
            (grantor        int)

        /*
        ** We need to create a table which will contain a row for every object
        ** privilege to be returned to the client.
        */

        create table #column_privileges
            (grantee_gid    int,
             grantor        int,
             grantee        int,
             insertpriv     tinyint,
             insert_go      tinyint NULL,
             deletepriv     tinyint,
             delete_go      tinyint NULL,
             selectpriv     varbinary (133) NULL,
             select_go      varbinary (133) NULL,
             updatepriv     varbinary (133) NULL,
             update_go      varbinary (133) NULL,
             referencepriv  varbinary (133) NULL,
             reference_go   varbinary (133) NULL)

        exec sp_jdbc_computeprivs @tab_name, @tab_owner, @table_qualifier, 
			     NULL, 0, @table_id
        fetch tpriv_cursor into @tab_name, @tab_owner, @table_id

        drop table #column_privileges
        drop table #distinct_grantors
        drop table #sysprotects
        drop table #useful_groups

    end

    close tpriv_cursor


    /* Output the results table */

    select TABLE_CAT, TABLE_SCHEM, TABLE_NAME, GRANTOR, GRANTEE,
           PRIVILEGE, IS_GRANTABLE
    from #results_table
    order by TABLE_SCHEM, TABLE_NAME, PRIVILEGE

    drop table #jdbc_tprivs
    drop table #results_table
    set nocount off 	

    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx

go

exec sp_procxmode 'sp_jdbc_gettableprivileges', 'anymode'
go

grant execute on sp_jdbc_gettableprivileges to public
go

dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_gettableprivileges 
*/


/*Stored procedure to support CTS test suite  ADDPOINT_GETCATALOGS_CTS*/
/*
** sp_jdbc_getcatalogs_cts
*/
if exists (select * from sysobjects where name = 'sp_jdbc_getcatalogs_cts')
    begin
        drop procedure sp_jdbc_getcatalogs_cts
    end
go
/** SECTION END: CLEANUP **/


CREATE PROCEDURE sp_jdbc_getcatalogs_cts
as
declare @dbname varchar(32)
declare @startedInTransaction       bit

    if @@trancount = 0
    begin
        set chained off
    end

    /* check if we're in a transaction, before we try any select statements */
    if (@@trancount > 0)
      select @startedInTransaction = 1
    else
      select @startedInTransaction = 0

    set transaction isolation level 1

    if (@startedInTransaction = 1)
       save transaction jdbc_keep_temptables_from_tx

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    create table #tmpcatalog
    ( TABLE_CAT  varchar (32) null)

    DECLARE jcurs_getcatalog CURSOR
    FOR select name from master..sysdatabases FOR READ ONLY
    OPEN  jcurs_getcatalog
    FETCH jcurs_getcatalog INTO  @dbname

    while (@@sqlstatus = 0)
    begin
        insert into #tmpcatalog values(@dbname)
        FETCH jcurs_getcatalog INTO @dbname
    end
    close jcurs_getcatalog
    deallocate cursor jcurs_getcatalog
    select TABLE_CAT  from #tmpcatalog order by TABLE_CAT
    drop table #tmpcatalog

    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx
go

exec sp_procxmode 'sp_jdbc_getcatalogs_cts', 'anymode'
go

grant execute on sp_jdbc_getcatalogs_cts to public
go

/*
**  End of sp_jdbc_getcatalogs_cts
*/

/* 
** sp_jdbc_getcatalogs
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_getcatalogs')
    begin
        drop procedure sp_jdbc_getcatalogs
    end
go
/** SECTION END: CLEANUP **/
 

CREATE PROCEDURE sp_jdbc_getcatalogs 
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1
    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    select TABLE_CAT=name from master..sysdatabases order by name 
go
 
exec sp_procxmode 'sp_jdbc_getcatalogs', 'anymode'
go
 
grant execute on sp_jdbc_getcatalogs to public
go

commit
go
dump transaction sybsystemprocs with truncate_only 
go

/* 
**  End of sp_jdbc_getcatalogs
*/


/*
**  sp_jdbc_primarykey
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_jdbc_primarykey')
begin
	drop procedure sp_jdbc_primarykey
end
go
/** SECTION END: CLEANUP **/

/*
** Altered from the ODBC sp_pkeys defined in sycsp11.sql.
**
** To facilitate eventually combining scripts for ODBC and JDBC,
** only the ordering of the arguments and the final select have been modified.
*/
/*
** note: there is one raiserror message: 18040
**
** messages for 'sp_jdbc_primarykey'               18039, 18040
**
** 17461, 'Object does not exist in this database.'
** 18039, 'table qualifier must be name of current database.'
** 18040, 'catalog procedure %1! can not be run in a transaction.', sp_jdbc_primarykey
**
*/

create procedure sp_jdbc_primarykey
			   @table_qualifier varchar(32 ),
			   @table_owner 	varchar(32 ),
			   @table_name		varchar(300)
as
    declare @msg varchar(255)
    declare @keycnt smallint
    declare @indexid smallint
    declare @indexname varchar(255)
    declare @i int
    declare @id int
    declare @uid smallint
    declare @actual_table_name varchar(300)
    declare @startedInTransaction bit

    if (@@trancount = 0)
    begin
        set chained off
    end

    /* see if we're in a transaction, before we try any select statements */
    if (@@trancount > 0)
        select @startedInTransaction = 1
    else 
        select @startedInTransaction = 0

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    select @actual_table_name = @table_name

    select @id = NULL

	set nocount on

	set transaction isolation level 1

        if (@startedInTransaction = 1)
            save transaction jdbc_keep_temptables_from_tx 

	if @table_qualifier is not null
	begin
		if db_name() != @table_qualifier
		begin	
			/* if qualifier doesn't match current database */
			/* 'table qualifier must be name of current database'*/
			exec sp_getmessage 18039, @msg output
			raiserror 18039 @msg 
			return (2)
		end
	end
    
    exec sp_jdbc_escapeliteralforlike @table_name

	if @table_owner is null
	begin
        select @table_owner = '%'
	end
			
	if (select count(*) from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name) = 0
	begin	
		/* 17461, 'Object does not exist in this database.' */
		exec sp_getmessage 17674, @msg output
		raiserror 17674 @msg 
		return (3)
	end

	create table #pkeys(
			 TABLE_CAT       varchar(32 ),
			 TABLE_SCHEM     varchar(32 ),
			 TABLE_NAME      varchar(255),
			 COLUMN_NAME     varchar(255),
			 KEY_SEQ         smallint,
                         PK_NAME         varchar(255))


    DECLARE jcurs_sysuserobjects CURSOR
        FOR
	    select id, uid 
        from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name
        FOR READ ONLY

    OPEN  jcurs_sysuserobjects

    FETCH jcurs_sysuserobjects INTO @id, @uid 
    
    while (@@sqlstatus = 0)
    begin
        
        /*
        **  now we search for primary key (only declarative) constraints
        **  There is only one primary key per table.
        */
    
    	select @keycnt = keycnt, @indexid = indid, @indexname = name
    	from   sysindexes
    	where  id = @id
    	and indid > 0 /* make sure it is an index */
    	and status2 & 2 = 2 /* make sure it is a declarative constr */
    	and status & 2048 = 2048 /* make sure it is a primary key */
    
        /*
        ** For non-clustered indexes, keycnt as returned from sysindexes is one
        ** greater than the actual key count. So we need to reduce it by one to
        ** get the actual number of keys.
        */
    	if (@indexid >= 2)
    	begin
    		select @keycnt = @keycnt - 1
    	end
    
    	select @i = 1
    
    	while @i <= @keycnt
    	begin
    		insert into #pkeys values
    		(db_name(), user_name(@uid), @actual_table_name,
    			index_col(@actual_table_name, @indexid, @i, @uid), @i, @indexname)
    		select @i = @i + 1
    	end
    
        /*
        ** Go to the next user/object
        */
        FETCH jcurs_sysuserobjects INTO @id, @uid 
    end

    close jcurs_sysuserobjects
    deallocate cursor jcurs_sysuserobjects

    /*
    ** Original ODBC query:
    **
	** select table_qualifier, table_owner, table_name, column_name, key_seq
	** from #pkeys
	** order by table_qualifier, table_owner, table_name, key_seq
    */
    /*
    ** Primary keys are not explicitly named, so name is always null.
    */
    select  TABLE_CAT,
            TABLE_SCHEM,
            TABLE_NAME,
            COLUMN_NAME,
            KEY_SEQ,
            PK_NAME
	from #pkeys
	order by COLUMN_NAME
    
    drop table #pkeys

    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx 

	return (0)
go
exec sp_procxmode 'sp_jdbc_primarykey', 'anymode'
go
grant execute on sp_jdbc_primarykey to public
go
use sybsystemprocs 
go

/*
**  End of sp_jdbc_primarykey
*/



/*
**  sp_sql_type_name
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_sql_type_name')
begin
        drop procedure sp_sql_type_name
end
go
/** SECTION END: CLEANUP **/
 
/*
**  Implements RSMDA.getColumnTypeName
**  create a procedure that will query 
**  spt_jdbc_datatype_info for the correct jdbc mapped datatype or
**  the datasource specific systable, to retrieve the correct type
**  or user defined datatype name, based on the parameters
**  @datatype = the protocol datatype value
**  @usrtype = the data source specifc user defined datatype value
*/
create procedure sp_sql_type_name
        @datatype  tinyint,
        @usrtype   smallint
as
BEGIN

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

/* Special case for types numericn, decimaln, daten and timen.
** They do not seem to have the correct mapping of usertype & datatype
*/
   /* if type is decimaln(106) map to decimal(55)
    * if type is numericn(108) map to numeric(63) 
    * if type is daten (123) map to date (49)
    * if type is timen (147) map to time (51)
    */
   if (@datatype = 108)
   begin
	select @datatype = 63
   end
   else if (@datatype = 106)
   begin
	select @datatype = 55
   end
   else if (@datatype = 123)
   begin
	select @datatype = 49
   end
   else if (@datatype = 147)
   begin
	select @datatype = 51
   end
 
   /* if a usertype is greater than 100 that means it is a
    * user defined datatype, and it needs to be reference in
    * the datasource specific systype table.  If they are
    * user-defined numeric/decimal, then only use the usertype
    * for the search criteria (see the note on SPECIAL CASE below)
    * This is the fix for Bug 192969.
    */
   if (@usrtype > 100) 
   begin
	 select name from systypes
	    where usertype = @usrtype
   end
   /* check if we have the special case of a usertype signaling
    * UNICHAR (34) or UNIVARCHAR (35)
    */
   else if (@usrtype = 34 or @usrtype = 35)
   begin
       select name from systypes
         where usertype = @usrtype
   end
   /* simply check spt_jdbc_datatype_info for 
    * the predefined jdbc mapping for the types
    */
   else
   begin
       select j.type_name as name 
       from sybsystemprocs.dbo.spt_jdbc_datatype_info j
       where j.ss_dtype = @datatype
   end
END
go
/* end of sp_sql_type_name */
exec sp_procxmode 'sp_sql_type_name', 'anymode'
go
grant execute on sp_sql_type_name to public
go
commit
go
dump transaction sybsystemprocs with truncate_only 
go


/*
**  End of sp_sql_type_name
*/



/*
**  sp_jdbc_getbestrowidentifier
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select *
	from sysobjects where name = 'sp_jdbc_getbestrowidentifier')
begin
	drop procedure sp_jdbc_getbestrowidentifier
end
go
/** SECTION END: CLEANUP **/


/* Get a description of a table's optimal set of columns that uniquely 
** identifies a row
** Usually it's the unique primary key index column or the identity field
*/

create procedure sp_jdbc_getbestrowidentifier (
				 @table_qualifier	varchar(32 ) = null,
				 @table_owner		varchar(32 ) = null,
				 @table_name		varchar(255),
				 @scope			int,
				 @nullable		smallint)
as
	declare @indid              int
	declare @table_id           int
	declare @dbname             varchar(32 )
	declare @owner              varchar(32 )
	declare @full_table_name    varchar(765)
	declare @msg                varchar(765)

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

        /* this will make sure that all rows are sent even if
        ** the client "set rowcount" is differect
        */

        set rowcount 0


        if exists (select * from sysobjects where name = '#bestinfo')
        begin
   	    drop table #bestinfo
        end
        create table #bestinfo (
            SCOPE smallint, COLUMN_NAME varchar(255),
            DATA_TYPE smallint, TYPE_NAME varchar(255),
            COLUMN_SIZE int, BUFFER_LENGTH varchar(255),
            DECIMAL_DIGITS smallint, PSEUDO_COLUMN smallint)

	/* get database name */
	select @dbname = db_name()

	/* we don't want a temp table unless we're in tempdb */
       /* Adding tempdb check here depending on the ASE version ADDTEMPDB */

   if (@table_name like '#%' and db_name() != db_name(tempdb_id()))
	begin	
		exec sp_getmessage 17676, @msg output
		raiserror 17676 @msg
		return (1)
	end

	if @table_qualifier is not null
	begin
		/* if qualifier doesn't match current database */
		if @dbname != @table_qualifier
		begin	
			exec sp_getmessage 18039, @msg output
			raiserror 18039 @msg
			return (1)
		end
	end

    if (@table_owner is null) 
    begin
        select @table_owner ='%'
    end
    else
    begin
        
        if (charindex('%',@table_owner) > 0)
        begin
            exec sp_getmessage 17993, @msg output
            raiserror 17993 @msg, @table_owner
            return(1)
        end
        
        /*
        ** if there is a '_' character in @table_owner, 
        ** then we need to make it work literally in the like
        ** clause.
        */
        if (charindex('_', @table_owner) > 0)
        begin
            exec sp_jdbc_escapeliteralforlike
                @table_owner output
        end
    end
    
    
    if (@table_name is null) 
    begin
       exec sp_getmessage 17993, @msg output
       raiserror 17993 @msg, 'NULL'
       return(1)
    end
    
    if ((select count(*) 
        from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name) = 0)
    begin
      exec sp_getmessage 17674, @msg output
      raiserror 17674 @msg, @table_name
      return
    end

    declare owner_cur cursor for 
    	select @table_owner = user_name(uid) from sysobjects 
    		where name like @table_name ESCAPE '\' 
                and user_name(uid) like @table_owner ESCAPE '\' 
    open owner_cur
    fetch owner_cur into @owner
    while (@@sqlstatus = 0)
    begin
        select @full_table_name = @owner + '.' + @table_name

        /* get object ID */
        select @table_id = object_id(@full_table_name)

        /* ROWID, now find the id of the 'best' index for this table */

        select @indid = (
            select min(indid)
            from sysindexes
            where
                id = @table_id
                and indid > 0)		/* eliminate table row */
        
        /* Sybase's only PSEUDO_COLUMN is called SYB_IDENTITY_COL and */
        /* is only generated when dboption 'auto identity' is set on */
        if exists (select name from syscolumns where id=@table_id and name =
            'SYB_IDENTITY_COL')
        begin
            insert into #bestinfo values (
                convert(smallint, 0), 'SYB_IDENTITY_COL', 2, 'NUMERIC', 10,
                'not used', 0, 2)
        end
        else
        begin
            insert into #bestinfo 
	    select
                convert(smallint, 0),index_col(@full_table_name,indid,c.colid),
                d.data_type + convert(smallint, isnull(d.aux,
                        ascii(substring('666AAA@@@CB??GG',
                        2*(d.ss_dtype%35+1)+2-8/c2.length,1))
                        -60)),
                rtrim(substring(d.type_name, 1 + isnull(d.aux,
                        ascii(substring('III<<<MMMI<<A<A',
                        2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
                        -60), 18)),
                isnull(d.data_precision, convert(int,c2.length))
                        + isnull(d.aux, convert(int,
                        ascii(substring('???AAAFFFCKFOLS',
                        2*(d.ss_dtype%35+1)+2-8/c2.length,1))
                        -60)),
                'not used',
                    /*isnull(d.length, convert(int,c2.length))
                        + convert(int, isnull(d.aux,
                        ascii(substring('AAA<BB<DDDHJSPP',
                        2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
                        -64)),*/
                isnull(d.numeric_scale, convert(smallint,
                        isnull(d.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
                        -60))),
                1
	    from
            sysindexes x,
            syscolumns c,
            sybsystemprocs.dbo.spt_jdbc_datatype_info d,
            systypes t,
            syscolumns c2	/* self-join to generate list of index
                    ** columns and to extract datatype names */
            where
            x.id = @table_id
            and c2.name = index_col(@full_table_name, @indid,c.colid)
            and c2.id =x.id
            and c.id = x.id
            and c.colid < keycnt + (x.status & 16) / 16
            and x.indid = @indid
            and c2.type = d.ss_dtype
            and c2.usertype *= t.usertype
        end

        fetch owner_cur into @owner
    end
    select * from #bestinfo
    drop table #bestinfo
    return (0)
go
exec sp_procxmode 'sp_jdbc_getbestrowidentifier', 'anymode'
go
grant execute on sp_jdbc_getbestrowidentifier to public
go
commit
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_getbestrowidentifier
*/

/**
 * sp_jdbc_getisolationlevels
 */
 
/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs
go

if exists (select * from sysobjects where name = 'sp_jdbc_getisolationlevels')
begin
    drop procedure sp_jdbc_getisolationlevels
end
go
/** SECTION END: CLEANUP **/

/**
 * <P> This procedure is used to determine which transaction isolation
 * levels are supported by this ASE server.  This proc is registered
 * with the spt_mda table to be executed when the user calls:
 * <CODE> DatabaseMetaData.supportsTransactionIsolationLevel(int) </CODE>.
 * If the int specified is found in the row returned by this procedure,
 * then that level is supported.  The levels are indicated by using the
 * integer mappings found in the java.sql.Connection interface.
 * <UL> All ASE versions currently support these levels:
 *              <LI> TRANSACTION_SERIALIZABLE  (8) and
 *              <LI> TRANSACTION_READ_COMMITTED  (2)            </UL>
 * <UL> ASE versions after 10.1 added support for these levels:
 *              <LI>  TRANSACTION_READ_UNCOMMITTED (1).         </UL>
 * <P> This procedure accesses the @@version string, determines the
 * version of ASE, and returns the appropriate levels.
 * <P> WARNING:  Should future versions of ASE support more transaction
 * isolation levels (e.g., TRANSACTION_REPEATABLE_READ (4)), this proc
 * must be modified.
 */
 
create procedure sp_jdbc_getisolationlevels as

    declare
      @startVersion    int,         /* index of version # in @@version    */
      @versionNum      varchar(20), /* whole version number (eg 11.5.1)   */
      @versionFloat    float,       /* major & minor ver # (eg 11.5)      */
      @minorVersion    varchar(15), /* minor version (eg 5.1)             */
      @earliestVersion float,       /* this ver supports READ_UNCOMMITTED */
      @firstDecimal    int,         /* index of 1st decimal point         */
      @secondDecimal   int,         /* index of 2nd decimal point         */
      @endVersion      int	    /* index of end of version number     */

    /* server must be at least 10.1.x to support levels 8, 2, AND 1. */
    select @earliestVersion = 10.1  

    /* find where the version number is in this mess of characters */
    select @startVersion = patindex('%/[0-9]%.%[0-9]/%', @@version) +1

    /* could not find version number in expected format within @@version */
    if (@startVersion <= 1)
    begin
	select 0 /* returning TRANSACTION_NONE */
	return 2
    end

    select @versionNum = substring(@@version, @startVersion, 20)
        
    /* Find the first decimal point in this version number */
    select @firstDecimal = charindex('.', @versionNum)
    
    /* extract the minor version and any "sub-minor" version (eg 5.1) */
    select @minorVersion = substring(@versionNum, @firstDecimal + 1, 15)

    /* Find the second decimal point in this version number */
    /* if none found, then "pretend" to have one at the end */
    /* of the version number (where the "/" is)             */

    select @secondDecimal = charindex('.',@minorVersion)
    select @endVersion = charindex('/',@minorVersion)
    if ((@secondDecimal = 0) or (@endVersion < @secondDecimal))
       select @secondDecimal = @endVersion

    /* Compute major and minor versions as a float (eg "11.5" --> 11.5F) */
    select @versionFloat = convert(float, substring(@versionNum, 1,
                                           @secondDecimal+@firstDecimal - 1))
    
    if (@versionFloat >= @earliestVersion)
       select 8,2,1
    else
       select 8,2
   
    return (0)   
go

exec sp_procxmode 'sp_jdbc_getisolationlevels', 'anymode'
go

grant execute on sp_jdbc_getisolationlevels to public
go

commit
go


/*
**  sp_jdbc_getindexinfo
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select *
	from sysobjects
		where name = 'sp_jdbc_getindexinfo')
begin
	drop procedure sp_jdbc_getindexinfo
end
go
/** SECTION END: CLEANUP **/


/* getindexinfo returns information on the indexes of a page
** is unique is set to TRUE only indexes on indexes where it's value's must
** be unique are returned.
** garantee alwys accurate data
*/
create procedure sp_jdbc_getindexinfo (
	@table_qualifier	varchar(32 ) = NULL,
	@table_owner		varchar(32 ) = NULL,
	@table_name		varchar(255),
	@unique			varchar(5) ,
	@approximate 		char(5))
as
    declare @indid              int
    declare @lastindid          int
    declare @full_table_name    varchar(765)
    declare @msg                varchar(250)
    declare @tableid            int
    declare @startedInTransaction bit

    if (@@trancount = 0)
    begin
        set chained off
    end 

    /* see if we are already in a transaction */
    if (@@trancount > 0)
        select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

    /* this will make sure that all rows are sent even if
    ** the client "set rowcount" is differect
    */

    set rowcount 0

    /*
    ** Verify table qualifier is name of current database.
    */
    if @table_qualifier is not null
    begin
    	if db_name() != @table_qualifier
    	begin	/* If qualifier doesn't match current database */
    		/*
    		** 18039, 'Table qualifier must be name of current database.'
    		*/
    		exec sp_getmessage 18039, @msg output
    		raiserror 18039 @msg
    		return (1)
    	end
    end
    select @table_qualifier = db_name()
    
    set transaction isolation level 1
    
    if (@startedInTransaction = 1)
        save transaction jdbc_keep_temptables_from_tx 
     
    if (@table_owner is null)
    begin
        select @table_owner ='%'
    end
    
    if (@table_name is null) 
    begin
       exec sp_getmessage 17993, @msg output
       raiserror 17993 @msg, 'NULL'
       return(1)
    end

    if ((select count(*) 
        from sysobjects 
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name) = 0)
    begin
        exec sp_getmessage 17674, @msg output
        raiserror 17674 @msg
        return
    end

    create table #TmpIndex(
    	TABLE_CAT       varchar(32 ),
    	TABLE_SCHEM     varchar(32 ),
    	TABLE_NAME      varchar(255),
    	INDEX_QUALIFIER varchar(32 ) null,
    	INDEX_NAME      varchar(255) null,
    	NON_UNIQUE      varchar(5),
    	TYPE            smallint,
    	ORDINAL_POSITION smallint null,
    	COLUMN_NAME     varchar(255) null,
    	ASC_OR_DESC     char(1) null,
    	index_id	int null,
    	CARDINALITY     int null,
    	PAGES           int null,
    	FILTER_CONDITION varchar(32 ) null,
    	status		smallint,
        table_id    int)


    DECLARE jcurs_sysuserobjects CURSOR
        FOR
	    select id
        from sysobjects
        where user_name(uid) like @table_owner ESCAPE '\'
        and name = @table_name
        FOR READ ONLY

    OPEN  jcurs_sysuserobjects

    FETCH jcurs_sysuserobjects INTO @tableid 
    
    while (@@sqlstatus = 0)
    begin
        /*
        ** build the full_table_name for use below in 
        ** obtaining the index column via the INDEX_COL()
        ** internal function
        */
        select @full_table_name = user_name(uid) + '.' + name
        from sysobjects
        where id = @tableid

        /*
        ** Start at lowest index id, while loop through indexes. 
        ** Create a row in #TmpIndex for every column in sysindexes, each is
        ** followed by an row in #TmpIndex with table statistics for the preceding
        ** index.
        */
        select @indid = min(indid)
        	from sysindexes
        	where id = @tableid
       		and indid > 0
       		and indid < 255

        while @indid is not NULL
        begin
        	insert #TmpIndex	/* Add all columns that are in index */
        	select
        		db_name(),		/* table_qualifier */
        		user_name(o.uid),	/* table_owner	   */
        		o.name,			/* table_name	   */
        		o.name, 		/* index_qualifier */
        		x.name,			/* index_name	   */
        		'FALSE',		/* non_unique	   */
        		1,			/* SQL_INDEX_CLUSTERED */
        		colid,			/* seq_in_index	   */
        		INDEX_COL(@full_table_name,indid,colid),/* column_name	   */
        		'A',			/* collation	   */
        		@indid,			/* index_id 	   */
/* Server dependent stored procedure add here ADDPOINT_ROWCOUNT*/
                        row_count(db_id(), x.id), /* cardinality        */
                        data_pages(db_id(), x.id,
                                    case
                                        when x.indid = 1
                                            then 0
                                    else x.indid
                                    end),   /* pages           */

        		null,			/* Filter condition not available */
        					/* in SQL Server*/
        		x.status, 		/* Status */	
                @tableid    /* table id, internal use for updating the non_unique field */
        	from sysindexes x, syscolumns c, sysobjects o
        	where x.id = @tableid
        		and x.id = o.id
        		and x.id = c.id
        		and c.colid < keycnt+(x.status&16)/16
        		and x.indid = @indid
        
            /*
            ** only update the inserts for the current
            ** owner.table
            */
            update #TmpIndex
                set NON_UNIQUE = 'TRUE'
                where status&2 != 2 /* If non-unique index */
                and table_id = @tableid
    
        	/*
        	** Save last index and increase index id to next higher value.
        	*/
        	select @lastindid = @indid
        	select @indid = NULL
        
        	select @indid = min(indid)
        	from sysindexes
        	where id = @tableid
        		and indid > @lastindid
        		and indid < 255
        end
        
        /* 
        ** Now add row with table statistics 
        */
        insert #TmpIndex
        	select
        		db_name(),		/* table_qualifier */
        		user_name(o.uid),	/* table_owner	   */
        		o.name, 		/* table_name	   */
        		null,			/* index_qualifier */
        		null,			/* index_name	   */
        		'FALSE',		/* non_unique	   */
        		0,			/* SQL_table_STAT  */
        		null,			/* seq_in_index	*/
        		null,			/* column_name	   */
        		null,			/* collation	   */
        		0,			/* index_id 	   */
/* Server dependent stored procedure add here ADDPOINT_ROWCOUNT*/
                        row_count(db_id(), x.id), /* cardinality        */
                        data_pages(db_id(), x.id,
                                    case
                                        when x.indid = 1
                                            then 0
                                    else x.indid
                                    end),   /* pages           */

        		null,			/* Filter condition not available */
        					/* in SQL Server*/
        		0,			/* Status */
                @tableid    /* tableid */
        	from sysindexes x, sysobjects o
        	where o.id = @tableid
        		and x.id = o.id
        		and (x.indid = 0 or x.indid = 1)	
        	/*  
        	** If there are no indexes
        	** then table stats are in a row with indid = 0
        	*/

        /*
        ** Go to the next user/object
        */
        FETCH jcurs_sysuserobjects INTO @tableid 
    end

    close jcurs_sysuserobjects
    deallocate cursor jcurs_sysuserobjects

    update #TmpIndex
        set
            TYPE = 3,		/* SQL_INDEX_OTHER */
            CARDINALITY = NULL,
            PAGES = NULL
        where index_id > 1		/* If non-clustered index */
           
    if (@unique!='1')
    begin
    	/* If all indexes desired */
    	select
    		TABLE_CAT,
    		TABLE_SCHEM,
    		TABLE_NAME,
    		NON_UNIQUE,
    		INDEX_QUALIFIER,
    		INDEX_NAME,
    		TYPE,
    		ORDINAL_POSITION,
    		COLUMN_NAME,
    		ASC_OR_DESC,
    		CARDINALITY,
    		PAGES,
    		FILTER_CONDITION			
    	from #TmpIndex
    	order by NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION
    end
    else	
    begin
    	/* else only unique indexes desired */
    	select
    		TABLE_CAT,
    		TABLE_SCHEM,
    		TABLE_NAME,
    		NON_UNIQUE,
    		INDEX_QUALIFIER,
    		INDEX_NAME,
    		TYPE,
    		ORDINAL_POSITION,
    		COLUMN_NAME,
    		ASC_OR_DESC,
    		CARDINALITY,
    		PAGES,
    		FILTER_CONDITION
    	from #TmpIndex
    	where NON_UNIQUE = 'FALSE' 	
    	order by NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION
    
    end
    
    drop table #TmpIndex

    if (@startedInTransaction = 1)
        rollback transaction jdbc_keep_temptables_from_tx 
  
    return (0)

go

exec sp_procxmode 'sp_jdbc_getindexinfo', 'anymode'
go
grant execute on sp_jdbc_getindexinfo to public
go
commit
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_getindexinfo
*/


/*
**  sp_jdbc_stored_procedures
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects
		where name = 'sp_jdbc_stored_procedures')
begin
	drop procedure sp_jdbc_stored_procedures
end
go
/** SECTION END: CLEANUP **/


/*
** Altered from the ODBC sp_jdbc_procedures defined in sycsp11.sql.
**
** New column 'PROCEDURE_TYPE' was added to support JDBC spec. This
** column is to indicate if the procedure returns a result. If 0,
** column will be evalued as DatabaseMetadata.procedureResultUnknown;
** this means that the procedure MAY return a result.
*/
/*
** Messages for 'sp_jdbc_stored_procedures'	18041
**
** 18041, 'Stored Procedure qualifier must be name of current database.'
**
*/
create procedure sp_jdbc_stored_procedures
@sp_qualifier	varchar(32 ) = null,	/* stored procedure qualifier; 
					** For the SQL Server, the only valid
					** values are NULL or the current 
					** database name
					*/
@sp_owner	varchar(771) = null,	/* stored procedure owner */
@sp_name	varchar(771) = null	/* stored procedure name */
as

declare	@msg	varchar(90)
declare @uid   int
declare @protecttype tinyint
declare @id  int
declare @action    smallint
declare @number smallint
declare @sequence int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* this will make sure that all rows are sent even if
** the client "set rowcount" is differect
*/

set rowcount 0



/* If qualifier is specified */
if @sp_qualifier is not null
begin
	/* If qualifier doesn't match current database */
	if db_name() != @sp_qualifier
	begin
		/* If qualifier is not specified */
		if @sp_qualifier = ''
		begin
			/* in this case, we need to return an empty 
			** result set because the user has requested a 
			** database with an empty name 
			*/
			select @sp_name = ''
			select @sp_owner = ''
		end

		/* qualifier is specified and does not match current database */
		else
		begin	
			/* 
			** 18041, 'Stored Procedure qualifer must be name of
			** current database'
			*/
			exec sp_getmessage 18041, @msg out
			raiserror 18041 @msg
			return (1)
		end
	end
end

/* If procedure name not supplied, match all */
if @sp_name is null
begin  
	select @sp_name = '%'
end

/* If procedure owner not supplied, match all */
if @sp_owner is null	
	select @sp_owner = '%'

/* 
** Retrieve the stored procedures and associated info on them
*/
/*

** get rows for public, current users, user's groups
*/
    
    create table #jsysprotects
    (uid int not null,
     protecttype tinyint not null,
     id  int not null,
     action     smallint not null
    )

    begin
        declare jsysprotects_cur1 cursor for
        select p.uid, p.protecttype, p.id, p.action
        from sysprotects p, sysusers u
        where action in (193,224)
        and (p.uid = 0         /* get rows for public */
        or p.uid = user_id()    /* current user */
        or p.uid = u.gid)     /* users group */
    open jsysprotects_cur1
    fetch jsysprotects_cur1 into @uid,@protecttype,@id,@action
    while (@@sqlstatus = 0)
        begin
           insert into #jsysprotects
           values(@uid,@protecttype,@id,@action)
           fetch jsysprotects_cur1 into @uid,@protecttype,@id,@action
    end
    deallocate cursor jsysprotects_cur1
    end

    create table #jsysprocedures
    (number   smallint  not null,
     sequence int not null,
     id  int not null
    )
    begin
    declare jsysprotects_cur2 cursor for
    select number,sequence,id
       from sysprocedures p 
        where sequence = 0    
    open jsysprotects_cur2
    fetch jsysprotects_cur2 into @number,@sequence,@id
    while (@@sqlstatus = 0)
        begin
           insert into #jsysprocedures
           values(@number,@sequence,@id)
           fetch jsysprotects_cur2 into @number,@sequence,@id
    end
    deallocate cursor jsysprotects_cur2
    end    

select  PROCEDURE_CAT = db_name(),
	PROCEDURE_SCHEM = user_name(o.uid),
	PROCEDURE_NAME = o.name +';'+ ltrim(str(p.number,5)),
	num_input_params = -1,		/* Constant since value unknown */
	num_output_params = -1,	        /* Constant since value unknown */
	num_result_sets = -1,		/* Constant since value unknown */
	REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
	PROCEDURE_TYPE = 0
from sysobjects o, #jsysprocedures p,sysusers u
where o.name like @sp_name ESCAPE '\'
	and user_name(o.uid) like @sp_owner ESCAPE '\'
	and o.type = 'P'		/* Object type of Procedure */
	and p.id = o.id
	and u.uid = user_id()		/* constrain sysusers uid for use in 
					** subquery 
					*/

	and (suser_id() = 
             (select uid from sysusers where suid = suser_id()) /* User is the System Administrator */
	     or  o.uid = user_id()	/* User created the object */
					/* here's the magic..select the highest 
					** precedence of permissions in the 
					** order (user,group,public)  
					*/

	     /*
	     ** The value of protecttype is
	     **
	     **		0  for grant with grant
	     **		1  for grant and,
	     **		2  for revoke
	     **
	     ** As protecttype is of type tinyint, protecttype/2 is
	     ** integer division and will yield 0 for both types of
	     ** grants and will yield 1 for revoke, i.e., when
	     ** the value of protecttype is 2.  The XOR (^) operation
	     ** will reverse the bits and thus (protecttype/2)^1 will
	     ** yield a value of 1 for grants and will yield a
	     ** value of zero for revoke.
	     **
	     ** Normal uids have values upto 16383, roles have uids
	     ** from 16384 upto 16389 and uids of groups start from
	     ** 16390 onwards.
	     **
	     ** If there are several entries in the sysprotects table
	     ** with the same Object ID, then the following expression
	     ** will prefer an individual uid entry over a group entry
	     ** and prefer a group entry over a role entry.
	     **
	     ** For example, let us say there are two users u1 and u2
	     ** with uids 4 and 5 respectiveley and both u1 and u2
	     ** belong to a group g12 whose uid is 16390.  procedure p1
	     ** is owned by user u0 and user u0 performs the following
	     ** actions:
	     **
	     **		grant exec on p1 to g12
	     **		revoke grant on p1 from u1
	     **
	     ** There will be two entries in sysprotects for the object
	     ** p1, one for the group g12 where protecttype = grant (1)
	     ** and one for u1 where protecttype = revoke (2).
	     **
	     ** For the group g12, the following expression will
	     ** evaluate to:
	     **
	     **		(((+)*abs(16390-16383))*2) + ((1/2)^1))
	     **		= ((14) + (0)^1) = 14 + 1 = 15
	     **
	     ** For the user entry u1, it will evaluate to:
	     **
	     **		(((+)*abs(4-16383)*2) + ((2/2)^1))
	     **		= ((abs(-16379)*2 + (1)^1)
	     **		= 16379*2 + 0 = 32758
	     **
	     ** As the expression evaluates to a bigger number for the
	     ** user entry u1, select max() will chose 32758 which,
	     ** ANDed with 1 gives 0, i.e., sp_jdbc_stored_procedures will
	     ** not display this particular procedure to the user.
	     **
	     ** When the user u2 invokes sp_jdbc_stored_procedures, there is
	     ** only one entry for u2, which is the entry for the group
	     ** g12, and so this entry will be selected thus allowing
	     ** the procedure in question to be displayed.
	     **
	     ** Notice that multiplying by 2 makes the number an
	     ** even number (meaning the last digit is 0) so what
	     ** matters at the end is (protecttype/2)^1.
	     **
	     */

	     or ((select max(((sign(uid)*abs(uid-16383))*2)
			     + ((protecttype/2)^1))
		   from #jsysprotects p
		   where p.id = o.id		/* outer join to correlate 
						** with all rows in sysobjects 
						*/
		   )&1 			/* more magic...normalize GRANT */
	    	  ) = 1) 		/* final magic...compare Grants	*/
order by PROCEDURE_SCHEM, PROCEDURE_NAME
drop table #jsysprotects
drop table #jsysprocedures
go
exec sp_procxmode 'sp_jdbc_stored_procedures', 'anymode'
go
grant execute on sp_jdbc_stored_procedures to public
go
commit
go
dump transaction sybsystemprocs with truncate_only 
go


/*
**  End of sp_jdbc_stored_procedures
*/



/*
**  sp_jdbc_getprocedurecolumns
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_getprocedurecolumns')
    begin
        drop procedure sp_jdbc_getprocedurecolumns
    end
go
/** SECTION END: CLEANUP **/


create procedure sp_jdbc_getprocedurecolumns (
@sp_qualifier   varchar(32 ) = null,     /* stored procedure qualifier*/
@sp_owner       varchar(32 ) = null,     /* stored procedure owner */
@sp_name        varchar(771),            /* stored procedure name */
@column_name    varchar(771) = null)
as
declare @msg 			varchar(250)
declare @group_num              int
declare @semi_position          int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
/* this will make sure that all rows are sent even if
** the client "set rowcount" is differect
*/

set rowcount 0



if @sp_qualifier is not null
begin
	if db_name() != @sp_qualifier
	begin
		if @sp_qualifier = ''
		begin
			select @sp_name = ''
			select @sp_owner = ''
		end
		else
		begin	
			/* 
			** 18041, 'Stored Procedure qualifer must be name of
			** current database'
			*/
			exec sp_getmessage 18041, @msg out
			raiserror 18041 @msg
			return (1)
		end
	end
end
else
	select @sp_qualifier = db_name()

select @semi_position = charindex(';',@sp_name)
if (@semi_position > 0)
begin   /* If group number separator (;) found */
    select @group_num = convert(int,substring(@sp_name, @semi_position + 1, 2))
    select @sp_name = substring(@sp_name, 1, @semi_position -1)
end
else
begin   /* No group separator, so default to group number of 1 */
    select @group_num = 1
end      

if (@sp_owner is null) select @sp_owner ='%'
if (@sp_name is null) select @sp_name ='%'
if (@column_name is null) select @column_name ='%'

/*
 * build a temporary table for holding the results.
 * The following is from the JDBC specification at
 * DatabaseMetaData.getProcedureColumns
 */
create table #jproccols_res
    (PROCEDURE_CAT   varchar(32 )  null,
     PROCEDURE_SCHEM varchar(32 )  null,
     PROCEDURE_NAME  varchar(255)  not null,
     COLUMN_NAME     varchar(255)  not null,
     COLUMN_TYPE     smallint     not null, 
     DATA_TYPE       smallint     not null,
     TYPE_NAME       varchar(255)  not null,
     "PRECISION"     int          not null,
     LENGTH          int          not null,
     SCALE           smallint     not null, 
     RADIX           smallint     not null, 
     NULLABLE        smallint     not null,
     REMARKS         varchar(255) null,
     colid           int          not null /* hidden, used for ordering */
    )

/*
 * insert defined parameters (if any)
 */
INSERT INTO #jproccols_res
SELECT DISTINCT
    PROCEDURE_CAT   = db_name(),
    PROCEDURE_SCHEM = user_name(o.uid),
    PROCEDURE_NAME  = (select object_name(p.id) + ';' + ltrim(str(p.number,5)) 
                        from sysprocedures p where p.id = o.id and p.number = @group_num 
                        group by p.id,p.number),
    COLUMN_NAME      = c.name,
/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ADDPOINT_COL_TYPE */

                    /* Note that that ASE 12.5+ places a 2 in 
                       syscolumns.status2 (to signify an out-only param) when
                       a parameter is declared as an output param in a 
                       Transact-SQL stored proc. This is despite the fact that
                       a TSQL out param can be used for both input and output
                       values. The reason for this is that the status2 column
                       value is based on the text used to create the
                       procedure.
                       SQLJ procedures *do* have out-only params, as well as
                       inout params. Therefore, the status2 column for SQLJ
                       proc params will accurately reflect the paramter usage.
                       In any case, the below COLUMN_TYPE code accounts for
                       these quirks by differentiating between SQLJ procs
                       (the case branch with the 0x2000000 in it) and TSQL 
                       procs. */

    COLUMN_TYPE     = case 
                       when c.status2 is NULL then 0
                       when (o.sysstat2 & hextoint('0x2000000') != 0) then
                           (ascii(substring('AD>B>>>E', c.status2, 1)) -64)
                       else (ascii(substring('AB>B>>>E', c.status2, 1))
                       - 64)
                      end,


    DATA_TYPE       = jdt.data_type,
    TYPE_NAME       = 
                        case
                            when t.name = 'usmallint' then 'unsigned smallint'
                            when t.name = 'uint' then 'unsigned int'
                            when t.name = 'ubigint' then 'unsigned bigint'
                        else
                            t.name
                        end,
    'PRECISION'     = (isnull(convert(int, c.prec),
                      isnull(convert(int, jdt.data_precision),
                      convert(int, c.length)))
                      +isnull(jdt.aux, convert(int,
                      ascii(substring('???AAAFFFCKFOLS',
                      2*(jdt.ss_dtype%35+1)+2-8/c.length,1))-60))),    
    LENGTH          = (isnull(convert(int, c.length), 
                      convert(int, jdt.length)) +
                      convert(int, isnull(jdt.aux,
                      ascii(substring('AAA<BB<DDDHJSPP',
                      2*(jdt.ss_dtype%35+1)+2-8/c.length,
                      1))-64))),
    SCALE           = (isnull(isnull(convert(smallint, c.scale), 
                       convert(smallint, jdt.numeric_scale)), 0) +
                        convert(smallint, isnull(jdt.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(jdt.ss_dtype%35+1)+2-8/c.length,
                        1))-60))),    
    RADIX           = convert(smallint, 0), 
    NULLABLE        = convert(smallint, 2),  /* procedureNullableUnknown */
    REMARKS         = c.printfmt,
    colid           = c.colid /* parameter position order */
FROM syscolumns c, sysobjects o,
     sybsystemprocs.dbo.spt_jdbc_datatype_info jdt, systypes t
WHERE jdt.ss_dtype = c.type 
    and t.type = jdt.ss_dtype
    and c.usertype = t.usertype
    and c.id = o.id
    and user_name(o.uid) like @sp_owner ESCAPE '\'
    and o.type ='P'
    and o.name like @sp_name ESCAPE '\'
    and c.name like @column_name ESCAPE '\'
    and c.number = @group_num


/*
 * add the 'return parameter'
 */
INSERT INTO #jproccols_res    
SELECT DISTINCT
    PROCEDURE_CAT   = db_name(),
    PROCEDURE_SCHEM = user_name(o.uid),
    PROCEDURE_NAME  = (select object_name(p.id) + ';' + ltrim(str(p.number,5)) 
                        from sysprocedures p where p.id = o.id and p.number = @group_num 
                        group by p.id,p.number),
    COLUMN_NAME     = 'RETURN_VALUE',
    COLUMN_TYPE     = convert(smallint, 5), /* procedureColumnReturn */
    DATA_TYPE       = jdt.data_type,
    TYPE_NAME       = jdt.type_name,
    'PRECISION'     = (isnull(convert(int, jdt.data_precision),
                      convert(int, jdt.length))
                      +isnull(jdt.aux, convert(int,
                      ascii(substring('???AAAFFFCKFOLS',
                      2*(jdt.ss_dtype%35+1)+2-8/jdt.length,1))-60))),    
    LENGTH          = (isnull(jdt.length, convert(int, t.length)) +
                      convert(int, isnull(jdt.aux,
                      ascii(substring('AAA<BB<DDDHJSPP',
                      2*(jdt.ss_dtype%35+1)+2-8/t.length,
                      1))-64))),
    SCALE           = (convert(smallint, jdt.numeric_scale) +
                        convert(smallint, isnull(jdt.aux,
                        ascii(substring('<<<<<<<<<<<<<<?',
                        2*(jdt.ss_dtype%35+1)+2-8/jdt.length,
                        1))-60))),    
    RADIX           = convert(smallint, 0), 
    NULLABLE        = convert(smallint, 0), /* procedureNoNulls */
    REMARKS         = 'procedureColumnReturn',
    colid           = 0 /* always the first parameter */
FROM sybsystemprocs.dbo.spt_jdbc_datatype_info jdt,
     sysobjects o,systypes t
WHERE jdt.ss_dtype = 56 /* return parameter is an int */
    and t.type = jdt.ss_dtype
    and user_name(o.uid) like @sp_owner ESCAPE '\'
    and o.type ='P'
    and o.name like @sp_name ESCAPE '\'
    and 'RETURN_VALUE' like @column_name ESCAPE '\'


/*
 * return the data to the client
 */
SELECT PROCEDURE_CAT, PROCEDURE_SCHEM, PROCEDURE_NAME, COLUMN_NAME,
    COLUMN_TYPE, DATA_TYPE, TYPE_NAME, "PRECISION", LENGTH, SCALE,
    RADIX, NULLABLE, REMARKS
FROM #jproccols_res
ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, colid

/* 
 * cleanup
 */
DROP TABLE #jproccols_res
go

exec sp_procxmode 'sp_jdbc_getprocedurecolumns', 'anymode'
go
grant execute on sp_jdbc_getprocedurecolumns to public
go
commit
go

/*
**  End of sp_jdbc_getprocedurecolumns
*/


/*
**  sp_jdbc_getversioncolumns
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name = 'sp_jdbc_getversioncolumns')
begin
	drop procedure sp_jdbc_getversioncolumns
end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_getversioncolumns (
				 @table_qualifier	varchar(32 ) = null,
				 @table_owner		varchar(32 ) = null,
				 @table_name		varchar(255))
as
	declare @indid			int
	declare @table_id		int
	declare @dbname			varchar(32 )
	declare @full_table_name	varchar(765)
	declare @msg			varchar(765)
	declare @owner			varchar(32 )

create table #versionhelp (SCOPE smallint null, COLUMN_NAME varchar(255) null,
DATA_TYPE int null, TYPE_NAME varchar(8) null, COLUMN_SIZE int null,
BUFFER_LENGTH smallint null, DECIMAL_DIGITS smallint null,  
PSEUDO_COLUMN smallint null)

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

        /* this will make sure that all rows are sent even if
        ** the client "set rowcount" is differect
        */

        set rowcount 0


	/* get database name */
	select @dbname = db_name()

	/* we don't want a temp table unless we're in tempdb */
       /* Adding tempdb check here depending on the ASE version ADDTEMPDB */

   if (@table_name like '#%' and db_name() != db_name(tempdb_id()))
	begin	
		exec sp_getmessage 17676, @msg output
		raiserror 17676 @msg
		return (1)
	end

	if @table_qualifier is not null
	begin
		/* if qualifier doesn't match current database */
		if @dbname != @table_qualifier
		begin	
			exec sp_getmessage 18039, @msg output
			raiserror 18039 @msg
			return (1)
		end
	end

    if (@table_owner is null) select @table_owner = '%'
    else
    begin
        /*        
        ** NOTE: SQL Server allows an underscore '_' in the table owner, even 
        **       though it is a single character wildcard.
        */
        if (charindex('%',@table_owner) > 0)
        begin
            exec sp_getmessage 17993, @msg output
            raiserror 17993 @msg, @table_owner
            return(1)
        end
        exec sp_jdbc_escapeliteralforlike @table_owner output
    end
    
    if (@table_name is null) 
    begin
       exec sp_getmessage 17993, @msg output
       raiserror 17993 @msg, 'NULL'
       return(1)
    end
    
    if (select count(*) 
        from sysobjects
        where user_name(uid) 
        like @table_owner ESCAPE '\'
      	and name = @table_name) = 0 
    begin
      exec sp_getmessage 17674, @msg output
      raiserror 17674 @msg
      return 1
    end
    else 
    begin
	declare version_cur cursor for
     	        select @table_owner = user_name(uid) from sysobjects 
    		where name = @table_name and user_name(uid) like @table_owner

	open version_cur
	fetch version_cur into @owner

	while (@@sqlstatus = 0)
        begin
       	    if @owner is null
  	    begin	/* if unqualified table name */
		select @full_table_name = @table_name
 	    end
	    else
	    begin	/* qualified table name */
		select @full_table_name = @owner + '.' + @table_name
	    end

	    /* get object ID */
	    select @table_id = object_id(@full_table_name)

	    insert into #versionhelp select
		convert(smallint, 0),
		c.name ,
		(select data_type from 
			sybsystemprocs.dbo.spt_jdbc_datatype_info
			where type_name = 'binary'),
		'BINARY',
		isnull(d.data_precision,
				convert(int,c.length))
				+ isnull(d.aux, convert(int,
				ascii(substring('???AAAFFFCKFOLS',
				2*(d.ss_dtype%35+1)+2-8/c.length,1))
				-60)),
		18, /* Number of chars = 2^4 byte + '0x' */
		isnull(d.numeric_scale + convert(smallint,
				isnull(d.aux,
				ascii(substring('<<<<<<<<<<<<<<?',
				2*(d.ss_dtype%35+1)+2-8/c.length, 1))
				-60)),0),
		1
 		from
			systypes t, syscolumns c, 
			sybsystemprocs.dbo.spt_jdbc_datatype_info d
		where
			c.id = @table_id
			and c.type = d.ss_dtype
			and c.usertype = 80	/* TIMESTAMP */
			and t.usertype = 80	/* TIMESTAMP */
	    fetch version_cur into @owner
	end
    end
    select * from #versionhelp
go
exec sp_procxmode 'sp_jdbc_getversioncolumns', 'anymode'
go
grant execute on sp_jdbc_getversioncolumns to public
go
commit
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_getversioncolumns
*/



/*
**  sp_default_charset
*/

/* 
** obtain the SQL server default charset
*/


/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go
 
if exists (select * from sysobjects where name = 'sp_default_charset')
begin
        drop procedure sp_default_charset
end
go
/** SECTION END: CLEANUP **/
 

/*
**  create a procedure that will query the datasource
**  specific syscharset, and sysconfigures tables, and do a join to 
**  determine what is the correct charset that has been set as a default
**  on the server.
*/
create procedure sp_default_charset
as

    if @@trancount = 0
    begin
    	set chained off
    end
    
    set transaction isolation level 1

    select name as DEFAULT_CHARSET from master.dbo.syscharsets
       where ((select value from master.dbo.sysconfigures      
               where config=131)  /* default charset id */
              = master.dbo.syscharsets.id)
go
exec sp_procxmode 'sp_default_charset', 'anymode'
go
grant execute on sp_default_charset to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_default_charset
*/


/* 
** JDBC 2.0
** 
** DatabaseMetaData.getUDTs(catalog, schema, typeNamePattern, int types[])
**
** NOT SUPPORTED
*/
/** SECTION BEGIN: CLEANUP **/
if exists (select * from sysobjects where name = 'sp_jdbc_getudts')
begin
        drop procedure sp_jdbc_getudts
end
go
/** SECTION END: CLEANUP **/
create procedure sp_jdbc_getudts (
        @table_qualifier        varchar(32 ) = NULL,
        @table_owner            varchar(32 ) = NULL,
        @type_name_pattern      varchar(255),
        @types                  varchar(255))
as
    declare @empty_string varchar(1)
    declare @empty_int int
    
    select @empty_string = ''
    select @empty_int = 0

    /* not supported, return an empty result set */    
    select 
        TYPE_CAT = @empty_string,
        TYPE_SCHEM = @empty_string,
        TYPE_NAME = @empty_string,
        CLASS_NAME = @empty_string,
        DATA_TYPE = @empty_int,
        REMARKS = @empty_string
    where
        1 = 2
go

/* end of dbo.sp_jdbc_getudts */
exec sp_procxmode 'sp_jdbc_getudts', 'anymode'
go
grant execute on sp_jdbc_getudts to public
go
dump transaction sybsystemprocs with truncate_only 
go

/** SECTION BEGIN: CLEANUP **/
if exists (select * from sysobjects where name = 'sp_jdbc_getxacoordinator')
begin
        drop procedure sp_jdbc_getxacoordinator
end
go
/** SECTION END: CLEANUP **/       

/* Don't delete the following line. This is where sp_jdbc_getxacoordinator gets inserted. */
/*** ADDPOINT_JTA ***/
/*
** JDBC 2.0 extensions (JTA support)
** 
** SybDatabaseMetaData.getXACoordinatorType()
** 
** returns a resultset of the form:
** TxnStyle (indicating which transaction coordinator is being used.
** 0 means none.
**
** RequiredRoles (indicates what role the user must have to use)
** NULL means none.
**
** Status (a bitmask of capabilities that the coordinator provides)
** 0x00000001 - set if user has necessary role
** 0x00000002 - set if txns can migrate among connections
** 0x00000004 - set if multiple connections can participate in same txn simultaneously
**
** UniqueID (a string which uniquely identifies this server)
*/
create procedure sp_jdbc_getxacoordinator
as

declare @txnMode int
declare @status int
declare @uniqueID varchar(12)

/* For 12.0 and higher, jConnect expects to use DTM001. */
/* DTM001 is defined as 2 in SybDataSource.RMTYPE_ASE_XA_DTM. */
/* Users must have dtm_tm_role to use DTM.   */
/* Next, determine whether or not user has */
/* dtm_tm_role when setting the status bits. */
/* Lastly, return the unique ID for this resource. */

/* verify that the 12.0 server is configured for XA using DTM */
if ((select cur.value from master.dbo.syscurconfigs cur, master.dbo.sysconfigures conf
     where conf.comment = 'enable DTM' and cur.config = conf.config) != 0)
begin
     /* verify that the 12.0 server is licensed for XA using DTM */
     if (license_enabled('ASE_DTM') = 1)
     begin
         select @txnMode=2
     end
end
else
begin
     select @txnMode=0
end

/* now check for role permission */
if (charindex('dtm_tm_role', show_role()) != 0)
begin
     select @status=7
end
else
begin
     select @status=6
end

/* return results and name the columns */
select TxnStyle=@txnMode, RequiredRole='dtm_tm_role', Status=@status, UniqueID=@@nodeid
go

/* end of dbo.sp_jdbc_getxacoordinator */
exec sp_procxmode 'sp_jdbc_getxacoordinator', 'anymode'
go
grant execute on sp_jdbc_getxacoordinator to public
go
dump transaction sybsystemprocs with truncate_only 
go

/* Don't delete the following line. This is where server-specific sp's get inserted. */
/*** ADDPOINT_DCL ***/
/*
**  sp_jdbc_class_for_name
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_class_for_name')
    begin
        drop procedure sp_jdbc_class_for_name
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_class_for_name (
        @class_name varchar(255))
as
    select
        xtbinaryoffrow
    from 
        sysxtypes 
    where 
        xtname = @class_name

go

exec sp_procxmode 'sp_jdbc_class_for_name', 'anymode'
go
grant execute on sp_jdbc_class_for_name to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_class_for_name
*/



/*
**  sp_jdbc_jar_for_class
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_jar_for_class')
    begin
        drop procedure sp_jdbc_jar_for_class
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_jar_for_class (
        @class_name varchar(255))
as
    select
        sj.jbinary
    from
        sysjars sj, sysxtypes sjc
    where
        sjc.xtname = @class_name and sj.jid = sjc.xtcontainer
go

exec sp_procxmode 'sp_jdbc_jar_for_class', 'anymode'
go
grant execute on sp_jdbc_jar_for_class to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_jar_for_class
*/



/*
**  sp_jdbc_jar_by_name
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_jar_by_name')
    begin
        drop procedure sp_jdbc_jar_by_name
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_jar_by_name (
        @jar_name varchar(255))
as
    select
        sj.jbinary
    from
        sysjars sj
    where 
        jname = @jar_name
go

exec sp_procxmode 'sp_jdbc_jar_by_name', 'anymode'
go
grant execute on sp_jdbc_jar_by_name to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_jar_by_name
*/



/*
**  sp_jdbc_classes_in_jar
*/

/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

if exists (select * from sysobjects where name =
    'sp_jdbc_classes_in_jar')
    begin
        drop procedure sp_jdbc_classes_in_jar
    end
go
/** SECTION END: CLEANUP **/

create procedure sp_jdbc_classes_in_jar (
        @jar_name varchar(255))
as
    select 
        sjc.xtname 
    from 
        sysjars sj, sysxtypes sjc 
    where 
        sj.jid = sjc.xtcontainer and sj.jname = @jar_name
go

exec sp_procxmode 'sp_jdbc_classes_in_jar', 'anymode'
go
grant execute on sp_jdbc_classes_in_jar to public
go
dump transaction sybsystemprocs with truncate_only 
go

/*
**  End of sp_jdbc_classes_in_jar
*/



/** SECTION BEGIN: CLEANUP **/
use sybsystemprocs 
go

sp_configure 'allow updates', 0
go

set quoted_identifier off
go

/** SECTION END: CLEANUP **/

/*
**  End of sql_server.sql
*/
declare @retval int
exec @retval = sp_version 'installjdbc',NULL,'jConnect (TM) for JDBC(TM)/6.05(Build 26515)/P/EBF16508/JDK14/Fri Jan 16 12:48:51 2009', 'end'
if (@retval != 0) select syb_quit()
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_computeprivs')
begin
	drop procedure sp_odbc_computeprivs
end
go
print "Installing sp_odbc_computeprivs"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_server_info')
begin
	drop procedure sp_odbc_server_info
end
go
print "Installing sp_odbc_server_info"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_databases')
begin
	drop procedure sp_odbc_databases
end
go
print "Installing sp_odbc_databases"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_columns')
begin
	drop procedure sp_odbc_columns
end
go
print "Installing sp_odbc_columns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_datatype_info')
begin
	drop procedure sp_odbc_datatype_info
end
go
print "Installing sp_odbc_datatype_info"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getversioncolumns')
begin
	drop procedure sp_odbc_getversioncolumns
end
go
print "Installing sp_odbc_getversioncolumns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getcolumnprivileges')
begin
	drop procedure sp_odbc_getcolumnprivileges
end
go
print "Installing sp_odbc_getcolumnprivileges"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_tables')
begin
	drop procedure sp_odbc_tables
end
go
print "Installing sp_odbc_tables"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_gettableprivileges')
begin
	drop procedure sp_odbc_gettableprivileges
end
go
print "Installing sp_odbc_gettableprivileges"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getindexinfo')
begin
	drop procedure sp_odbc_getindexinfo
end
go
print "Installing sp_odbc_getindexinfo"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_primarykey')
begin
	drop procedure sp_odbc_primarykey
end
go
print "Installing sp_odbc_primarykey"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_fkeys')
begin
	drop procedure sp_odbc_fkeys
end
go
print "Installing sp_odbc_fkeys"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_stored_procedures')
begin
	drop procedure sp_odbc_stored_procedures
end
go
print "Installing sp_odbc_stored_procedures"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getprocedurecolumns')
begin
	drop procedure sp_odbc_getprocedurecolumns
end
go
print "Installing sp_odbc_getprocedurecolumns"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*
**  ODBC_INSTALL
**  This file contains the metadata Stored Procedures used by the ODBC drivers.
**
*/

/*
** Stored procedures created:
**
** Name                          	Default Location	Comments
** --------------------------------------------------------------------------------------------------
** 1>  sp_odbc_server_info		sybsystemprocs
** 2>  sp_odbc_databases		sybsystemprocs
** 3>  sp_odbc_columns			sybsystemprocs
** 4>  sp_odbc_datatype_info		sybsystemprocs
** 5>  sp_odbc_getversioncolumns	sybsystemprocs		
** 6>  sp_odbc_getcolumnprivileges	sybsystemprocs
** 7>  sp_odbc_tables			sybsystemprocs
** 8>  sp_odbc_gettableprivileges	sybsystemprocs
** 9>  sp_odbc_getindexinfo		sybsystemprocs
** 10> sp_odbc_primarykey		sybsystemprocs
** 11> sp_odbc_fkeys			sybsystemprocs
** 12> sp_odbc_stored_procedures	sybsystemprocs
** 13> sp_odbc_getprocedurecolumns	sybsystemprocs
** 14> sp_odbc_computeprivs		sybsystemprocs	added to support ,
**								sp_odbc_gettableprivileges
**								sp_odbc_getcolumnprivileges
** 15> sp_version			sybsystemprocs
*/
set flushmessage on
go

print ""
go

declare @version_string varchar(255) 
select @version_string = '15.0.0.346/'+ 'Fri 01-16-2009 17:45:38.79' 
print "ODBC - Build Version : %1!", @version_string 
declare @retval int
exec @retval = sp_version 'ODBC MDA Scripts', NULL, @version_string, 'start'
if (@retval != 0) select syb_quit()
go


use sybsystemprocs
go

if exists (select * from sysobjects where name = 'sp_odbc_computeprivs')
    begin
        drop procedure sp_odbc_computeprivs
    end
go

/*
** Results Table needs to be created so that sp_odbc_computeprivs has a temp
** table to reference when the procedure is compiled.  Otherwise, the calling
** stored procedure will create the temp table for sp_odbc_computeprivs.
*/
create table #results_table
        (table_qualifier        varchar (32),
         table_owner            varchar (32),
         table_name             varchar (255),
         column_name            varchar (255) NULL,
         grantor                varchar (32),
         grantee                varchar (32),
         privilege              varchar (32),
         is_grantable           varchar (3))
go

create procedure sp_odbc_computeprivs (
                        @table_name             varchar(255),
                        @table_owner            varchar(32),
                        @table_qualifier        varchar(32),
                        @column_name            varchar(255),
                        @calledfrom_colpriv     tinyint,
                        @tab_id                 int)

AS

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_COMPUTE_PRIVS */

--    declare @low 		int		/* range of userids to check */
--    declare @high 		int
--    declare @max_uid		smallint        /* max uid allowed for a user */
    
    declare @grantor_name       varchar (32)    /* the ascii name of grantor.
                                                   used for output */
    declare @grantee_name       varchar (32)    /* the ascii name of grantee.
                                                   used for output */
    declare @col_count          smallint        /* number of columns in
                                                   @table_name */
    declare @grantee            int             /* id of the grantee */
    declare @action             smallint        /* action refers to select,
                                                   update...*/
    declare @columns            varbinary (133) /* bit map of column
                                                   privileges */
    declare @protecttype        tinyint         /* grant/revoke or grant with
                                                   grant option */
    declare @grantor            int             /* id of the grantor of the
                                                   privilege */
    declare @grp_id             int             /* the group a user belongs
                                                   to */
    declare @grant_type         tinyint         /* used as a constant */
    declare @revoke_type        tinyint         /* used as a constant */
    declare @select_action      smallint        /* used as a constant */
    declare @update_action      smallint        /* used as a constant */
    declare @reference_action   smallint        /* used as a constant */
    declare @insert_action      smallint        /* used as a constant */
    declare @delete_action      smallint        /* used as a constant */
    declare @public_select      varbinary (133) /* stores select column bit map
                                                   for public */
    declare @public_reference   varbinary (133) /* stores reference column bit
                                                   map for public */
    declare @public_update      varbinary (133) /* stores update column bit map
                                                   for public */
    declare @public_insert      tinyint         /* stores if insert has been
                                                   granted to public */
    declare @public_delete      tinyint         /* store if delete has been
                                                   granted to public */
    declare @grp_select         varbinary (133) /* stores select column bit map
                                                   for group */
    declare @grp_update         varbinary (133) /* stores update column bit map
                                                   for group */
    declare @grp_reference      varbinary (133) /* stores reference column bit
                                                   map for group */
    declare @grp_delete         tinyint         /* if group hs been granted
                                                   delete privilege */
    declare @grp_insert         tinyint         /* if group has been granted
                                                   insert privilege */
    declare @inherit_select     varbinary (133) /* stores select column bit map
                                                   for inherited privs*/
    declare @inherit_update     varbinary (133) /* stores update column bit map
                                                   for inherited privs */
    declare @inherit_reference  varbinary (133) /* stores reference column bit
                                                   map for inherited privs */
    declare @inherit_insert     tinyint         /* inherited insert priv */
    declare @inherit_delete     tinyint         /* inherited delete priv */
    declare @select_go          varbinary (133) /* user column bit map of
                                                   select with grant */
    declare @update_go          varbinary (133) /* user column bit map of
                                                   update with grant */
    declare @reference_go       varbinary (133) /* user column bitmap of
                                                   reference with grant */
    declare @insert_go          tinyint         /* user insert priv with
                                                   grant option */
    declare @delete_go          tinyint         /* user delete priv with grant
                                                   option  */
    declare @prev_grantor       int             /* used to detect if the
                                                   grantor has changed between
                                                   two consecutive tuples */
    declare @col_pos            smallint        /* col_pos of the column we are
                                                   interested in. It is used to
                                                   find the col-bit in the
                                                   bitmap */
    declare @owner_id           int             /* id of the owner of the
                                                   table */
    declare @dbid               smallint        /* dbid for the table */
    declare @grantable          varchar (3)     /* 'YES' or 'NO' if the
                                                   privilege is grantable or
                                                   not */
    declare @is_printable       tinyint         /* 1, if the privilege info is
                                                   to be outputted */
    declare @startedInTransaction bit
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0
                                                       

    if (@startedInTransaction = 1)
	save transaction odbc_keep_temptable_tx    

/* 
** Initialize all constants to be used in this procedure
*/

    select @grant_type = 1

    select @revoke_type = 2
   
    select @select_action = 193

    select @reference_action = 151

    select @update_action = 197

    select @delete_action = 196

    select @insert_action = 195

--    select @max_uid = 16383

--    select @low = -32768, @high = 32767
    
/*
** compute the table owner id
*/

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id

/*
** create a temporary sysprotects table that only has grant/revoke tuples
** for the requested table. This is done as an optimization as the sysprotects
** table may need to be traversed several times
*/

    create table #sysprotects
        (uid            int,
         action         smallint,
         protecttype    tinyint,
         columns        varbinary (133) NULL,
         grantor        int)

/*
** This table contains all the groups including PUBLIC that users, who
** have been granted privilege on this table, belong to. Also it includes
** groups that have been explicitly granted privileges on the table object
*/
    create table #useful_groups
        (grp_id         int)

/*
** create a table that contains the list of grantors for the object requested.
** We will do a cartesian product of this table with sysusers in the
** current database to capture all grantor/grantee tuples
*/

    create table #distinct_grantors
        (grantor        int)

/*
** We need to create a table which will contain a row for every object
** privilege to be returned to the client.  
*/

    create table #column_privileges 
        (grantee_gid    int,
         grantor        int,
         grantee        int,
         insertpriv     tinyint,
         insert_go      tinyint NULL,
         deletepriv     tinyint,
         delete_go      tinyint NULL,
         selectpriv     varbinary (133) NULL,
         select_go      varbinary (133) NULL,
         updatepriv     varbinary (133) NULL,
         update_go      varbinary (133) NULL,
         referencepriv  varbinary (133) NULL,
         reference_go   varbinary (133) NULL)

/*
** this cursor scans the distinct grantor, group_id pairs
*/
    declare grp_cursor cursor for
        select distinct grp_id, grantor 
        from #useful_groups, #distinct_grantors
        order by grantor

/* 
** this cursor scans all the protection tuples that represent
** grant/revokes to users only
*/
    declare user_protect cursor for
        select uid, action, protecttype, columns, grantor
        from   #sysprotects
        where  (uid != 0) and
--              (uid <= @max_uid)
               ((uid >= @@minuserid and uid < @@mingroupid) or 
               (uid > @@maxgroupid and uid <= @@maxuserid)) 


/*
** this cursor is used to scan #column_privileges table to output results
*/
    declare col_priv_cursor cursor for
          select grantor, grantee, insertpriv, insert_go, deletepriv,
              delete_go, selectpriv, select_go, updatepriv, update_go,
              referencepriv, reference_go
          from #column_privileges



/*
** column count is needed for privilege bit-map manipulation
*/
    select @col_count = count (*) 
    from   syscolumns
    where  id = @tab_id


/* 
** populate the temporary sysprotects table #sysprotects
*/

        insert into #sysprotects 
                select uid, action, protecttype, columns, grantor
                from sysprotects
                where (id = @tab_id)               and
                      ((action = @select_action)   or
                      (action = @update_action)    or
                      (action = @reference_action) or
                      (action = @insert_action)    or
                      (action = @delete_action))

/* 
** insert privilege tuples for the table owner. There is no explicit grants
** of these privileges to the owner. So these tuples are not there in
** sysprotects table
*/

if not exists (select * from #sysprotects where (action = @select_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @select_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @update_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @update_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @reference_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @reference_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @insert_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @insert_action, 0, NULL, @owner_id)
end

if not exists (select * from #sysprotects where (action = @delete_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @delete_action, 0, NULL, @owner_id)
end


/* 
** populate the #distinct_grantors table with all grantors that have granted
** the privilege to users or to gid or to public on the table_name
*/

    insert into #distinct_grantors 
          select distinct grantor from #sysprotects

/* 
** Populate the #column_privilegs table as a cartesian product of the table
** #distinct_grantors and all the users, other than groups, in the current
** database
*/


    insert into #column_privileges
          select gid, g.grantor, su.uid, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00,
              0x00, 0x00
          from sysusers su, #distinct_grantors g
        where  (su.uid != 0) and
--                (su.uid <= @max_uid)
               ((su.uid >= @@minuserid and su.uid < @@mingroupid) or
               (su.uid > @@maxgroupid and su.uid <= @@maxuserid)) 

/*
** populate #useful_groups with only those groups whose members have been
** granted/revoked privileges on the @tab_id in the current database. It also
** contains those groups that have been granted/revoked privileges explicitly
*/

    insert into #useful_groups
        select distinct gid
        from   sysusers su, #sysprotects sp
        where  (su.uid = sp.uid) 


    open grp_cursor

    fetch grp_cursor into @grp_id, @grantor

    /* 
    ** This loop computes all the inherited privilegs of users due
    ** their membership in a group
    */

    while (@@sqlstatus != 2)
   
    begin

         /* 
         ** initialize variables 
         */
         select @public_select = 0x00
         select @public_update = 0x00
         select @public_reference = 0x00
         select @public_delete = 0
         select @public_insert = 0


         /* get the select privileges granted to PUBLIC */

         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @select_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_select = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @select_action)
         end


         /* get the update privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @update_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_update = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @update_action)
         end

         /* get the reference privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @reference_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_reference = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @reference_action)
         end


         /* get the delete privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @delete_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_delete = 1
         end

         /* get the insert privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @insert_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_insert = 1
         end


         /*
         ** initialize group privileges 
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** if the group id is other than PUBLIC, we need to find the grants to
         ** the group also 
         */

         if (@grp_id <> 0)
         begin
                /* find select privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @select_action)
                end

                /* find update privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @update_action)
                end

                /* find reference privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @reference_action)
                end

                /* find delete privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @delete_action)))
                begin

                        select @grp_delete = 1
                end

                /* find insert privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @insert_action)))
                begin

                        select @grp_insert = 1

                end

         end

         /* at this stage we have computed all the grants to PUBLIC as well as
         ** the group by a specific grantor that we are interested in. Now we
         ** will use this info to compute the overall inherited privileges by
         ** the users due to their membership to the group or to PUBLIC 
         */


         exec sybsystemprocs.dbo.syb_aux_privunion @public_select, @grp_select,
             @col_count, @inherit_select output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_update, @grp_update, 
             @col_count, @inherit_update output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_reference,
             @grp_reference, @col_count, @inherit_reference output

         select @inherit_insert = @public_insert + @grp_insert
         select @inherit_delete = @public_delete + @grp_delete

         /*
         ** initialize group privileges to store revokes
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** now we need to find if there are any revokes on the group under
         ** consideration. We will subtract all privileges that are revoked
         ** from the group from the inherited privileges
         */

         if (@grp_id <> 0)
         begin
                /* check if there is a revoke row for select privilege*/
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @select_action)
                end

                /* check if there is a revoke row for update privileges */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @update_action)
                end

                /* check if there is a revoke row for reference privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @reference_action)
                end

                /* check if there is a revoke row for delete privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @delete_action)))
                begin
                        select @grp_delete = 1
                end

                /* check if there is a revoke row for insert privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @insert_action)))
                begin
                        select @grp_insert = 1

                end


                /* 
                ** now subtract the revoked privileges from the group
                */

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                                                 @grp_select,
                                                 @col_count,
                                                 @inherit_select output

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                                                 @grp_update,
                                                 @col_count,
                                                 @inherit_update output

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference,
                                                 @grp_reference,
                                                 @col_count,
                                                 @inherit_reference output

                if (@grp_delete = 1)
                        select @inherit_delete = 0

                if (@grp_insert = 1)
                        select @inherit_insert = 0

         end

         /*
         ** now update all the tuples in #column_privileges table for this
         ** grantor and group id
         */

         update #column_privileges
         set
                insertpriv      = @inherit_insert,
                deletepriv      = @inherit_delete,
                selectpriv      = @inherit_select,
                updatepriv      = @inherit_update,
                referencepriv   = @inherit_reference

         where (grantor     = @grantor) and
               (grantee_gid = @grp_id)


         /*
         ** the following update updates the privileges for those users
         ** whose groups have not been explicitly granted privileges by the
         ** grantor. So they will all have all the privileges of the PUBLIC
         ** that were granted by the current grantor
         */

         select @prev_grantor = @grantor         
         fetch grp_cursor into @grp_id, @grantor

         if ((@prev_grantor <> @grantor) or (@@sqlstatus = 2))

         begin
         /* Either we are at the end of the fetch or we are switching to
         ** a different grantor. 
         */

               update #column_privileges 
               set
                        insertpriv      = @public_insert,
                        deletepriv      = @public_delete,
                        selectpriv      = @public_select,
                        updatepriv      = @public_update,
                        referencepriv   = @public_reference
                from #column_privileges cp
                where (cp.grantor = @prev_grantor) and
                      (not EXISTS (select * 
                                   from #useful_groups ug
                                   where ug.grp_id = cp.grantee_gid))

         end
    end


    close grp_cursor


    /* 
    ** At this stage, we have populated the #column_privileges table with
    ** all the inherited privileges
    */
    /*
    ** update #column_privileges to give all access to the table owner that way
    ** if there are any revoke rows in sysprotects, then the calculations will
    ** be done correctly.  There will be no revoke rows for table owner if
    ** privileges are revoked from a group that the table owner belongs to.
    */
    update #column_privileges
    set
        insertpriv      = 0x01, 
        deletepriv      = 0x01, 
        selectpriv      = 0x01,
        updatepriv      = 0x01,
        referencepriv   = 0x01

        where grantor = grantee
          and grantor = @owner_id

    
    /* 
    ** Now we will go through each user grant or revoke in table #sysprotects
    ** and update the privileges in #column_privileges table
    */
    open user_protect

    fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor

    while (@@sqlstatus != 2)
    begin
        /*
        ** In this loop, we can find grant row, revoke row or grant with grant
        ** option row. We use protecttype to figure that. If it is grant, then
        ** the user specific privileges are added to the user's inherited
        ** privileges. If it is a revoke, then the revoked privileges are
        ** subtracted from the inherited privileges. If it is a grant with
        ** grant option, we just store it as is because privileges can
        ** only be granted with grant option to individual users
        */

        /* 
        ** for select action
        */
        if (@action = @select_action)
        begin
             /* get the inherited select privilege */
             select @inherit_select = selectpriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)

             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_select,
                    @columns, @col_count, @inherit_select output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                         @columns, @col_count, @inherit_select output

                else
                     /* it is a grant with grant option */

                     select @select_go = @columns

             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set selectpriv = @inherit_select
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin

                  update #column_privileges
                  set select_go = @select_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /*
        ** update action
        */
        if (@action = @update_action)
        begin
             /* find out the inherited update privilege */
             select @inherit_update = updatepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* user has an individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_update,
                    @columns, @col_count, @inherit_update output

             else 
                if (@protecttype = @revoke_type)
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                         @columns, @col_count, @inherit_update output

                else
                     /* it is a grant with grant option */
                     select @update_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set updatepriv = @inherit_update
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set update_go = @update_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /* it is the reference privilege */
        if (@action = @reference_action)
        begin
             select @inherit_reference = referencepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_reference,
                    @columns, @col_count, @inherit_reference output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor
                        @inherit_reference, @columns, @col_count,
                        @inherit_reference output

                else
                     /* it is a grant with grant option */
                     select @reference_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set referencepriv = @inherit_reference
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set reference_go = @reference_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /*
        ** insert action
        */

        if (@action = @insert_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_insert = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_insert = 0
                 else
                      select @insert_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set insertpriv = @inherit_insert
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set insert_go = @insert_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /* 
        ** delete action
        */

        if (@action = @delete_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_delete = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_delete = 0
                 else
                      select @delete_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set deletepriv = @inherit_delete
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set delete_go = @delete_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        fetch user_protect into @grantee, @action, @protecttype, @columns,
            @grantor
    end

    close user_protect

open col_priv_cursor
fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
                         @inherit_delete, @delete_go, @inherit_select,
                         @select_go, @inherit_update, @update_go,
                         @inherit_reference, @reference_go

while (@@sqlstatus != 2)
begin

      /* 
      ** name of the grantor
      */
      select @grantor_name = name 
      from   sysusers
      where  uid = @grantor


      /*
      ** name of the grantee
      */

      select @grantee_name = name
      from   sysusers
      where  uid = @grantee

      /* 
      ** At this point, we are either printing privilege information for a
      ** a specific column or for table_privileges
      */

            select @col_pos = 0

            if (@calledfrom_colpriv = 1)
            begin
            /* 
            ** find the column position
            */
                 select @col_pos = colid
                 from syscolumns
                 where (id = @tab_id) and
                       (name = @column_name)
            end

            /* 
            ** check for insert privileges
            */
            /* insert privilege is only a table privilege */
            if (@calledfrom_colpriv = 0)
            begin
                    exec sybsystemprocs.dbo.syb_aux_printprivs 
                        @calledfrom_colpriv, @col_pos, @inherit_insert,
                        @insert_go, 0x00, 0x00, 0, @grantable output,
                        @is_printable output

                    if (@is_printable = 1)
                    begin
                          insert into #results_table
                               values (@table_qualifier, @table_owner,
                                       @table_name, @column_name,
                                       @grantor_name, @grantee_name, 'INSERT',
                                       @grantable)
                    end
            end

            /* 
            ** check for delete privileges
            */

            if (@calledfrom_colpriv = 0)
            /* delete privilege need only be printed if called from
               sp_table_privileges */
            begin
                    exec sybsystemprocs.dbo.syb_aux_printprivs 
                         @calledfrom_colpriv, @col_pos, @inherit_delete,
                         @delete_go, 0x00, 0x00, 0, @grantable output,
                         @is_printable output

                    if (@is_printable = 1)
                    begin
                        insert into #results_table
                                values (@table_qualifier, @table_owner,
                                        @table_name, @column_name,
                                        @grantor_name, @grantee_name, 'DELETE',
                                        @grantable)
                    end
            end

            /* 
            ** check for select privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                        @calledfrom_colpriv, @col_pos, 0, 0, @inherit_select,
                        @select_go, 1, @grantable output, @is_printable output


            if (@is_printable = 1)
            begin
                  insert into #results_table
                         values (@table_qualifier, @table_owner, @table_name,
                                 @column_name, @grantor_name, @grantee_name,
                                 'SELECT', @grantable)
            end
            /* 
            ** check for update privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                @calledfrom_colpriv, @col_pos, 0, 0, @inherit_update,
                @update_go, 1, @grantable output, @is_printable output

            if (@is_printable = 1)
            begin
                  insert into #results_table
                        values (@table_qualifier, @table_owner, @table_name,
                                @column_name, @grantor_name, @grantee_name,
                                'UPDATE', @grantable)
            end
            /*
            ** check for reference privs
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                @calledfrom_colpriv, @col_pos, 0, 0, @inherit_reference,
                @reference_go, 1, @grantable output, @is_printable output

            if (@is_printable = 1)
            begin
                insert into #results_table
                        values (@table_qualifier, @table_owner, @table_name,
                                @column_name, @grantor_name, @grantee_name,
                                'REFERENCE', @grantable)
            end



      fetch col_priv_cursor into @grantor, @grantee, @inherit_insert,
          @insert_go, @inherit_delete, @delete_go, @inherit_select, @select_go,
          @inherit_update, @update_go, @inherit_reference, @reference_go
end

close col_priv_cursor

    drop table #column_privileges
    drop table #distinct_grantors
    drop table #sysprotects
    drop table #useful_groups
    
    if (@startedInTransaction = 1)
	rollback transaction odbc_keep_temptable_tx    


go

/*
** Drop temp table used for creation of sp_odbc_computeprivs
*/
drop table #results_table
go

exec sp_procxmode 'sp_odbc_computeprivs', 'anymode'
go

grant execute on sp_odbc_computeprivs to public
go


if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_server_info')
begin
	drop procedure sp_odbc_server_info
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_odbc_server_info"
**
** 18059, "Attribute id %1! is not supported."
*/

create procedure sp_odbc_server_info
@attribute_id int = NULL		/* optional attribute id */
as


set nocount on

/* If an attribute id was specified then just return the info for that
** attribute.
*/
if @attribute_id is not null
begin
	/* Verify that the attribute is valid. */
	if not exists ( select attribute_id 
		from sybsystemprocs.dbo.spt_server_info
			where attribute_id = @attribute_id )
	begin
		/*
		** 18059, "Attribute id %1! is not supported."
		*/
		raiserror 18059, @attribute_id
		return (1)
	end

	select * from sybsystemprocs.dbo.spt_server_info
		where attribute_id = @attribute_id
end

/* If no attribute was specified then return info for all supported
** attributes.
*/
else
begin
	select * from sybsystemprocs.dbo.spt_server_info
end

return (0)
go
exec sp_procxmode 'sp_odbc_server_info', 'anymode'
go
grant execute on sp_odbc_server_info to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_databases')
begin
	drop procedure sp_odbc_databases
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

create procedure sp_odbc_databases
as

    declare @startedInTransaction bit
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0
                                                       


	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

    if (@startedInTransaction = 1)
	save transaction odbc_keep_temptable_tx    


	/* Use temporary table to sum up database size w/o using group by */
	create table #databases (
				  database_name varchar(32),
				  size int)

	/* Insert row for each database */
	insert into #databases
		select
			name,
			(select sum(size) from master.dbo.sysusages
				where dbid = d.dbid)
		from master.dbo.sysdatabases d

	select
		 database_name,
				/* Convert from number of pages to K */
		 database_size = size * (@@maxpagesize / 1024),
		 remarks = convert(varchar(254),null)	/* Remarks are NULL */
	from #databases

    drop table #databases
    if (@startedInTransaction = 1)
	rollback transaction odbc_keep_temptable_tx    

return(0)
go
go
exec sp_procxmode 'sp_odbc_databases', 'anymode'
go
grant execute on sp_odbc_databases to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_columns')
begin
	drop procedure sp_odbc_columns
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G% " */
/*      10.0        07/20/93        sproc/columns */
 

/* This is the version for servers which support UNION */

/* This routine is intended for support of ODBC connectivity.  Under no
** circumstances should changes be made to this routine unless they are
** to fix ODBC related problems.  All other users are at there own risk!
**
** Please be aware that any changes made to this file (or any other ODBC
** support routine) will require Sybase to recertify the SQL server as
** ODBC compliant.  This process is currently being managed internally
** by the "Interoperability Engineering Technology Solutions Group" here
** within Sybase.
*/

CREATE PROCEDURE sp_odbc_columns (
				 @table_name		varchar(771),
				 @table_owner		varchar(32) = null,
				 @table_qualifier	varchar(32) = null,
				 @column_name		varchar(771) = null )
AS
    declare @full_table_name    varchar(1543)
    declare @table_id int
    declare @char_bin_types   varchar(32)
    
    declare @o_uid              int
    declare @o_name             varchar (255)
    declare @d_data_type        smallint
    declare @d_aux              int
    declare @d_ss_dtype         tinyint
    declare @d_type_name        varchar (255)
    declare @d_data_precision   int
    declare @d_numeric_scale    smallint
    declare @d_numeric_radix    smallint
    declare @d_sql_data_type    smallint
    declare @c_name             varchar (255)
    declare @c_length           int
    declare @c_prec             tinyint
    declare @c_scale            tinyint
    declare @c_type             tinyint
    declare @c_colid            smallint
    declare @c_status           tinyint
    declare @c_cdefault         int
    declare @xtname             varchar (255)
    declare @column_default   	varchar (1024)
    declare @ident		bit
    declare @max_cdefault_len	int
    declare @cdefault_len	int

    declare @startedInTransaction bit
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0
                                                       

  
    set transaction isolation level 1

    if (@startedInTransaction = 1)
	save transaction odbc_keep_temptable_tx    
 
/* character and binary datatypes */
	select @char_bin_types =
		char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

    if @column_name is null /*	If column name not supplied, match all */
	select @column_name = '%'

    /* Check if the current database is the same as the one provided */
    if @table_qualifier is not null
    begin
		if db_name() != @table_qualifier
		begin	/* 
			** If qualifier doesn't match current database 
			** 18039, Table qualifier must be name of current database
			*/
			raiserror 18039
			return (1)
		end
    end

    if @table_name is null
    begin	/*	If table name not supplied, match all */
		select @table_name = '%'
    end

    if @table_owner is null
    begin	/* If unqualified table name */
		SELECT @full_table_name = @table_name
    end
    else
    begin	/* Qualified table name */
		SELECT @full_table_name = @table_owner + '.' + @table_name
    end

    /* Get Object ID */
    SELECT @table_id = object_id(@full_table_name)


    /* create the temp table to hold column results */
    create table #odbc_columns (
        TABLE_CAT         varchar (32) null,
        TABLE_SCHEM       varchar (32) null,
        TABLE_NAME        varchar (255) null,
        COLUMN_NAME       varchar (255) null,
        DATA_TYPE         smallint null,
        TYPE_NAME         varchar (255) null,
        COLUMN_SIZE       int null,
        BUFFER_LENGTH     int null,
        DECIMAL_DIGITS    smallint null,
        NUM_PREC_RADIX    smallint null,
        NULLABLE          smallint null,
        REMARKS           varchar (255) null,
        COLUMN_DEF        varchar (512) null,
        SQL_DATA_TYPE     smallint null,
        SQL_DATETIME_SUB  smallint null,
        CHAR_OCTET_LENGTH int null,
        ORDINAL_POSITION  int null,
        IS_NULLABLE       varchar (10) null)

	select @max_cdefault_len = 512

    /* If the table name parameter is valid, get the information */ 
    if ((charindex('%',@full_table_name) = 0) and
		(charindex('_',@full_table_name) = 0)  and
		@table_id != 0)
    begin
      declare odbc_columns_cursor1 cursor for
        SELECT 
               c.cdefault,
               c.colid,
               c.length,
               c.name,
               c.prec,
               c.scale,
               c.status,
               c.type,
               d.aux, 
               d.data_precision,
               d.data_type,
               d.numeric_radix,
               d.numeric_scale,
               d.sql_data_type,
               d.ss_dtype,
		    case 
		     when c.usertype = 80 then t.name
		     when c.usertype = 24 then t.name
		     when c.usertype = 25 then t.name
		    else
			  d.type_name
		    end,               
              
               o.name,
               o.uid,
               xtname,
               convert(bit, (c.status & 0x80))
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		sysxtypes x,
		systypes t
	WHERE
		o.id = @table_id
		AND c.id = o.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		AND t.type = d.ss_dtype
		AND c.xtype *= x.xtid
		AND o.type != 'P'
		AND c.name like @column_name
--	AND d.ss_dtype IN (111, 109, 38, 110)	/* Just *N types */
 	AND d.ss_dtype IN (111, 109, 38, 110, 68)	/* Just *N types */	
		AND c.usertype < 100		/* No user defined types */
		
      open odbc_columns_cursor1

      fetch odbc_columns_cursor1 into
        @c_cdefault,
        @c_colid,
        @c_length,
        @c_name,
        @c_prec,
        @c_scale,
        @c_status,
        @c_type,
        @d_aux, 
        @d_data_precision,
        @d_data_type,
        @d_numeric_radix,
        @d_numeric_scale,
        @d_sql_data_type,
        @d_ss_dtype,
        @d_type_name,
        @o_name,
        @o_uid,
        @xtname,
        @ident
        
	while (@@sqlstatus = 0)
        begin
	if (@c_cdefault is NOT NULL)
	  begin
           	exec sp_drv_column_default @c_cdefault, @column_default out
           	select @cdefault_len= datalength(@column_default)

		if (@cdefault_len > @max_cdefault_len)
			select @column_default = "TRUNCATED"

           	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		INSERT INTO #odbc_columns values(
		DB_NAME(),
		USER_NAME(@o_uid),
		@o_name,
		@c_name,
		@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60)),
		/* TYPE_NAME */
		case
	            	when @ident = 1 then 
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))+' identity'
	            	else
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))
		end,
		isnull(convert(int, @c_prec),
			 isnull(convert(int, @d_data_precision),
			convert(int,@c_length)))
			+isnull(@d_aux, convert(int,
			ascii(substring("???AAAFFFCKFOLS",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		isnull(convert(int, @c_length), 
			convert(int, @c_length)) +
			   convert(int, isnull(@d_aux,
			ascii(substring("AAA<BB<DDDHJSPP",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-64)),
		isnull(convert(smallint, @c_scale), 
		       convert(smallint, @d_numeric_scale))
			+convert(smallint,
			isnull(@d_aux,
			ascii(substring("<<<<<<<<<<<<<<?",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60)),
		@d_numeric_radix,
		/* set nullability from status flag */
		convert(smallint, convert(bit, @c_status&8)),
		convert(varchar(254),null),	/* Remarks are NULL */
                @column_default,
                isnull(@d_sql_data_type,
			@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60))),
		convert(smallint,NULL),
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(@c_type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision 
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint, 
                    	substring('0111111', 
                       	charindex(char(@c_type), 
			@char_bin_types)+1, 1)) * 
                	/* calculate the precision */
                	isnull(convert(int, @c_prec),
                    	isnull(convert(int, @d_data_precision),
                       	convert(int,@c_length)))
                    	+isnull(@d_aux, convert(int,
                       	ascii(substring('???AAAFFFCKFOLS',
                       	2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		convert(int,@c_colid),
		rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, @c_status&8))*3)+1, 3)))
                	
	fetch odbc_columns_cursor1 into
	@c_cdefault,
	@c_colid,
	@c_length,
	@c_name,
	@c_prec,
	@c_scale,
	@c_status,
	@c_type,
	@d_aux, 
	@d_data_precision,
	@d_data_type,
	@d_numeric_radix,
	@d_numeric_scale,
	@d_sql_data_type,
	@d_ss_dtype,
	@d_type_name,
	@o_name,
	@o_uid,
	@xtname,
	@ident
	
	end		/* end of if	*/
	end	/* end of while */

	deallocate cursor odbc_columns_cursor1
	declare odbc_columns_cursor2 cursor for
	SELECT 
	       c.cdefault,
	       c.colid,
	       c.length,
	       c.name,
	       c.prec,
	       c.scale,
	       c.status,
	       c.type,
	       d.aux, 
	       d.data_precision,
	       d.data_type,
	       d.numeric_radix,
	       d.numeric_scale,
	       d.sql_data_type,
	       d.ss_dtype,
		    case 
		     when c.usertype = 80 then t.name
		     when c.usertype = 24 then t.name
		     when c.usertype = 25 then t.name
		    else
			  d.type_name
		    end,               
	       o.name,
	       o.uid,
	       xtname,
	       convert(bit, (c.status & 0x80))
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		sysxtypes x,
		systypes t
	WHERE
		o.id = @table_id
		AND c.id = o.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		/*
		** We need a equality join with 
		** sybsystemprocs.dbo.spt_datatype_info here so that
		** there is only one qualified row returned from 
		** sybsystemprocs.dbo.spt_datatype_info, thus avoiding
		** duplicates.
		*/
		AND t.type = d.ss_dtype
		AND c.xtype *= x.xtid
		AND o.type != 'P'
		AND c.name like @column_name
--	AND (d.ss_dtype NOT IN (111, 109, 38, 110) /* No *N types */
 	AND (d.ss_dtype NOT IN (111, 109, 38, 110, 68) /* No *N types */
			OR c.usertype >= 100) /* User defined types */

      open odbc_columns_cursor2
      fetch odbc_columns_cursor2 into
          @c_cdefault,
          @c_colid,
          @c_length,
          @c_name,
          @c_prec,
          @c_scale,
          @c_status,
          @c_type,
          @d_aux, 
          @d_data_precision,
          @d_data_type,
          @d_numeric_radix,
          @d_numeric_scale,
          @d_sql_data_type,
          @d_ss_dtype,
          @d_type_name,
          @o_name,
          @o_uid,
          @xtname,
          @ident

      while (@@sqlstatus = 0)
      begin
 	  if (@c_cdefault is NOT NULL)
 	  begin
	        exec sp_drv_column_default @c_cdefault, @column_default out
           	select @cdefault_len= datalength(@column_default)

		if (@cdefault_len > @max_cdefault_len)
			select @column_default = "TRUNCATED"
		
	   /* All other types including user data types */
		INSERT INTO #odbc_columns values(
		DB_NAME(),
		USER_NAME(@o_uid),
		@o_name,
		@c_name,
		@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60)),
		/* TYPE_NAME */
		case
	            	when @ident = 1 then 
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))+' identity'
	            	else
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))
		end,
		isnull(convert(int, @c_prec),
			 isnull(convert(int, @d_data_precision), 
			convert(int,@c_length)))
			+isnull(@d_aux, convert(int,
			ascii(substring("???AAAFFFCKFOLS",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		isnull(convert(int, @c_length), 
			convert(int, @c_length)) +
			   convert(int, isnull(@d_aux,
			ascii(substring("AAA<BB<DDDHJSPP",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-64)),
		isnull(convert(smallint, @c_scale), 
		       convert(smallint, @d_numeric_scale)) +
			convert(smallint, isnull(@d_aux,
			ascii(substring("<<<<<<<<<<<<<<?",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60)),
		@d_numeric_radix,
		/* set nullability from status flag */
		convert(smallint, convert(bit, @c_status&8)),
		convert(varchar(254),null),	/* Remarks are NULL */
                @column_default,
                isnull(@d_sql_data_type,
			@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60))),
		convert(smallint,NULL),
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(@c_type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision 
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint, 
			substring('0111111', 
			charindex(char(@c_type), 
			@char_bin_types)+1, 1)) * 
			/* calculate the precision */
			isnull(convert(int, @c_prec),
			isnull(convert(int, @d_data_precision),
			convert(int,@c_length)))
			+isnull(@d_aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		convert(int,@c_colid),
		rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, @c_status&8))*3)+1, 3)))

	fetch odbc_columns_cursor2 into
	@c_cdefault,
	@c_colid,
	@c_length,
	@c_name,
	@c_prec,
	@c_scale,
	@c_status,
	@c_type,
	@d_aux, 
	@d_data_precision,
	@d_data_type,
	@d_numeric_radix,
	@d_numeric_scale,
	@d_sql_data_type,
	@d_ss_dtype,
	@d_type_name,
	@o_name,
	@o_uid,
	@xtname,
	@ident
              
	end  /* end of if */              

	end /* while loop */
	deallocate cursor odbc_columns_cursor2
    end
    else
    begin
	/* 
	** This block is for the case where there IS pattern
	** matching done on the table name. 
	*/
	if @table_owner is null /* If owner not supplied, match all */
			select @table_owner = '%'

	declare odbc_columns_cursor3 cursor for
	select
		c.cdefault,
		c.colid,
		c.length,
		c.name,
		c.prec,
		c.scale,
		c.status,
		c.type,
		d.aux, 
		d.data_precision,
		d.data_type,
		d.numeric_radix,
		d.numeric_scale,
		d.sql_data_type,
		d.ss_dtype,
		    case 
		     when c.usertype = 80 then t.name
		     when c.usertype = 24 then t.name
		     when c.usertype = 25 then t.name
		    else
			  d.type_name
		    end,               
		o.name,
		o.uid,
		xtname,
		convert(bit, (c.status & 0x80))
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		sysxtypes x,
		systypes t
	WHERE
		o.name like @table_name
		AND user_name(o.uid) like @table_owner
		AND o.id = c.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		AND t.type = d.ss_dtype
		AND o.type != 'P'
		AND c.xtype *= x.xtid
		AND c.name like @column_name
--	AND d.ss_dtype IN (111, 109, 38, 110)	/* Just *N types */
 	AND d.ss_dtype IN (111, 109, 38, 110, 68)	/* Just *N types */	
		AND c.usertype < 100

        open odbc_columns_cursor3

	fetch odbc_columns_cursor3 into
		@c_cdefault,
		@c_colid,
		@c_length,
		@c_name,
		@c_prec,
		@c_scale,
		@c_status,
		@c_type,
		@d_aux, 
		@d_data_precision,
		@d_data_type,
		@d_numeric_radix,
		@d_numeric_scale,
		@d_sql_data_type,
		@d_ss_dtype,
		@d_type_name,
		@o_name,
		@o_uid,
		@xtname,
		@ident


        /* INTn, FLOATn, DATETIMEn and MONEYn types */

        while (@@sqlstatus = 0)
        begin
	  if (@c_cdefault is NOT NULL)
	  begin
          	exec sp_drv_column_default @c_cdefault, @column_default out
           	select @cdefault_len= datalength(@column_default)

		  if (@cdefault_len > @max_cdefault_len)
		  	select @column_default = "TRUNCATED"
          
          /* INTn, FLOATn, DATETIMEn and MONEYn types */
		INSERT INTO #odbc_columns values(
		DB_NAME(),
		USER_NAME(@o_uid),
		@o_name,
		@c_name,
		@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60)),
		/* TYPE_NAME */
		case
	            	when @ident = 1 then 
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))+' identity'
	            	else
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))
		end,
		isnull(convert(int, @c_prec),
			isnull(convert(int, @d_data_precision),
				 convert(int, @c_length)))
			+isnull(@d_aux, convert(int,
			ascii(substring("???AAAFFFCKFOLS",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		isnull(convert(int, @c_length), 
			convert(int,@c_length)) +
			   convert(int, isnull(@d_aux,
			ascii(substring("AAA<BB<DDDHJSPP",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-64)),
		isnull(convert(smallint, @c_scale), 
		       convert(smallint, @d_numeric_scale)) +
			convert(smallint, isnull(@d_aux,
			ascii(substring("<<<<<<<<<<<<<<?",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60)),
		@d_numeric_radix,
		/* set nullability from status flag */
		convert(smallint, convert(bit, @c_status&8)),
		convert(varchar(254),null),	/* Remarks are NULL */
                @column_default,
                isnull(@d_sql_data_type,
			@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60))),
		convert(smallint,NULL),
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(@c_type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision 
		** if not, return a 0 and multiply it by the precision
		*/
		convert(smallint, 
                    	substring('0111111', 
                       	charindex(char(@c_type), 
			@char_bin_types)+1, 1)) * 
                	/* calculate the precision */
                	isnull(convert(int, @c_prec),
                    	isnull(convert(int, @d_data_precision),
                       	convert(int,@c_length)))
                    	+isnull(@d_aux, convert(int,
                       	ascii(substring('???AAAFFFCKFOLS',
                       	2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		convert(int,@c_colid),
                rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, @c_status&8))*3)+1, 3)))
	fetch odbc_columns_cursor3 into
		@c_cdefault,
		@c_colid,
		@c_length,
		@c_name,
		@c_prec,
		@c_scale,
		@c_status,
		@c_type,
		@d_aux, 
		@d_data_precision,
		@d_data_type,
		@d_numeric_radix,
		@d_numeric_scale,
		@d_sql_data_type,
		@d_ss_dtype,
		@d_type_name,
		@o_name,
		@o_uid,
		@xtname,
		@ident
           end 	/* end of if	*/

        end /* while loop */

	deallocate cursor odbc_columns_cursor3
        declare odbc_columns_cursor4 cursor for
        SELECT 
               c.cdefault,
               c.colid,
               c.length,
               c.name,
               c.prec,
               c.scale,
               c.status,
               c.type,
               d.aux, 
               d.data_precision,
               d.data_type,
               d.numeric_radix,
               d.numeric_scale,
               d.sql_data_type,
               d.ss_dtype,
		    case 
		     when c.usertype = 80 then t.name
		     when c.usertype = 24 then t.name
		     when c.usertype = 25 then t.name
		    else
			  d.type_name
		    end,               
               o.name,
               o.uid,
               xtname,
               convert(bit, (c.status & 0x80))
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		sysxtypes x,
		systypes t
	WHERE
		o.name like @table_name
		AND user_name(o.uid) like @table_owner
		AND o.id = c.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		/*
		** We need a equality join with 
		** sybsystemprocs.dbo.spt_datatype_info here so that
		** there is only one qualified row returned from 
		** sybsystemprocs.dbo.spt_datatype_info, thus avoiding
		** duplicates.
		*/
		AND t.type = d.ss_dtype
		AND c.name like @column_name
		AND o.type != 'P'
		AND c.xtype *= x.xtid
		AND c.name like @column_name
--	AND (d.ss_dtype NOT IN (111, 109, 38, 110) /* No *N types */
 	AND (d.ss_dtype NOT IN (111, 109, 38, 110, 68) /* No *N types */
			OR c.usertype >= 100) /* User defined types */

	open odbc_columns_cursor4

	fetch odbc_columns_cursor4 into
		@c_cdefault,
		@c_colid,
		@c_length,
		@c_name,
		@c_prec,
		@c_scale,
		@c_status,
		@c_type,
		@d_aux, 
		@d_data_precision,
		@d_data_type,
		@d_numeric_radix,
		@d_numeric_scale,
		@d_sql_data_type,
		@d_ss_dtype,
		@d_type_name,
		@o_name,
		@o_uid,
		@xtname,
		@ident


        while (@@sqlstatus = 0)
        begin
	  if (@c_cdefault is NOT NULL)
	  begin
	        exec sp_drv_column_default @c_cdefault, @column_default out
           	select @cdefault_len= datalength(@column_default)

		if (@cdefault_len > @max_cdefault_len)
			select @column_default = "TRUNCATED"
          
          /* All other types including user data types */
		INSERT INTO #odbc_columns values(
		/* TABLE_CAT */
		DB_NAME(),
            	/* TABLE_SCHEM */
		USER_NAME(@o_uid),
		/* TABLE_NAME */
		@o_name,
		/*COLUMN_NAME*/
		@c_name,
		/* DATA_TYPE */
		@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60)),
		/* TYPE_NAME */
		case
	            	when @ident = 1 then 
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))+' identity'
	            	else
			rtrim(substring(@d_type_name,
			1+isnull(@d_aux,
			ascii(substring("III<<<MMMI<<A<A",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60), 18))
		end,
		/* COLUMN_SIZE */  	
		isnull(convert(int, @c_prec),
			isnull(convert(int, @d_data_precision),
			convert(int,@c_length)))
			+isnull(@d_aux, convert(int,
			ascii(substring("???AAAFFFCKFOLS",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		/* BUFFER_LENGTH */ 			
		isnull(convert(int, @c_length), 
			convert(int, @c_length)) +
			convert(int, isnull(@d_aux,
			ascii(substring("AAA<BB<DDDHJSPP",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-64)),
		/* DECIMAL_DIGITS */ 	
		isnull(convert(smallint, @c_scale),
			convert(smallint, @d_numeric_scale)) +
			convert(smallint, isnull(@d_aux,
			ascii(substring("<<<<<<<<<<<<<<?",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,
			1))-60)),
		/* NUM_PREC_RADIX */	
		@d_numeric_radix,
		/* NULLABLE */
		/* set nullability from status flag */
		convert(smallint, convert(bit, @c_status&8)),
		/* REMARKS */
		convert(varchar(254),null),
		/* COLUMN_DEF */
                @column_default,
                /* SQL_DATA_TYPE */
                isnull(@d_sql_data_type,
			@d_data_type+convert(smallint,
			isnull(@d_aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))
			-60))),
		/* SQL_DATETIME_SUB */	
		convert(smallint,NULL),
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(@c_type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   else
            	**       set char_octet_length = 0;
            	*/
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision 
		** if not, return a 0 and multiply it by the precision
		*/
		/* CHAR_OCTET_LENGTH */
		convert(smallint, 
			substring('0111111', 
			charindex(char(@c_type), 
			@char_bin_types)+1, 1)) * 
			/* calculate the precision */
			isnull(convert(int, @c_prec),
			isnull(convert(int, @d_data_precision),
			convert(int,@c_length)))
			+isnull(@d_aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			2*(@d_ss_dtype%35+1)+2-8/@c_length,1))-60)),
		/* ORDINAL_POSITION */	
		convert(int,@c_colid),
		/* IS_NULLABLE */
		rtrim(substring('NO YES',
                	(convert(smallint, convert(bit, @c_status&8))*3)+1, 3)))
	fetch odbc_columns_cursor4 into
		@c_cdefault,
		@c_colid,
		@c_length,
		@c_name,
		@c_prec,
		@c_scale,
		@c_status,
		@c_type,
		@d_aux, 
		@d_data_precision,
		@d_data_type,
		@d_numeric_radix,
		@d_numeric_scale,
		@d_sql_data_type,
		@d_ss_dtype,
		@d_type_name,
		@o_name,
		@o_uid,
		@xtname,
		@ident
           end	/* end of if 	*/

         end /* while loop */ 
         
         deallocate cursor odbc_columns_cursor4
end
SELECT * FROM #odbc_columns ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION
drop table #odbc_columns
if (@startedInTransaction = 1)
   rollback transaction odbc_keep_temptable_tx    

return(0)
go
exec sp_procxmode 'sp_odbc_columns', 'anymode'
go
grant execute on sp_odbc_columns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_datatype_info')
begin
	drop procedure sp_odbc_datatype_info
end
go





/* 
** Sccsid = "%Z% generic/sproc/%M% %I% %G%"
**
** History:
**	mm/yy		Author					Comments
**	12/06		Meena Ramakrishnan		Changes to conform to the ODBC API 
**										of returning the system types in any
**										given sql data type first before the user defined types
**	
**	This stored procedure has been ported from the ASE stored procedure sp_datatype_info
**
**	10.0	steven	1.1	07/13/93	sproc/src/datatype_info
**						Ported from MS catalog SP's
**
** Implementation Notes:
** 	The messiness of 'sp_odbc_data_type_info' was to get around the
** problem of returning the correct lengths for user defined types.  The
** join on the type name ensures all user defined types are returned, but
** this puts a null in the data_type column.  By forcing an embedded
** select and correlating it with the current row in systypes, we get the
** correct data_type mapping even for user defined types.  
**
**	parameters: data_type  of type int
*/

create procedure sp_odbc_datatype_info
@data_type int = 0,			/* Provide datatype_info for type # */
@odbc_ver  int = 3			/* Provide result set for ODBC 3.0 API # */
as
declare @tname varchar(30)
declare @datatype smallint
declare @data_precision int
declare @literal_prefix varchar(30)
declare @literal_suffix varchar(30)
declare @create_params	varchar(30)
declare @nullable	smallint
declare @case_sensitive	smallint
declare @searchable	smallint
declare @unsigned_attribute smallint
declare	@money	smallint
declare	@auto_increment	smallint
declare	@local_type_name	varchar(30)
declare	@minimum_scale	smallint
declare	@maximum_scale	smallint
declare	@sql_data_type	smallint
declare	@sql_datetime_sub smallint
declare	@num_prec_radix	int
declare	@interval_precision	smallint
declare @usertype smallint
declare @startedInTransaction bit

if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0
                                                       

if (@startedInTransaction = 1)
   save transaction odbc_keep_temptable_tx    
   
	
	create table #spt_odbc_datatypes 
	(
	id			numeric(20,0) identity,
	spid			smallint ,
	TYPE_NAME		varchar (30) not null,
	DATA_TYPE		smallint not null,
	COLUMN_SIZE		int null,
	LITERAL_PREFIX		varchar (30) null,
	LITERAL_SUFFIX		varchar (30) null,
	CREATE_PARAMS		varchar (30) null,
	NULLABLE		smallint not null,
	CASE_SENSITIVE		smallint not null,
	SEARCHABLE		smallint not null,
	UNSIGNED_ATTRIBUTE	smallint null,
	FIXED_PREC_SCALE	smallint not null,
	AUTO_UNIQUE_VALUE	smallint null,
	LOCAL_TYPE_NAME		varchar (30) default 'NULL',
	MINIMUM_SCALE		smallint null,
	MAXIMUM_SCALE		smallint null,
	SQL_DATA_TYPE		smallint not null,
	SQL_DATETIME_SUB	smallint null,
	NUM_PREC_RADIX		int null,
	INTERVAL_PRECISION	smallint null,
	USER_TYPE		smallint null,
	constraint odbc_datatypes_pk primary key(id,spid)) 

   

if (@data_type = 93)
  select @data_type = 11
if (@data_type = 92)
  select @data_type = 10
if (@data_type = 91)
  select @data_type = 9
	if (select @data_type) = 0
		begin
		declare  cur_odbc_datatype_info1 cursor
		for
		select	/* Real SQL Server data types */
			TYPE_NAME = 
				    case 
				     when t.name = 'usmallint' then 'unsigned smallint'
				     when t.name = 'uint' then 'unsigned int'
				     when t.name = 'ubigint' then 'unsigned bigint'
				    else
				    	 t.name
				    end,
			DATA_TYPE = case					
					when d.data_type = 11 and @odbc_ver = 3 then convert(smallint,93)
				     	when d.data_type = 9  and @odbc_ver = 3 then convert(smallint,91)
				    	when d.data_type = 10 and @odbc_ver = 3 then convert(smallint,92)
				    	when t.name ='univarchar'and @odbc_ver = 3 then convert(smallint,-9)
					when t.name ='unichar' and @odbc_ver = 3 then convert(smallint,-8)
					when t.name ='univarchar'and @odbc_ver = 2 then convert(smallint,-9)
					when t.name ='unichar' and @odbc_ver = 2 then convert(smallint,-8)
				    else 
				    	d.data_type
				    end, 
			COLUMN_SIZE = case
						 when t.name in ('univarchar', 'unichar') then isnull(d.data_precision,convert(int,t.length))/2
						else
						isnull(d.data_precision,convert(int,t.length))
						end,
			LITERAL_PREFIX = d.literal_prefix,
			LITERAL_SUFIX = d.literal_suffix,
			CREATE_PARAMS = case  
							when e.create_params in ('max length') then 'length'
							when d.data_type in (1,12) then 'length'
							else
							e.create_params
							end,
			NULLABLE = d.nullable,
			CASE_SENSITIVE = d.case_sensitive,
			SEARCHABLE = d.searchable,
			UNSIGNED_ATTRIBUTE = d.unsigned_attribute,
			FIXED_PREC_SCALE = d.money,
			AUTO_UNIQUE_VALUE = d.auto_increment,
			LOCAL_TYPE_NAME = case when t.name in ('timestamp') then 'timestamp'
							else
							d.local_type_name
							end,
			MINIMUM_SCALE = case 
					when d.data_type in (11,10) then convert(smallint,0)
					else
					d.minimum_scale
					end,
			MAXIMUM_SCALE = case
					when d.data_type in (11, 10)  then convert(smallint,3)
						else
					d.minimum_scale
					end,
			SQL_DATA_TYPE = case
					when d.data_type in (11,10,9) then convert(smallint,9)
					when t.name ='univarchar' then convert(smallint,-9)
				    when t.name ='unichar' then convert(smallint,-8)
					else
					isnull(d.sql_data_type,
				d.data_type+convert(smallint,
                		isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        	2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        	-60)))
				end,
			SQL_DATETIME_SUB = case
					   when d.data_type = 11 then convert(smallint,3)
					   when d.data_type = 10 then convert(smallint,2)
					   when d.data_type = 9 then convert(smallint,1)
					else
					d.sql_datetime_sub
					end,
			NUM_PREC_RADIX = case
							when d.data_type in (7,6,5,4,3,2,-7,-6) then convert(int,10)
							else
							 convert(int,d.num_prec_radix)
							end,
			INTERVAL_PRECISION = d.interval_precision,
			USERTYPE = t.usertype
		from 	sybsystemprocs.dbo.spt_datatype_info d, syscolumns c,
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			d.ss_dtype = t.type
			and t.usertype *= e.user_type
			and c.type =* d.ss_dtype
			    /* restrict results to "real" datatypes */
			and t.name not in ("nchar","nvarchar",
					   "sysname","longsysname","timestamp",
					   "datetimn","floatn","intn","moneyn","uintn")
			and t.usertype < 100	/* No user defined types */
		
		UNION
		
		select	/* SQL Server user data types */
			TYPE_NAME = 
				    case 
				     when t.name = 'usmallint' then 'unsigned smallint'
				     when t.name = 'uint' then 'unsigned int'
				     when t.name = 'ubigint' then 'unsigned bigint'
				    else
				    	 t.name
				    end,
			DATA_TYPE = case 
						when d.data_type = 11 and @odbc_ver = 3 then convert(smallint,93)
				     		when d.data_type = 9  and @odbc_ver = 3 then convert(smallint,91)
				    		when d.data_type = 10 and @odbc_ver = 3 then convert(smallint,92)
						when t.name ='univarchar'and @odbc_ver = 3 then convert(smallint,-9)
						when t.name ='unichar' and @odbc_ver = 3 then convert(smallint,-8)
						when t.name ='univarchar'and @odbc_ver = 2 then convert(smallint,-9)
						when t.name ='unichar' and @odbc_ver = 2 then convert(smallint,-8)
						else 
				    		d.data_type
						end,
			COLUMN_SIZE =	case
								when t.name in ('univarchar', 'unichar') then isnull(d.data_precision,convert(int,t.length))/2
							else
								isnull(d.data_precision,convert(int,t.length))
							end,
			LITERAL_PREFIX = d.literal_prefix,
			LITERAL_SUFIX = d.literal_suffix,
			CREATE_PARAMS = case  
							when e.create_params in ('max length') then 'length'
							when d.data_type in (1,12) then 'length'
							else
							e.create_params
							end,
			NULLABLE = d.nullable,
			CASE_SENSITIVE = d.case_sensitive,
			SEARCHABLE = d.searchable,
			UNSIGNED_ATTRIBUTE = d.unsigned_attribute,
			FIXED_PREC_SCALE = d.money,
			AUTO_UNIQUE_VALUE = d.auto_increment,
			LOCAL_TYPE_NAME =case when t.name in ('timestamp') then 'timestamp'
							else
							d.local_type_name
							end,
			MINIMUM_SCALE = case 
					when d.data_type in (11,10) then convert(smallint,0)
					else
					d.minimum_scale
					end,
			MAXIMUM_SCALE = case
					when d.data_type in (11, 10)  then convert(smallint,3)
					else
					d.minimum_scale
					end,
			SQL_DATA_TYPE = case
					when d.data_type in (11,10,9) then convert(smallint,9)
					 when t.name ='univarchar' then convert(smallint,-9)
				    when t.name ='unichar' then convert(smallint,-8)
					else
					isnull(d.sql_data_type,
				d.data_type+convert(smallint,
                		isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        	2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        	-60)))
				end,
			SQL_DATETIME_SUB = case
					   when d.data_type =11 then convert(smallint,3)
					   when d.data_type = 10 then convert(smallint,2)
					   when d.data_type = 9 then convert(smallint,1)
					else
					d.sql_datetime_sub
					end,
			NUM_PREC_RADIX = case
							when d.data_type in (7,6,5,4,3,2,-7,-6) then convert(int,10)
							else
							 convert(int,d.num_prec_radix)
							end,
			INTERVAL_PRECISION = d.interval_precision,
			USERTYPE =t.usertype
		from 	sybsystemprocs.dbo.spt_datatype_info d, syscolumns c,
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			d.ss_dtype = t.type
			and t.usertype *= e.user_type
			and c.type =* d.ss_dtype
			    /* 
			    ** Restrict to user defined types (value > 100)
			    ** and Sybase user defined types (listed)
			    */
			and (t.name in ("nchar","nvarchar","sysname","timestamp")
			    or t.usertype >= 100)      /* User defined types */
		order by  USERTYPE
		
		open cur_odbc_datatype_info1
		fetch cur_odbc_datatype_info1 into
		@tname,
		@datatype,
		@data_precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@money,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix,
		@interval_precision,
		@usertype
		
		while (@@sqlstatus = 0)
		begin
		insert into  #spt_odbc_datatypes values(
		@@spid,
		@tname,
		@datatype,
		@data_precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@money,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix,	
		@interval_precision,
		@usertype)

		fetch cur_odbc_datatype_info1 into
		@tname,
		@datatype,
		@data_precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@money,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix,	
		@interval_precision,
		@usertype
		end /* while */
		deallocate cursor cur_odbc_datatype_info1
					
		
		end /*	if	*/
	else
		begin
		declare  cur_odbc_datatype_info3 cursor
		for		
		select	/* Real SQL Server data types */
			TYPE_NAME = case 
							when t.name = 'usmallint' then 'unsigned smallint'
							when t.name = 'uint' then 'unsigned int'
							when t.name = 'ubigint' then 'unsigned bigint'
						else
				    		t.name
						end,
			DATA_TYPE = case 
						when d.data_type = 11 and @odbc_ver = 3 then convert(smallint,93)
				     		when d.data_type = 9  and @odbc_ver = 3 then convert(smallint,91)
				    		when d.data_type = 10 and @odbc_ver = 3 then convert(smallint,92)
						when t.name ='univarchar'and @odbc_ver = 3 then convert(smallint,-9)
						when t.name ='unichar' and @odbc_ver = 3 then convert(smallint,-8)
						when t.name ='univarchar'and @odbc_ver = 2 then convert(smallint,-9)
						when t.name ='unichar' and @odbc_ver = 2 then convert(smallint,-8)
						else 
				    		d.data_type
						end,
			COLUMN_SIZE =	case
								when t.name in ('univarchar', 'unichar') then isnull(d.data_precision,convert(int,t.length))/2
							else
								isnull(d.data_precision,convert(int,t.length))
							end,
			LITERAL_PREFIX = d.literal_prefix,
			LITERAL_SUFIX = d.literal_suffix,
			CREATE_PARAMS = case  
								when e.create_params in ('max length') then 'length'
								when d.data_type in (1,12) then 'length'
							else
								e.create_params
							end,
			NULLABLE = d.nullable,
			CASE_SENSITIVE = d.case_sensitive,
			SEARCHABLE = d.searchable,
			UNSIGNED_ATTRIBUTE = d.unsigned_attribute,
			FIXED_PREC_SCALE = d.money,
			AUTO_UNIQUE_VALUE = d.auto_increment,
			LOCAL_TYPE_NAME =	case 
									when t.name in ('timestamp') then 'timestamp'
								else
									d.local_type_name
								end,
			MINIMUM_SCALE = case 
								when d.data_type in (11,10) then convert(smallint,0)
							else
								d.minimum_scale
							end,
			MAXIMUM_SCALE = case
								when d.data_type in (11, 10)  then convert(smallint,3)
							else
								d.minimum_scale
							end,	
			SQL_DATA_TYPE = case
								when d.data_type in (11,10,9) then convert(smallint,9)
								when t.name ='univarchar' then convert(smallint,-9)
								when t.name ='unichar' then convert(smallint,-8)
							else
								isnull(d.sql_data_type,
								d.data_type+convert(smallint,
                				isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        		2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        		-60)))
							end,
			SQL_DATETIME_SUB =	case
									when d.data_type =11 then convert(smallint,3)
									when d.data_type = 10 then convert(smallint,2)
									when d.data_type = 9 then convert(smallint,1)
								else
									d.sql_datetime_sub
								end,
			NUM_PREC_RADIX =	case
									when d.data_type in (7,6,5,4,3,2,-7,-6) then convert(int,10)
								else
									convert(int,d.num_prec_radix)
								end,
			INTERVAL_PRECISION = d.interval_precision,
			USERTYPE=t.usertype
		from 	sybsystemprocs.dbo.spt_datatype_info d,syscolumns c, 
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			data_type = @data_type
			and d.ss_dtype = t.type
			and t.usertype *= e.user_type
			and c.type =* d.ss_dtype
			    /* restrict results to "real" datatypes */
			and t.name not in ("nchar","nvarchar",
					   "sysname","longsysname","timestamp",
					   "datetimn","floatn","intn","moneyn","uintn")
			and t.usertype < 100	/* No user defined types */
	
		UNION	
		select	/* SQL Server and user data types */
			TYPE_NAME = 
				    case 
				     when t.name = 'usmallint' then 'unsigned smallint'
				     when t.name = 'uint' then 'unsigned int'
				     when t.name = 'ubigint' then 'unsigned bigint'
				    else
				    	 t.name
				    end,
			DATA_TYPE = case 
						when d.data_type = 11 and @odbc_ver = 3 then convert(smallint,93)
				     		when d.data_type = 9  and @odbc_ver = 3 then convert(smallint,91)
				    		when d.data_type = 10 and @odbc_ver = 3 then convert(smallint,92)
						when t.name ='univarchar'and @odbc_ver = 3 then convert(smallint,-9)
						when t.name ='unichar' and @odbc_ver = 3 then convert(smallint,-8)
						when t.name ='univarchar'and @odbc_ver = 2 then convert(smallint,-9)
						when t.name ='unichar' and @odbc_ver = 2 then convert(smallint,-8)
						else 
				    		d.data_type
						end,
			COLUMN_SIZE =	case
							when t.name in ('univarchar','unichar') then isnull(d.data_precision,convert(int,t.length))/2
							else
							isnull(d.data_precision,convert(int,t.length))
							end,
			LITERAL_PREFIX = d.literal_prefix,
			LITERAL_SUFIX = d.literal_suffix,
			CREATE_PARAMS = case  
							when e.create_params in ('max length') then 'length'
							when d.data_type in (1,12) then 'length'
							else
							e.create_params
							end,
			NULLABLE = d.nullable,
			CASE_SENSITIVE = d.case_sensitive,
			SEARCHABLE = d.searchable,
			UNSIGNED_ATTRIBUTE = d.unsigned_attribute,
			FIXED_PREC_SCALE = d.money,
			AUTO_UNIQUE_VALUE = d.auto_increment,
			LOCAL_TYPE_NAME = case when t.name in ('timestamp') then 'timestamp'
							else
							d.local_type_name
							end,
			MINIMUM_SCALE = case 
					when d.data_type in (11,10) then convert(smallint,0)
					else
					d.minimum_scale
					end,
			MAXIMUM_SCALE = case
					when d.data_type in (11, 10)  then convert(smallint,3)
					else
					d.minimum_scale
					end,
			SQL_DATA_TYPE = case
					when d.data_type in (11,10,9) then convert(smallint,9)
					 when t.name ='univarchar' then convert(smallint,-9)
				    when t.name ='unichar' then convert(smallint,-8)
					else
					isnull(d.sql_data_type,
				d.data_type+convert(smallint,
                		isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        	2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        	-60)))
				end,
			SQL_DATETIME_SUB = case
					   when d.data_type =11 then convert(smallint,3)
					     when d.data_type = 10 then convert(smallint,2)
					   when d.data_type = 9 then convert(smallint,1)
					else
					d.sql_datetime_sub
					end,
			NUM_PREC_RADIX = case
							when d.data_type in (7,6,5,4,3,2,-7,-6) then convert(int,10)
							else
							 convert(int,d.num_prec_radix)
							end,
			INTERVAL_PRECISION = d.interval_precision,
			USERTYPE=t.usertype
		from 	sybsystemprocs.dbo.spt_datatype_info d, syscolumns c,
			sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
		where
			data_type = @data_type
			and d.ss_dtype = t.type
			and t.usertype *= e.user_type
			and c.type =* d.ss_dtype
			    /* 
			    ** Restrict to user defined types (value > 100)
			    ** and Sybase user defined types (listed)
			    */
			and (t.name in ("nchar","nvarchar","sysname","timestamp")
			    or t.usertype >= 100)     /* User defined types */
		order by  USERTYPE
	
			open cur_odbc_datatype_info3
		fetch cur_odbc_datatype_info3 into
		@tname,
		@datatype,
		@data_precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@money,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix,
		@interval_precision,
		@usertype
		while (@@sqlstatus = 0)
		begin
		insert into  #spt_odbc_datatypes values(
		@@spid,
		@tname,
		@datatype,
		@data_precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@money,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix,	
		@interval_precision,
		@usertype)

		fetch cur_odbc_datatype_info3 into
		@tname,
		@datatype,
		@data_precision,
		@literal_prefix,
		@literal_suffix,
		@create_params,
		@nullable,
		@case_sensitive,
		@searchable,
		@unsigned_attribute,
		@money,
		@auto_increment,
		@local_type_name,
		@minimum_scale,
		@maximum_scale,
		@sql_data_type,
		@sql_datetime_sub,
		@num_prec_radix,	
		@interval_precision,
		@usertype
		end /*while */
		deallocate cursor cur_odbc_datatype_info3
		
		end /* else */
		
select 	TYPE_NAME,
		DATA_TYPE,
		COLUMN_SIZE,
		LITERAL_PREFIX,
		LITERAL_SUFFIX,
		CREATE_PARAMS,
		NULLABLE,
		CASE_SENSITIVE,
		SEARCHABLE,
		UNSIGNED_ATTRIBUTE,
		FIXED_PREC_SCALE,
		AUTO_UNIQUE_VALUE,
		LOCAL_TYPE_NAME,
		MINIMUM_SCALE,
		MAXIMUM_SCALE,
		SQL_DATA_TYPE,
		SQL_DATETIME_SUB,
		NUM_PREC_RADIX,
		INTERVAL_PRECISION
from #spt_odbc_datatypes 
group by SQL_DATA_TYPE
order by  DATA_TYPE, USER_TYPE, TYPE_NAME

drop table #spt_odbc_datatypes 
if (@startedInTransaction = 1)
   rollback transaction odbc_keep_temptable_tx    

return (0)
go
exec sp_procxmode 'sp_odbc_datatype_info', 'anymode'
go
grant execute on sp_odbc_datatype_info to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getversioncolumns')
begin
	drop procedure sp_odbc_getversioncolumns
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	10.0	1.0	9 JUL 93	sproc/src/special_columns */

/* 
** Messages for "sp_odbc_getversioncolumns"
**
** 17863, "There is no table named %1! in the current database."
** 18039, "Table qualifier must be name of current database."
** 18042, "Illegal value for 'col_type' argument. Legal values are 'V' or 'R'."
**
*/

create procedure sp_odbc_getversioncolumns (
				 @table_name		varchar(771),
				 @table_owner		varchar(32) = null,
				 @table_qualifier	varchar(32) = null,
				 @col_type		char(1) = 'R' )
as
	declare @indid			int
	declare @table_id		int
	declare @dbname			varchar(255)
	declare @full_table_name	varchar(1543)
	declare @version		varchar(32)

	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

	/* get database name */
	select @dbname = db_name()

	/* we don't want a temp table unless we're in tempdb */
	if (@table_name like "#%" and @dbname != db_name(tempdb_id()))
-- 	if (@table_name like "#%" and @dbname != 'tempdb')		-- 12.0
-- 	if @table_name like "#%" and @dbname != db_name(tempdb_id())	-- 12.5

	begin	
		/* 17863, "There is no table named %1! in the current database." */
		raiserror 17863, @table_name
		return (1)
	end

	if @table_qualifier is not null
	begin
		if @dbname != @table_qualifier
		begin	
			/* 18039, "Table qualifier must be name of current database." */
			raiserror 18039
			return (1)
		end
	end

	if @table_owner is null
	begin	/* if unqualified table name */
		select @full_table_name = @table_name
	end
	else
	begin	/* qualified table name */
		select @full_table_name = @table_owner + '.' + @table_name
	end

	/* get object ID */
	select @table_id = object_id(@full_table_name)

	if @col_type = 'V'
	begin /* if ROWVER, just run that query */
		select
			SCOPE = convert(smallint, 0),
			COLUMN_NAME = c.name,
			DATA_TYPE = d.data_type + convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
			TYPE_NAME = t.name,
			COLUMN_SIZE = isnull(d.data_precision,
					convert(int,c.length))
					+ isnull(d.aux, convert(int,
					ascii(substring("???AAAFFFCKFOLS",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
			BUFFER_LENGTH = isnull(d.length, convert(int,c.length))
					+ convert(int,
					isnull(d.aux,
					ascii(substring("AAA<BB<DDDHJSPP",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-64)),
			DECIMAL_DIGITS = d.numeric_scale + convert(smallint,
					isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-60)),
			PSEUDO_COLUMN=convert(smallint,1)						
		from
			systypes t, syscolumns c, sybsystemprocs.dbo.spt_datatype_info d
		where
			c.id = @table_id
			and c.type = d.ss_dtype
			and c.usertype = 80	/* TIMESTAMP */
			and t.usertype = 80	/* TIMESTAMP */
			
		return (0)
	end

	if @col_type != 'R'
	begin
		/* 18042, "Illegal value for 'col_type' argument. Legal values are 'V' or 'R'." */

		raiserror 18042
		return (1)
	end

	/* An identity column is the most optimal unique identifier */
	if exists (select colid from syscolumns
		where id = @table_id and (status&128) = 128)
	begin
	    select
		SCOPE = convert(smallint, 0),
		COLUMN_NAME = c.name,
		DATA_TYPE = d.data_type + convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		TYPE_NAME = rtrim(substring(d.type_name,
					1 + isnull(d.aux,
					ascii(substring("III<<<MMMI<<A<A",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-60), 18)),
		COLUMN_SIZE = isnull(d.data_precision, convert(int,c.length))
					+ isnull(d.aux, convert(int,
					ascii(substring("???AAAFFFCKFOLS",
					2*(d.ss_dtype%35+1)+2-8/c.length,1))
					-60)),
		BUFFER_LENGTH = isnull(d.length, convert(int,c.length))
					+ convert(int, isnull(d.aux,
					ascii(substring("AAA<BB<DDDHJSPP",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-64)),
		DECIMAL_DIGITS = d.numeric_scale + convert(smallint,
					isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					2*(d.ss_dtype%35+1)+2-8/c.length, 1))
					-60)),
		PSEUDO_COLUMN=convert(smallint,1)					
	    from
		syscolumns c,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	    where
		c.id = @table_id
		and (c.status&128) = 128
		and c.type = d.ss_dtype
		and c.usertype *= t.usertype

	    return (0)
	end

	/* ROWID, now find the id of the 'best' index for this table */

	select @indid = (
		select min(indid)
		from sysindexes
		where
			status & 2 = 2		/* if unique index */
			and id = @table_id
			and indid > 0)		/* eliminate table row */

	 select
		SCOPE = convert(smallint, 0),
		COLUMN_NAME = index_col(@full_table_name,indid,c.colid),
		DATA_TYPE = d.data_type + convert(smallint,
					isnull(d.aux,
					ascii(substring("666AAA@@@CB??GG",
					2*(d.ss_dtype%35+1)+2-8/c2.length,1))
					-60)),
		TYPE_NAME = rtrim(substring(d.type_name,
					1 + isnull(d.aux,
					ascii(substring("III<<<MMMI<<A<A",
					2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
					-60), 18)),
		COLUMN_SIZE = isnull(d.data_precision, convert(int,c2.length))
					+ isnull(d.aux, convert(int,
					ascii(substring("???AAAFFFCKFOLS",
					2*(d.ss_dtype%35+1)+2-8/c2.length,1))
					-60)),
		BUFFER_LENGTH = isnull(d.length, convert(int,c2.length))
					+ convert(int, isnull(d.aux,
					ascii(substring("AAA<BB<DDDHJSPP",
					2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
					-64)),
		DECIMAL_DIGITS = d.numeric_scale + convert(smallint,
					isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					2*(d.ss_dtype%35+1)+2-8/c2.length, 1))
					-60)),
		PSEUDO_COLUMN=convert(smallint,1)					
	from
		sysindexes x,
		syscolumns c,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		syscolumns c2	/* self-join to generate list of index
				** columns and to extract datatype names */
	where
		x.id = @table_id
		and c2.name = index_col(@full_table_name, @indid,c.colid)
		and c2.id =x.id
		and c.id = x.id
		and c.colid < keycnt + (x.status & 16) / 16
		and x.indid = @indid
		and c2.type = d.ss_dtype
		and c2.usertype *= t.usertype

	return (0)
go
go
exec sp_procxmode 'sp_odbc_getversioncolumns', 'anymode'
go
grant execute on sp_odbc_getversioncolumns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getcolumnprivileges')
begin
	drop procedure sp_odbc_getcolumnprivileges
end
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_odbc_getcolumnprivileges ( 
                        @table_name  varchar(771),
                        @table_owner varchar(32) = null,
                        @table_qualifier varchar(32)= null,
                        @column_name varchar(771) = null)

as        

    declare @owner_id    		int
    declare @full_table_name    	varchar(1543)
    declare @tab_id 			int	    /* object id of the table specified */
    declare @startedInTransaction bit


    if (@@trancount > 0)
       select @startedInTransaction = 1
    else
       select @startedInTransaction = 0
                                                       


    set nocount on
    /*
    ** set the transaction isolation level
    */
    if @@trancount = 0
    begin
	   set chained off
    end
   
    set transaction isolation level 1

    if (@startedInTransaction = 1)
       save transaction odbc_keep_temptable_tx    

    /*
    **  Check to see that the table is qualified with database name
    */
    if @table_name like "%.%.%" 
    begin
		/* 18021, "Object name can only be qualified with owner name" */
		raiserror 18021
		return (1)
    end

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like "#%" and db_name() != db_name(tempdb_id()))
    begin
		/* 
		** 17676, "This may be a temporary object. Please execute 
		** procedure from your temporary database."
		*/
		raiserror 17676
		return (1)
    end

    /*
    ** The table_qualifier should be same as the database name. Do the sanity check
    ** if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
	/* set the table qualifier name */
	select @table_qualifier = db_name ()
    else
    begin
        if db_name() != @table_qualifier
        begin
			raiserror 18039
	     	return (1)
		end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name prefixed
    ** by the owner id
    */
    if (@table_owner is null) or (@table_owner = '')
	        select @full_table_name = @table_name
    else
    begin
	if (@table_name like "%.%") and
	    substring (@table_name, 1, charindex(".", @table_name) -1) != @table_owner
	begin
	 	/* 18011, Object name must be qualified with the owner name * */
		raiserror 18011
		return (1)
	end
	
	if not (@table_name like "%.%")
        	select @full_table_name = @table_owner + '.' + @table_name
	else
	        select @full_table_name = @table_name

    end

    /* 
    ** check to see if the specified table exists or not
    */

    select @tab_id = object_id(@full_table_name)
    if (@tab_id is null)
    begin
		raiserror 17492
		return (1)
    end


    /*
    ** check to see if the @tab_id indeeed represents a table or a view
    */

    if not exists (select * 
                  from   sysobjects
                  where (@tab_id = id) and
	                ((type = 'U') or
                        (type = 'S') or
		        (type = 'V')))
    begin
		raiserror 17492
		return (1)
    end
 

    /*
    ** if the column name is not specified, set the column name to wild 
	** character such it matches all the columns in the table
    */
    if @column_name is null
        select @column_name = '%'

    else
    begin
     /*
	 ** check to see if the specified column is indeed a column belonging
	 ** to the table
	 */
         if not exists (select * 
                        from syscolumns
			where (id = @tab_id) and
			      (name like @column_name))
	 begin
		raiserror 17563, @column_name
		return (1)
	end
    end

   /* Create temp table to store results from sp_aux_computeprivs */
    create table #results_table
	 (TABLE_CAT		varchar (32),
	  TABLE_SCHEM		varchar (32),
	  TABLE_NAME		varchar (255),
	  COLUMN_NAME		varchar (255) NULL,
	  GRANTOR		varchar (32),
	  GRANTEE 		varchar (32),
	  PRIVILEGE		varchar (32),
	  IS_GRANTABLE		varchar (3))


   /*
   ** declare cursor to cycle through all possible columns
   */
   declare cursor_columns cursor
	for select name from syscolumns 
	    where (id = @tab_id) 
	      and (name like @column_name)

   /*
   ** For each column in the list, generate privileges
   */
   open cursor_columns
   fetch cursor_columns into @column_name
   while (@@sqlstatus = 0)
   begin

	/* 
	** compute the table owner id
	*/

	select @owner_id = uid
	from   sysobjects
	where  id = @tab_id


	/*
	** get table owner name
	*/

	select @table_owner = name 
	from sysusers 
	where uid = @owner_id

	exec sp_odbc_computeprivs @table_name, @table_owner, @table_qualifier, 
			     @column_name, 1, @tab_id

	set nocount off 	

	fetch cursor_columns into @column_name
   end

   close cursor_columns
   deallocate cursor cursor_columns

   /* Print out results */ 
   select distinct * from #results_table
   order by COLUMN_NAME, GRANTEE

drop table #results_table
if (@startedInTransaction = 1)
   save transaction odbc_keep_temptable_tx    

return (0)
go
exec sp_procxmode 'sp_odbc_getcolumnprivileges', 'anymode'
go
grant execute on sp_odbc_getcolumnprivileges to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_tables')
begin
	drop procedure sp_odbc_tables
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	10.0	1.1	06/16/93	sproc/tables */

/*
** Messages for "sp_odbc_tables"         18039
**
** 17676, "This may be a temporary object. Please execute procedure from your 
**         temporary database."
**
** 18039, "Table qualifier must be name of current database"
**
*/
create procedure sp_odbc_tables
@table_name		varchar(771)  = null,
@table_owner     	varchar(32)  = null,
@table_qualifier 	varchar(32)  = null,
@table_type		varchar(100) = null
as

declare @type1 varchar(3)
declare @tableindex int


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* temp table */
if (@table_name like "#%" and
   db_name() != db_name(tempdb_id()))
begin
	/*
        ** Can return data about temp. tables only in session's temporary db
        */
		raiserror 17676
	return(1)
end

/*
** Special feature #1:	enumerate databases when owner and name
** are blank but qualifier is explicitly '%'.  
*/
if @table_qualifier = '%' and
	@table_owner = '' and
	@table_name = ''
begin	

	/*
	** If enumerating databases 
	*/
	select
		TABLE_CAT = name,
		TABLE_SCHEM = null,
		TABLE_NAME = null,
		TABLE_TYPE= 'Database',

		/*
		** Remarks are NULL 
		*/
		REMARKS = convert(varchar(254),null)

		from master..sysdatabases

		/*
		** eliminate MODEL database 
		*/
		where name != 'model'
		order by TABLE_CAT
end

/*
** Special feature #2:	enumerate owners when qualifier and name
** are blank but owner is explicitly '%'.
*/
else if @table_qualifier = '' and
	@table_owner = '%' and
	@table_name = ''
	begin	

		/*
		** If enumerating owners 
		*/
		select distinct
			TABLE_CAT = null,
			TABLE_SCHEM = user_name(uid),
			TABLE_NAME = null,
			TABLE_TYPE = 'Owner',

		/*
		** Remarks are NULL 
		*/
		REMARKS = convert(varchar(254),null)

		from sysobjects
		order by TABLE_SCHEM
	end
	else
	begin 
		/*
		** end of special features -- do normal processing 
		*/
		if @table_qualifier is not null
		begin
			if db_name() != @table_qualifier
			begin
				if @table_qualifier = ''
				begin  	

					/*
					** If empty qualifier supplied
					** Force an empty result set 
					*/
					select @table_name = ''
					select @table_owner = ''
				end
				else
				begin

					/*
					** If qualifier doesn't match current 
					** database. 
					*/
					raiserror 18039
					return 1
				end
			end
		end
		if @table_type is null
		begin	

			/*
			** Select all ODBC supported table types 
			*/
			select @type1 = 'SUV'
		end
		else
		begin
			/*
			** TableType are case sensitive if CS server 
			*/
			select @type1 = null

			/*
			** Add System Tables 
			*/
			if (charindex("'SYSTEM TABLE'",@table_type) != 0)
				select @type1 = @type1 + 'S'

			/*
			** Add User Tables 
			*/
			if (charindex("'TABLE'",@table_type) != 0)
				select @type1 = @type1 + 'U'

			/*
			** Add Views 
			*/
			if (charindex("'VIEW'",@table_type) != 0)
				select @type1 = @type1 + 'V'
		end
		if @table_name is null
		begin	

			/*
			** If table name not supplied, match all 
			*/
			select @table_name = '%'
		end
		else
		begin
			if (@table_owner is null) and 
			   (charindex('%', @table_name) = 0)
			begin	

			/*
			** If owner not specified and table is specified 
			*/
				if exists (select * from sysobjects
					where uid = user_id()
					and id = object_id(@table_name)
					and (type = 'U' or type = 'V' 
						or type = 'S'))
				begin	

				/*
				** Override supplied owner w/owner of table 
				*/
					select @table_owner = user_name()
				end
			end
		end


		/*
		** If no owner supplied, force wildcard 
		*/
		if @table_owner is null 
			select @table_owner = '%'
		select
			TABLE_CAT = db_name(),
			TABLE_SCHEM = user_name(o.uid),
			TABLE_NAME = o.name,
			TABLE_TYPE = rtrim ( 
					substring('SYSTEM TABLE            TABLE       VIEW       ',
					/*
					** 'S'=0,'U'=2,'V'=3 
					*/
					(ascii(o.type)-83)*12+1,12)),

			/*
			** Remarks are NULL
			*/
			REMARKS = convert(varchar(254),null)

		from sysobjects o
		where
			/* Special case for temp. tables.  Match ids */
			(o.name like @table_name or o.id=object_id(@table_name))
			and user_name(o.uid) like @table_owner

			/*
			** Only desired types
			*/
			and charindex(substring(o.type,1,1),@type1)! = 0 
		and (
                suser_id() = 1          /* User is the System Administrator */
                or o.uid = user_id()    /* User created the object */
                                        /* here's the magic..select the highest
                                        ** precedence of permissions in the
                                        ** order (user,group,public)
                                        */
 
                /*
                ** The value of protecttype is
                **
                **      0  for grant with grant
                **      1  for grant and,
                **      2  for revoke
                **
                ** As protecttype is of type tinyint, protecttype/2 is
                ** integer division and will yield 0 for both types of
                ** grants and will yield 1 for revoke, i.e., when
                ** the value of protecttype is 2.  The XOR (^) operation
                ** will reverse the bits and thus (protecttype/2)^1 will
                ** yield a value of 1 for grants and will yield a
                ** value of zero for revoke.
                **
	        ** For groups, uid = gid. We shall use this to our advantage.
                **
                ** If there are several entries in the sysprotects table
                ** with the same Object ID, then the following expression
                ** will prefer an individual uid entry over a group entry
                **
                ** For example, let us say there are two users u1 and u2
                ** with uids 4 and 5 respectiveley and both u1 and u2
                ** belong to a group g12 whose uid is 16390.  table t1
                ** is owned by user u0 and user u0 performs the following
                ** actions:
                **
                **      grant select on t1 to g12
                **      revoke select on t1 from u1
                **
                ** There will be two entries in sysprotects for the object t1,
                ** one for the group g12 where protecttype = grant (1) and
                ** one for u1 where protecttype = revoke (2).
                **
                ** For the group g12, the following expression will
                ** evaluate to:
                **
                **      ((abs(16390-16390)*2) + ((1/2)^1)
                **      = ((0) + (0)^1) = 0 + 1 = 1
                **
                ** For the user entry u1, it will evaluate to:
                **
                **      (((+)*abs(4-16390)*2) + ((2/2)^1))
                **      = (abs(-16386)*2 + (1)^1)
                **      = 16386*2 + 0 = 32772
                **
                ** As the expression evaluates to a bigger number for the
                ** user entry u1, select max() will chose 32772 which,
                ** ANDed with 1 gives 0, i.e., sp_odbc_tables will not display
                ** this particular table to the user.
                **
                ** When the user u2 invokes sp_odbc_tables, there is only one
                ** entry for u2, which is the entry for the group g12, and
                ** so the group entry will be selected thus allowing the
                ** table t1 to be displayed.
                **
		** ((select max((abs(uid-u.gid)*2)
	        ** 		+ ((protecttype/2)^1))
         	**
                ** Notice that multiplying by 2 makes the number an
                ** even number (meaning the last digit is 0) so what
                ** matters at the end is (protecttype/2)^1.
                **
                **/
 
                or ((select max((abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
                        from sysprotects p, sysusers u2
                        where p.id = o.id      /* outer join to correlate
                                                ** with all rows in sysobjects
                                                */
			and u2.uid = user_id()
			/*
			** get rows for public, current users, user's groups
			*/
		      	and (p.uid = 0 or 		/* public */
			     p.uid = user_id() or	/* current user */ 
			     p.uid = u2.gid)		/* users group */ 

			/*
			** check for SELECT, EXECUTE privilege.
			*/
		 	and (p.action in (193,224)))&1

			/*
			** more magic...normalise GRANT
			** and final magic...compare
			** Grants.
			*/
			) = 1
		/*
		** If one of any user defined roles or contained roles for the
		** user has permission, the user has the permission
		*/
		or exists(select 1
			from sysprotects p1,
				master.dbo.syssrvroles srvro,
				sysroles ro
			where p1.id = o.id
			and p1.uid = ro.lrid
			and ro.id = srvro.srid
	and has_role(srvro.name, 1) > 0
			and p1.action = 193))
		order by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
	
end

go
exec sp_procxmode 'sp_odbc_tables', 'anymode'
go
grant execute on sp_odbc_tables to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go



if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_gettableprivileges')
begin
	drop procedure sp_odbc_gettableprivileges
end
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_odbc_gettableprivileges ( 
                        @table_name  varchar(771),
                        @table_owner varchar(32) = null,
                        @table_qualifier varchar(32)= null)
as        
 
    declare @owner_id    		int
    declare @full_table_name    	varchar(1543)
    declare @tab_id 			int	    /* object id of the table specified */

    declare @tab_name                   varchar(255)
    declare @tab_owner                  varchar(32)
    declare @table_id 			int	    /* object id of the
                                                       table specified */
    declare @startedInTransaction bit


    if (@@trancount > 0)
       select @startedInTransaction = 1
    else
       select @startedInTransaction = 0
       
    set nocount on
    /*
    ** set the transaction isolation level
    */
    if @@trancount = 0
    begin
	   set chained off
    end
    
    set transaction isolation level 1

    if (@startedInTransaction = 1)
	save transaction odbc_keep_temptable_tx      

    /*
    **  Check to see that the table is qualified with the database name
    */
    if @table_name like "%.%.%"
    begin
	/* 18021, "Object name can only be qualified with owner name." */
	raiserror 18021
	return (1)
    end

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like "#%" and db_name() != db_name(tempdb_id()))
    begin
	/* 
	** 17676, "This may be a temporary object. Please execute 
	** procedure from your temporary database."
	*/
	raiserror 17676
	return (1)
    end


    /*
    ** The table_qualifier should be same as the database name. Do the sanity check
    ** if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
	/* set the table qualifier name */
	select @table_qualifier = db_name ()
    else
    begin
        if db_name() != @table_qualifier
        begin
	     /* 18039, "Table qualifier must be name of current database." */
	     raiserror 18039
	     return (1)
	end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name prefixed
    ** by the owner id
    */
    if (@table_owner is null) or (@table_owner = '')
        select @full_table_name = @table_name
    else
    begin
	if (@table_name like "%.%") and
	    substring (@table_name, 1, charindex(".", @table_name) -1) != @table_owner
	begin
	 	/* 18011, Object name must be qualified with the owner name */
		raiserror 18011
		return (1)
	end
	
	if not (@table_name like "%.%")
        	select @full_table_name = @table_owner + '.' + @table_name
	else
	        select @full_table_name = @table_name
    end

    /* 
    ** check to see if the specified table exists or not
    */

    select @tab_id = object_id(@full_table_name)
    if (@tab_id is null)
    begin
	/* 17492, "The table or view named doesn't exist in the current database." */
	raiserror 17492
	return (1)
    end


    /*
    ** check to see if the @tab_id indeeed represents a table or a view
    */

    if not exists (select * 
                  from   sysobjects
                  where (@tab_id = id) and
	                ((type = 'U') or
                        (type = 'S') or
		        (type = 'V')))
    begin
	/* 17492, "The table or view named doesn't exist in the current database." */
	raiserror 17492
	return (1)
    end

   /* 
   ** compute the table owner id
   */

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id



   /*
   ** get table owner name
   */

    select @table_owner = name 
    from sysusers 
    where uid = @owner_id

    /* Now, create a temporary table to hold a list of all the possible
       tables that we could get with the trio of table name, table owner and
       table catalog. Then, populate that table. */

    create table #odbc_tprivs
        (tab_id         int primary key,
         tab_name       varchar (255),
         tab_owner      varchar (32) null,
         uid            int,
         type           varchar (10))

    insert #odbc_tprivs 
        SELECT id, name, user_name(uid), uid, type 
        FROM sysobjects s 
        WHERE name LIKE @table_name ESCAPE '\'
            AND user_name (uid) LIKE @table_owner ESCAPE '\'
            AND charindex(substring(type,1,1), 'SUV') != 0

   /* Create temp table to store results from sp_aux_computeprivs */
    create table #results_table
	 (TABLE_CAT	varchar (32),
	  TABLE_SCHEM		varchar (32),
	  TABLE_NAME		varchar (255),
	  column_name		varchar (255) NULL,
	  GRANTOR		varchar (32),
	  GRANTEE 		varchar (32),
	  PRIVILEGE		varchar (32),
	  IS_GRANTABLE		varchar (3))

    declare tablepriv_cursor cursor for
        select tab_name, tab_owner, tab_id from #odbc_tprivs

    open tablepriv_cursor
   
    fetch tablepriv_cursor into @tab_name, @tab_owner, @table_id
 
    while (@@sqlstatus != 2)
    begin

        exec sp_odbc_computeprivs @tab_name, @tab_owner, @table_qualifier, 
			     NULL, 0, @table_id
        fetch tablepriv_cursor into @tab_name, @tab_owner, @table_id

    end

    close tablepriv_cursor
      /* Output the results table */

    select TABLE_CAT, TABLE_SCHEM, TABLE_NAME, GRANTOR, GRANTEE,
           PRIVILEGE, IS_GRANTABLE
    from #results_table
    order by TABLE_SCHEM, TABLE_NAME, PRIVILEGE

    drop table #odbc_tprivs
    drop table #results_table
  
    set nocount off 	
    if (@startedInTransaction = 1)
	rollback transaction odbc_keep_temptable_tx      

return (0)

go
exec sp_procxmode 'sp_odbc_gettableprivileges', 'anymode'
go
grant execute on sp_odbc_gettableprivileges to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getindexinfo')
begin
	drop procedure sp_odbc_getindexinfo
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_odbc_getindexinfo"          18039
**
** 18039, "Table qualifier must be name of current database."
** 18040, "Catalog procedure '%1!' can not be run in a transaction.
**
*/

/*
** Sp_statistics returns statistics for the given table, passed as first 
** argument. A row is returned for the table and then for each index found
** in sysindexes, starting with lowest value index id in sysindexes and 
** proceeding through the highest value index.  
**
** Returned rows consist of the columns:
** table qualifier (database name), table owner, table name from sysobjects, 
** non_unique (0/1), index qualifier (same as table name), 
** index name from sysindexes, type (SQL_INDEX_CLUSTERED/SQL_INDEX_OTHER), 
** sequence in index, column name, collation, table cardinality (row count), 
** and number of pages used by table (doampg).
*/

create procedure sp_odbc_getindexinfo (
	@table_name		varchar(771),
	@table_owner		varchar(32) = null,
	@table_qualifier	varchar(32) = null,
	@index_name		varchar(771) = '%',
	@is_unique 		char(1) = 'N')
as
declare @indid			int
declare @lastindid		int
declare @full_table_name	varchar(1543)
declare @startedInTransaction bit

if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0

/*
** Verify table qualifier is name of current database.
*/
if @table_qualifier is not null
begin
	if db_name() != @table_qualifier
	begin	/* If qualifier doesn't match current database */
		/*
		** 18039, "Table qualifier must be name of current database."
		*/
		raiserror 18039
		return (1)
	end
end

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
if (@startedInTransaction = 1)
   save transaction odbc_keep_temptable_tx    


create table #TmpIndex(
	TABLE_CAT	varchar(32),
	TABLE_SCHEM	varchar(32),
	TABLE_NAME	varchar(255),
	INDEX_QUALIFIER varchar(255) null,
	INDEX_NAME	varchar(255) null,
	NON_UNIQUE	smallint null,
	TYPE		smallint,
	ORDINAL_POSITION	smallint null,
	COLUMN_NAME	varchar(255) null,
	ASC_OR_DESC	char(1) null,
	index_id	int null,
	CARDINALITY	int null,
	PAGES		int null,
	FILTER_CONDITION varchar(32) null,	
	status		smallint,
	status2		smallint)

/*
** Fully qualify table name.
*/
if @table_owner is null
begin	/* If unqualified table name */
	select @full_table_name = @table_name
end
else
begin	/* Qualified table name */
	select @full_table_name = @table_owner + '.' + @table_name
end

/*
** Start at lowest index id, while loop through indexes. 
** Create a row in #TmpIndex for every column in sysindexes, each is
** followed by an row in #TmpIndex with table statistics for the preceding
** index.
*/
select @indid = min(indid)
	from sysindexes
	where id = object_id(@full_table_name)
		and indid > 0
		and indid < 255

while @indid != NULL
begin
	insert #TmpIndex	/* Add all columns that are in index */
	select
		db_name(),		/* table_qualifier */
		user_name(o.uid),	/* table_owner	   */
		o.name,			/* table_name	   */
		o.name, 		/* index_qualifier */
		x.name,			/* index_name	   */
		0,			/* non_unique	   */
		1,			/* SQL_INDEX_CLUSTERED */
		colid,			/* seq_in_index	   */
		INDEX_COL(@full_table_name,indid,colid),/* column_name	   */
		index_colorder(@full_table_name,
			indid,colid),	/* collation	   */
		@indid,			/* index_id 	   */
--	rowcnt(x.doampg),	/* cardinality	   */
 	row_count(db_id(), x.id), /* cardinality	*/	
--	data_pgs(x.id,doampg),	/* pages	   */
 	data_pages(db_id(), x.id,
 		case
 			when x.indid = 1
 			then 0
 			else x.indid
 		end),	/* pages	   */
       		null,			/* Filter condition not available */
       					/* in SQL Server*/		
		x.status,		/* status	   */
		x.status2		/* status2	   */		
	from sysindexes x, syscolumns c, sysobjects o
	where x.id = object_id(@full_table_name)
		and x.id = o.id
		and x.id = c.id
		and c.colid < keycnt+(x.status&16)/16
		and x.indid = @indid

	/*
	** Save last index and increase index id to next higher value.
	*/
	select @lastindid = @indid
	select @indid = NULL

	select @indid = min(indid)
	from sysindexes
	where id = object_id(@full_table_name)
		and indid > @lastindid
		and indid < 255
end

update #TmpIndex
	set NON_UNIQUE = 1
	where status&2 != 2 /* If non-unique index */

update #TmpIndex
	set
		TYPE = 3,		/* SQL_INDEX_OTHER */
		CARDINALITY = NULL,
		PAGES = NULL
	where index_id > 1		/* If non-clustered index */

update #TmpIndex
	set TYPE = 1			/* SQL_INDEX_CLUSTERED */
	where 
	status2&512 = 512	/* if placement index */
/* 
** Now add row with table statistics 
*/
insert #TmpIndex
	select
		db_name(),			/* table_qualifier */
		user_name(o.uid),		/* table_owner	   */
		o.name, 			/* table_name	   */
		null,				/* index_qualifier */
		null,				/* index_name	   */
		null,				/* non_unique	   */
		0,				/* SQL_table_STAT  */
		null,				/* seq_in_index	*/
		null,				/* column_name	   */
		null,				/* collation	   */
		0,				/* index_id 	   */
--	rowcnt(x.doampg),	/* cardinality	   */
 	row_count(db_id(), x.id), /* cardinality	*/	
--	data_pgs(x.id,doampg),	/* pages	   */
 	data_pages(db_id(), x.id,
 		case
 			when x.indid = 1
 			then 0
 			else x.indid
 		end),		/* pages	   */
       		null,				/* Filter condition not available */
        					/* in SQL Server*/		
		0,				/* status	   */
		0				/* status2	   */
	from sysindexes x, sysobjects o
	where o.id = object_id(@full_table_name)
		and x.id = o.id
		and (x.indid = 0 or x.indid = 1)	
	/*  
	** If there are no indexes
	** then table stats are in a row with indid = 0
	*/

if @is_unique != 'Y'	
begin
	/* If all indexes desired */
	select
		TABLE_CAT,
		TABLE_SCHEM,
		TABLE_NAME,
		NON_UNIQUE,
		INDEX_QUALIFIER,
		INDEX_NAME,
		TYPE,
		ORDINAL_POSITION,
		COLUMN_NAME,
		ASC_OR_DESC,
		CARDINALITY,
		PAGES,
		FILTER_CONDITION
	from #TmpIndex
	where INDEX_NAME like @index_name 	/* If matching name */
		or INDEX_NAME is null		/* If SQL_table_STAT row */
	order by NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION
end
else	
begin
	/* else only unique indexes desired */
	select
		TABLE_CAT,
		TABLE_SCHEM,
		TABLE_NAME,
		NON_UNIQUE,
		INDEX_QUALIFIER,
		INDEX_NAME,
		TYPE,
		ORDINAL_POSITION,
		COLUMN_NAME,
		ASC_OR_DESC,
		CARDINALITY,
		PAGES,
		FILTER_CONDITION
	from #TmpIndex
	where (NON_UNIQUE = 0 			/* If unique */
		or NON_UNIQUE is NULL)		/* If SQL_table_STAT row */
		and (INDEX_NAME like @index_name	/* If matching name */
		or INDEX_NAME is NULL)		/* If SQL_table_STAT row */
	order by NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION

end

drop table #TmpIndex
if (@startedInTransaction = 1)
   rollback transaction odbc_keep_temptable_tx      

return (0)
go
exec sp_procxmode 'sp_odbc_getindexinfo', 'anymode'
go
grant execute on sp_odbc_getindexinfo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_primarykey')
begin
	drop procedure sp_odbc_primarykey
end
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** note: there is one raiserror message: 18040
**
** messages for "sp_odbc_primarykey"               18039, 18040
**
** 17461, "Object does not exist in this database."
** 18039, "table qualifier must be name of current database."
** 18040, "catalog procedure %1! can not be run in a transaction.", sp_odbc_primarykey
**
*/

create procedure sp_odbc_primarykey
			   @table_name		varchar(771),
			   @table_owner 	varchar(32) = null,
			   @table_qualifier varchar(32) = null 
as
declare @keycnt smallint
declare @indexid smallint
declare @indexname varchar(771)
declare @i int
declare @id int
declare @uid int
declare @startedInTransaction bit
if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0
   
   
select @id = NULL


	set nocount on

if (@@trancount = 0)
begin
   set chained off
end

 if (@startedInTransaction = 1)
    save transaction odbc_keep_temptable_tx    



	set transaction isolation level 1

	if @table_qualifier is not null
	begin
		if db_name() != @table_qualifier
		begin	
			/* if qualifier doesn't match current database */
			/* "table qualifier must be name of current database"*/
			raiserror 18039
			return (1)
		end
	end

	if @table_owner is null
	begin
		select @id = id , @uid = uid
		from sysobjects 
		where name = @table_name
			and uid = user_id()
		if (@id is null)
		begin
			select @id = id ,@uid = uid
			from sysobjects 
			where name = @table_name
			and uid = 1
		end
	end
	else
	begin
		select @id = id , @uid = uid
		from sysobjects 
		where name = @table_name and uid = user_id(@table_owner)
	end
	
	if (@id is null)
	begin	
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end

	create table #pkeys(
			 TABLE_CAT varchar(32),
			 TABLE_SCHEM     varchar(32),
			 TABLE_NAME      varchar(255),
			 COLUMN_NAME     varchar(255),
			 KEY_SEQ	 smallint,
			 PK_NAME     	 varchar(255))


/*
**  now we search for primary key (only declarative) constraints
**  There is only one primary key per table.
*/

	select @keycnt = keycnt, @indexid = indid ,@indexname=name
	from   sysindexes
	where  id = @id
	and indid > 0 /* make sure it is an index */
	and status2 & 2 = 2 /* make sure it is a declarative constr */
	and status & 2048 = 2048 /* make sure it is a primary key */

/*
**  For non-clustered indexes, keycnt as returned from sysindexes is one
**  greater than the actual key count. So we need to reduce it by one to
**  get the actual number of keys.
*/

	if (@indexid >= 2)
	begin
		select @keycnt = @keycnt - 1
	end

	select @i = 1

	while @i <= @keycnt
	begin
		insert into #pkeys values
		(db_name(), user_name(@uid), @table_name,
			index_col(@table_name, @indexid, @i, @uid), @i,@indexname)
		select @i = @i + 1
	end

	select TABLE_CAT, TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, KEY_SEQ, PK_NAME
	from #pkeys
	order by TABLE_CAT, TABLE_SCHEM, TABLE_NAME, KEY_SEQ
	
 drop table #pkeys	
 if (@startedInTransaction = 1)
    rollback transaction odbc_keep_temptable_tx    
	
return (0)
go
exec sp_procxmode 'sp_odbc_primarykey', 'anymode'
go
grant execute on sp_odbc_primarykey to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_fkeys')
begin
	drop procedure sp_odbc_fkeys
end
go

/* sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** note: there is one raiserror message: 18040
**
** messages for "sp_odbc_fkeys"               18039, 18040
**
** 17461, "Object does not exist in this database." 
** 18040, "Catalog procedure %1! can not be run in a transaction.", sp_odbc_fkeys
** 18043 " Primary key table name or foreign key table name or both must be 
** given"
** 18044, "%1! table qualifier must be name of current database." [Primary
** key | Foreign key]
**
*/
CREATE PROCEDURE sp_odbc_fkeys
			   @pktable_name		varchar(255) = null,
			   @pktable_owner		varchar(32) = null,
			   @pktable_qualifier	varchar(32) = null,
			   @fktable_name		varchar(255) = null,
			   @fktable_owner		varchar(32) = null,
			   @fktable_qualifier	varchar(32) = null 
as
declare @ftabid int, @ptabid int, @constrid int,@keycnt int, @i int
declare @fokey1 int,  @fokey2 int,  @fokey3 int,  @fokey4 int,  @fokey5  int
declare @fokey6 int,  @fokey7 int,  @fokey8 int,  @fokey9 int,  @fokey10 int
declare @fokey11 int, @fokey12 int, @fokey13 int, @fokey14 int, @fokey15 int
declare @refkey1 int, @refkey2 int, @refkey3 int, @refkey4 int, @refkey5  int
declare @refkey6 int, @refkey7 int, @refkey8 int, @refkey9 int, @refkey10 int
declare @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
declare @refkey15 int, @refkey16 int, @fokey16 int, @status int
declare @msg varchar(1024)
declare @msg2 varchar(1024)
declare @ordpkey	int
declare @notDeferrable smallint
declare @startedInTransaction bit
	if (@@trancount > 0)
	   select @startedInTransaction = 1
	else
	   select @startedInTransaction = 0

	set nocount on

	if (@@trancount = 0)
	begin
		set chained off
	end

	set transaction isolation level 1

	if (@startedInTransaction = 1)
	    save transaction odbc_keep_temptable_tx    
	
	select @notDeferrable = 7

	if (@pktable_name is null) and (@fktable_name is null)
	begin	
		/* If neither primary key nor foreign key table names given */
		/* 
		** 18043 "Primary key table name or foreign key table name 
		** or both must be given"
		*/
		raiserror 18043
		return (1)
	end

	if @fktable_qualifier is not null
	begin
		if db_name() != @fktable_qualifier
		begin	
			/* If qualifier doesn't match current database */
			/* 18044 "%1! Table qualifier must be name of current database"
			** 18050 "Foreign key"
			*/
			exec sp_getmessage 18050, @msg2 output
			raiserror 18044, @msg2
			return (1)
		end
	end
	else
	begin
		/*
		** Now make sure that foreign table qualifier is pointing to the
		** current database in case it is not specified.
		*/
		select @fktable_qualifier = db_name()
	end

	if @pktable_qualifier is not null
	begin
		if db_name() != @pktable_qualifier
		begin	
			/* If qualifier doesn't match current database */
			/* 18044 "%1! Table qualifier must be name of current database"
			** 18051 "Primary Key"
			*/
			exec sp_getmessage 18051, @msg2 output
			raiserror 18044, @msg2
			return (1)
		end
	end
	else
	begin
		/*
		** Now make sure that primary table qualifier is pointing to the
		** current database in case it is not specified.
		*/
		select @pktable_qualifier = db_name()
	end


	create table #opid (pid int, uid int, name varchar(255))
	create table #ofid (fid int, uid int, name varchar(255))

	/* we will sort by fkey		*/
	/* unless pktable is null	*/

	select @ordpkey = 0

	if @pktable_name is not null
	begin 

		if (@pktable_owner is null)
		begin
			/* 
			** owner is NULL, so default to the current user
			** who owns this table, otherwise default to dbo
			** who owns this table.
			*/
			insert into #opid 
			select id, uid, name
			from sysobjects 
			where name = @pktable_name and uid = user_id()
			and type in ("S", "U")
			
			/* 
			** If the current user does not own the table, see
			** if the DBO of the current database owns the table.
			*/

			if ((select count(*) from #opid ) = 0)
			begin
				insert into #opid 
				select id, uid, name
				from sysobjects 
				where name = @pktable_name and uid = 1
				and type in ("S", "U")
			end
		end
		else
		begin
			insert into #opid
			select id, uid, name
			from sysobjects
			where name = @pktable_name 
			and uid = user_id(@pktable_owner)
			and type in ("S", "U")
		end
	end
	else 
	begin
		if (@pktable_owner is null)
		begin
		/* 
		** If neither pktable_name nor pktable_owner is specified,
		** then we are interested in every user or system table.
		*/
			insert into #opid 
			select id, uid, name
			from sysobjects 
			where type in ("S", "U")
		end
		else
		begin
			insert into #opid
			select id, uid, name
			from sysobjects
			where  uid = user_id(@pktable_owner)
			and type in ("S", "U")
		end
	end
		
	if @fktable_name is not null
	begin 
		/* sort by pkey	*/
		select @ordpkey = 1

		if (@fktable_owner is null)
		begin
			/* 
			** owner is NULL, so default to the current user
			** who owns this table, otherwise default to dbo
			** who owns this table.
			*/
			insert into #ofid 
			select id, uid, name
			from sysobjects 
			where name = @fktable_name and uid = user_id()
			and type in ("S", "U")

			/* 
			** If the current user does not own the table, see
			** if the DBO of the current database owns the table.
			*/

			if ((select count(*) from #opid ) = 0)
			begin
				insert into #ofid 
				select id, uid, name
				from sysobjects 
				where name = @fktable_name and uid = 1
				and type in ("S", "U")
			end
		end
		else
		begin
			insert into #ofid
			select id, uid, name
			from sysobjects
			where name = @fktable_name 
			and uid = user_id(@fktable_owner)
			and type in ("S", "U")
		end
	end
	else
	begin
		if (@fktable_owner is null)
		begin
		/* 
		** If neither fktable_name nor fktable_owner is specified,
		** then we are interested in every user table or systme 
		** table.
		*/			
			insert into #ofid 
			select id, uid, name
			from sysobjects 
			where type in ("S", "U")
		end
		else
		begin
			insert into #ofid
			select id, uid, name
			from sysobjects
			where  uid = user_id(@fktable_owner)
			and type in ("S", "U")
		end
	end

	if (((select count(*) from #ofid ) = 0) or
		((select count(*) from #opid) = 0))
	begin
		/* 17461, "Object does not exist in this database." */
		raiserror 17461
		return (1)
	end

	create table #ofkey_res( PKTABLE_CAT varchar(32),
				PKTABLE_SCHEM       varchar(32),
				PKTABLE_NAME       varchar(255),
				PKCOLUMN_NAME      varchar(255),
				FKTABLE_CAT varchar(32),
				FKTABLE_SCHEM       varchar(32),
				FKTABLE_NAME       varchar(255),
				FKCOLUMN_NAME       varchar(255),
				KEY_SEQ           smallint,	
				UPDATE_RULE smallint, 
				DELETE_RULE smallint,
				FK_NAME	varchar(255),
				PK_NAME	varchar(255))
	create table #opkeys(seq int,  keys varchar(255) null)
	create table #ofkeys(seq int, keys varchar(255) null)

	/*
	** Since there are possibly multiple rows in sysreferences
	** that describe foreign and primary key relationships among
	** two tables, so we declare a cursor on the selection from
	** sysreferences and process the output at row by row basis.
	*/
		
	declare curs_sysreferences cursor
	for
	select tableid, reftabid, constrid, keycnt,
	fokey1, fokey2, fokey3, fokey4, fokey5, fokey6, fokey7, fokey8, 
	fokey9, fokey10, fokey11, fokey12, fokey13, fokey14, fokey15,
	fokey16, refkey1, refkey2, refkey3, refkey4, refkey5,
	refkey6, refkey7, refkey8, refkey9, refkey10, refkey11,
	refkey12, refkey13, refkey14, refkey15, refkey16
	from sysreferences
	where tableid in (
		select fid from #ofid)
	and reftabid in (
		select pid from #opid)
	and frgndbname is NULL and pmrydbname is NULL
	for read only

	open  curs_sysreferences

	fetch  curs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt,@fokey1, 
	@fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8, 
	@fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15, 
	@fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6, 
	@refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12, 
	@refkey13, @refkey14, @refkey15, @refkey16

	while (@@sqlstatus = 0)
	begin
		/*
		** For each row of sysreferences which describes a foreign-
		** primary key relationship, do the following.
		*/

		/*
		** First store the column names that belong to primary keys
		** in table #pkeys for later retrieval.
		*/

		delete #opkeys
		insert #opkeys values(1, col_name(@ptabid,@refkey1))
		insert #opkeys values(2, col_name(@ptabid,@refkey2))
		insert #opkeys values(3, col_name(@ptabid,@refkey3))
		insert #opkeys values(4, col_name(@ptabid,@refkey4))
		insert #opkeys values(5, col_name(@ptabid,@refkey5))
		insert #opkeys values(6, col_name(@ptabid,@refkey6))
		insert #opkeys values(7, col_name(@ptabid,@refkey7))
		insert #opkeys values(8, col_name(@ptabid,@refkey8))
		insert #opkeys values(9, col_name(@ptabid,@refkey9))
		insert #opkeys values(10, col_name(@ptabid,@refkey10))
		insert #opkeys values(11, col_name(@ptabid,@refkey11))
		insert #opkeys values(12, col_name(@ptabid,@refkey12))
		insert #opkeys values(13, col_name(@ptabid,@refkey13))
		insert #opkeys values(14, col_name(@ptabid,@refkey14))
		insert #opkeys values(15, col_name(@ptabid,@refkey15))
		insert #opkeys values(16, col_name(@ptabid,@refkey16))
	
		/*
		** Second store the column names that belong to foreign keys
		** in table #fkeys for later retrieval.
		*/
		
		delete #ofkeys
		insert #ofkeys values(1, col_name(@ftabid,@fokey1))
		insert #ofkeys values(2, col_name(@ftabid,@fokey2))
		insert #ofkeys values(3, col_name(@ftabid,@fokey3))
		insert #ofkeys values(4, col_name(@ftabid,@fokey4))
		insert #ofkeys values(5, col_name(@ftabid,@fokey5))
		insert #ofkeys values(6, col_name(@ftabid,@fokey6))
		insert #ofkeys values(7, col_name(@ftabid,@fokey7))
		insert #ofkeys values(8, col_name(@ftabid,@fokey8))
		insert #ofkeys values(9, col_name(@ftabid,@fokey9))
		insert #ofkeys values(10, col_name(@ftabid,@fokey10))
		insert #ofkeys values(11, col_name(@ftabid,@fokey11))
		insert #ofkeys values(12, col_name(@ftabid,@fokey12))
		insert #ofkeys values(13, col_name(@ftabid,@fokey13))
		insert #ofkeys values(14, col_name(@ftabid,@fokey14))
		insert #ofkeys values(15, col_name(@ftabid,@fokey15))
		insert #ofkeys values(16, col_name(@ftabid,@fokey16))
	
		/* 
		** For each column of the current foreign-primary key relation,
		** create a row into result table: #fkey_res.
		*/

		select @i = 1
		while (@i <= @keycnt)
		begin
			insert into #ofkey_res 
				select @pktable_qualifier,
				(select user_name(uid) from #opid where pid = @ptabid),
				object_name(@ptabid),
				(select keys from #opkeys where seq = @i),
				@fktable_qualifier,
				(select user_name(uid) from #ofid where fid = @ftabid),
				object_name(@ftabid), 
				(select keys from #ofkeys where seq = @i),@i,
				1, 1,
			/* Foreign Key */				
				object_name(@constrid),
			/* Primary key name */
		                (select name from sysindexes where id = @ftabid
		                    and status > 2048 and status < 32768)
			select @i = @i + 1
		end
		
		/* 
		** Go to the next foreign-primary key relationship if any.
		*/

		fetch  curs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt,@fokey1, 
		@fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8, 
		@fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15, 
		@fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6, 
		@refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12, 
		@refkey13, @refkey14, @refkey15, @refkey16
	end

	close curs_sysreferences
	deallocate cursor curs_sysreferences

	/*
	** Everything is now in the result table #fkey_res, so go ahead
	** and select from the table now.
	*/

	/* if @ordpkey = 0 sort by fkey */
	/* else sort by pkey		*/
	if @ordpkey = 0
	begin
		select PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME,
		PKCOLUMN_NAME, FKTABLE_CAT, FKTABLE_SCHEM, 
		FKTABLE_NAME, FKCOLUMN_NAME, KEY_SEQ, UPDATE_RULE, DELETE_RULE,
		FK_NAME,PK_NAME,@notDeferrable as DEFERRABILITY
		from #ofkey_res
		order by FKTABLE_NAME,FKTABLE_SCHEM,KEY_SEQ, FKTABLE_CAT
	end
	else
	begin
		select PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME,
		PKCOLUMN_NAME, FKTABLE_CAT, FKTABLE_SCHEM, 
		FKTABLE_NAME, FKCOLUMN_NAME, KEY_SEQ, UPDATE_RULE, DELETE_RULE,
		FK_NAME,PK_NAME,@notDeferrable as DEFERRABILITY
		from #ofkey_res
		order by PKTABLE_NAME,PKTABLE_SCHEM,KEY_SEQ, PKTABLE_CAT
	end

drop table #opkeys
drop table #ofkeys
drop table #ofkey_res
if (@startedInTransaction = 1)
    rollback transaction odbc_keep_temptable_tx	
	
go
exec sp_procxmode 'sp_odbc_fkeys', 'anymode'
go
grant execute on sp_odbc_fkeys to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_stored_procedures')
begin
	drop procedure sp_odbc_stored_procedures
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_odbc_stored_procedures"	18041
**
** 18041, "Stored Procedure qualifier must be name of current database."
**
*/
create procedure sp_odbc_stored_procedures
@sp_name	varchar(771) = null,	/* stored procedure name */
@sp_owner	varchar(32) = null,	/* stored procedure owner */
@sp_qualifier	varchar(32) = null	/* stored procedure qualifier; 
					** For the SQL Server, the only valid
					** values are NULL or the current 
					** database name
					*/
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* If qualifier is specified */
if @sp_qualifier is not null
begin
	/* If qualifier doesn't match current database */
	if db_name() != @sp_qualifier
	begin
		/* If qualifier is not specified */
		if @sp_qualifier = ''
		begin
			/* in this case, we need to return an empty 
			** result set because the user has requested a 
			** database with an empty name 
			*/
			select @sp_name = ''
			select @sp_owner = ''
		end

		/* qualifier is specified and does not match current database */
		else
		begin	
			/* 
			** 18041, "Stored Procedure qualifer must be name of
			** current database"
			*/
			raiserror 18041
			return (1)
		end
	end
end

/* If procedure name not supplied, match all */
if @sp_name is null
begin  
	select @sp_name = '%'
end
else 
begin
	/* If owner name is not supplied, but procedure name is */ 
	if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
	begin
		/* If procedure exists and is owned by the current user */
		if exists (select * 
			   from sysobjects
			   where uid = user_id()
				and name = @sp_name
				and type = 'P') /* Object type of Procedure */
		begin
			/* Set owner name to current user */
			select @sp_owner = user_name()
		end
	end
end

/* If procedure owner not supplied, match all */
if @sp_owner is null	
	select @sp_owner = '%'

/* 
** Retrieve the stored procedures and associated info on them
*/
select  PROCEDURE_CAT = db_name(),
	PROCEDURE_SCHEM = user_name(o.uid),
	PROCEDURE_NAME = o.name ,
	NUM_INPUT_PARAMS = -1,		/* Constant since value unknown */
	NUM_OUTPUT_PARAMS = -1, 	/* Constant since value unknown */
	NUM_RESULT_SETS = -1,		/* Constant since value unknown */
	REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
	PROCEDURE_TYPE = case when o.type='P' then convert(smallint, 1) when o.type='F' then convert(smallint, 2) end
from sysobjects o,sysprocedures p,sysusers u
where o.name like @sp_name
	and p.sequence = 0
	and user_name(o.uid) like @sp_owner
	and o.type in ('P','F')		/* Object type of Procedure or Function */
	and p.id = o.id
	and u.uid = user_id()		/* constrain sysusers uid for use in 
					** subquery 
					*/

	and (suser_id() = 1 		/* User is the System Administrator */
	     or  o.uid = user_id()	/* User created the object */
					/* here's the magic..select the highest 
					** precedence of permissions in the 
					** order (user,group,public)  
					*/

	     /*
	     ** The value of protecttype is
	     **
	     **		0  for grant with grant
	     **		1  for grant and,
	     **		2  for revoke
	     **
	     ** As protecttype is of type tinyint, protecttype/2 is
	     ** integer division and will yield 0 for both types of
	     ** grants and will yield 1 for revoke, i.e., when
	     ** the value of protecttype is 2.  The XOR (^) operation
	     ** will reverse the bits and thus (protecttype/2)^1 will
	     ** yield a value of 1 for grants and will yield a
	     ** value of zero for revoke.
	     **
	     ** For groups, uid = gid. We shall use this to our advantage.
             ** 	
	     ** If there are several entries in the sysprotects table
	     ** with the same Object ID, then the following expression
	     ** will prefer an individual uid entry over a group entry
	     **
	     ** For example, let us say there are two users u1 and u2
	     ** with uids 4 and 5 respectiveley and both u1 and u2
	     ** belong to a group g12 whose uid is 16390.  procedure p1
	     ** is owned by user u0 and user u0 performs the following
	     ** actions:
	     **
	     **		grant exec on p1 to g12
	     **		revoke grant on p1 from u1
	     **
	     ** There will be two entries in sysprotects for the object
	     ** p1, one for the group g12 where protecttype = grant (1)
	     ** and one for u1 where protecttype = revoke (2).
	     **
	     ** For the group g12, the following expression will
	     ** evaluate to:
	     **
	     **		((abs(16390-16390)*2) + ((1/2)^1))
	     **		= ((0) + (0)^1) = 0 + 1 = 1
	     **
	     ** For the user entry u1, it will evaluate to:
	     **
	     **		((abs(4-16390)*2) + ((2/2)^1))
	     **		= ((abs(-16386)*2 + (1)^1)
	     **		= 16386*2 + 0 = 32772 
	     **
	     ** As the expression evaluates to a bigger number for the
	     ** user entry u1, select max() will chose 32772 which,
	     ** ANDed with 1 gives 0, i.e., sp_odbc_stored_procedures will
	     ** not display this particular procedure to the user.
	     **
	     ** When the user u2 invokes sp_odbc_stored_procedures, there is
	     ** only one entry for u2, which is the entry for the group
	     ** g12, and so this entry will be selected thus allowing
	     ** the procedure in question to be displayed.
	     **
             ** NOTE: With the extension of the uid's into negative space, 
             ** and uid limits going beyond 64K, the original expression 
	     ** has been modified from
	     ** ((select max(((sign(uid)*abs(uid-16383))*2)
	     **		+ ((protecttype/2)^1))
	     ** to
	     ** ((select max((abs(uid-u.gid)*2)
	     **		+ ((protecttype/2)^1))
	     ** 
	     ** Notice that multiplying by 2 makes the number an
	     ** even number (meaning the last digit is 0) so what
	     ** matters at the end is (protecttype/2)^1.
	     **
	     */

	     or ((select max( (abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
		   from sysprotects p, sysusers u2
		   where p.id = o.id
		   and u2.uid = user_id()
		   /*
		   ** get rows for public, current users, user's groups
		   */
		   and (p.uid = 0  		/* get rows for public */
		        or p.uid = user_id()	/* current user */
		        or p.uid = u2.gid) 	/* users group */
			     
		   /*
		   ** check for SELECT, EXECUTE privilege.
		   */
	           and (p.action in (193,224))	/* check for SELECT,EXECUTE 
						** privilege 
						*/
		   )&1 			/* more magic...normalize GRANT */
	    	  ) = 1	 		/* final magic...compare Grants	*/
	     /*
	     ** If one of any user defined roles or contained roles for the
	     ** user has permission, the user has the permission
	     */
	     or exists(select 1
		from	sysprotects p1,
			master.dbo.syssrvroles srvro,
			sysroles ro
		where	p1.id = o.id
			and p1.uid = ro.lrid
			and ro.id = srvro.srid
	and has_role(srvro.name, 1) > 0	
			and p1.action = 224))
			
order by PROCEDURE_CAT, PROCEDURE_SCHEM, PROCEDURE_NAME
go
exec sp_procxmode 'sp_odbc_stored_procedures', 'anymode'
go
grant execute on sp_odbc_stored_procedures to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_odbc_getprocedurecolumns')
begin
	drop procedure sp_odbc_getprocedurecolumns
end
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_odbc_getprocedurecolumns"
**
** 18039, "Table qualifier must be name of current database"
*/

create procedure sp_odbc_getprocedurecolumns
@procedure_name		varchar(771) = '%', 	/* name of stored procedure  */
@procedure_owner 	varchar(32) = null,	/* owner of stored procedure */
@procedure_qualifier	varchar(32) = null,	/* name of current database  */
@column_name		varchar(771) = null	/* col name or param name    */
as

declare @msg 		  varchar(255)
declare @group_num		int
declare @semi_position		int
declare @full_procedure_name	varchar(1543)
declare @procedure_id		int
declare @char_bin_types   varchar(32) 
declare @sptlang 			int

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

-- select @sptlang = @@langid

-- if @@langid != 0
-- begin
--         if not exists (
--                 select * from master.dbo.sysmessages where error
--                 between 17100 and 17109
--                 and langid = @@langid)
--             select @sptlang = 0
-- end

/* If column name not supplied, match all */
if @column_name is null 
	select @column_name = '%'

/* The qualifier must be the name of current database or null */
if @procedure_qualifier is not null
begin
	if db_name() != @procedure_qualifier
	begin
	if @procedure_qualifier = ''
		begin
			/* in this case, we need to return an empty result 
			** set because the user has requested a database with
			** an empty name
			*/
			select @procedure_name = ''
			select @procedure_owner = ''
		end
		else
		begin
			/*
			** 18039, Table qualifier must be name of current database
			*/
			exec sp_getmessage 18039, @msg output
			print @msg
			return
		end
	end
end


/* first we need to extract the procedure group number, if one exists */
select @semi_position = charindex(';',@procedure_name)
if (@semi_position > 0)
begin	/* If group number separator (;) found */
	select @group_num = convert(int,substring(@procedure_name, 
						  @semi_position + 1, 2))
	select @procedure_name = substring(@procedure_name, 1, 
					   @semi_position -1)
end
else
begin	/* No group separator, so default to group number of 1 */
	select @group_num = 1
end

/* character and binary datatypes */
select @char_bin_types =
	char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

if @procedure_owner is null
begin	/* If unqualified procedure name */
	select @full_procedure_name = @procedure_name
end
else
begin	/* Qualified procedure name */
	select @full_procedure_name = @procedure_owner + '.' + @procedure_name
end

/*
** If the @column_name parameter is "RETURN_VALUE" and this is a sqlj
** function, then we should be looking for column name "Return Type"
*/
if @column_name = "RETURN_VALUE"
	and exists (select 1 from sysobjects
		    where id = object_id(@full_procedure_name)
		    and type = 'F')
begin	
	select @column_name = "Return Type"
end

/*	Get Object ID */
select @procedure_id = object_id(@full_procedure_name)

if ((charindex('%',@full_procedure_name) = 0) and
	(charindex('_',@full_procedure_name) = 0)  and
	@procedure_id != 0)
begin
/*
** this block is for the case where there is no pattern
** matching required for the table name
*/
	select	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		PROCEDURE_CAT = db_name(),
		PROCEDURE_SCHEM = user_name(o.uid),
		PROCEDURE_NAME = o.name ,
                COLUMN_NAME =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                COLUMN_TYPE =
		case
			when c.name = 'Return Type'
				then convert(smallint, 5)
		when c.status2 = 1
			then convert(smallint, 1)
		when c.status2 = 2
			then convert(smallint, 4)
		when c.status2 = 4			     		
			then  convert(smallint, 2)
		else convert(smallint, 0)
		end,

/*
** With the current data in the spt_datatype_info table, the convert() below
** is never being used.
** These conversions were ported from the original Microsoft INSTCAT.SQL
** file which contained catalog stored procedures for 4.9 and earlier SQL
** Servers.
*/
		DATA_TYPE = 
		case 
			when d.data_type = 11
				then convert(smallint,93)
		else
			d.data_type
			    +convert(smallint, 
				     isnull(d.aux,
					    ascii(substring("666AAA@@@CB??GG",
						            2*(d.ss_dtype%35+1)
							    +2-8/c.length,
							    1)) - 60))
		end,
		TYPE_NAME = rtrim(substring(d.type_name,
					1+isnull(d.aux,
					     ascii(substring("III<<<MMMI<<A<A",
							2*(d.ss_dtype%35+1)
							+2-8/c.length,
						        1)) - 60), 
					    18)),
		COLUMN_SIZE = isnull(convert(int, c.prec),
			isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						          2*(d.ss_dtype%35+1)
							  +2-8/c.length,1))
							  -60)),
		BUFFER_LENGTH = isnull(d.length, convert(int,c.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						    	     2*(d.ss_dtype%35
							     +1)+2-8/c.length,
						             1))-64)),
		DECIMAL_DIGITS = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale)) +
			convert(smallint, 
				isnull(d.aux, ascii(substring("<<<<<<<<<<<<<<?",
					        2*(d.ss_dtype%35+1)
						+2-8/c.length,
					        1))-60)),
		NUM_PREC_RADIX = d.numeric_radix,
		NULLABLE =	/* set nullability from status flag */
			convert(smallint,1),/*convert(smallint, convert(bit, c.status&8))*/
		REMARKS = convert(varchar(254),NULL),	/* Remarks are NULL */
		COLUMN_DEF = convert(varchar(254),NULL),
		SQL_DATA_TYPE = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
			isnull(d.aux,
			ascii(substring("666AAA@@@CB??GG",
			2*(d.ss_dtype%35+1)+2-8/c.length,1))
			-60))),
		SQL_DATETIME_SUB = NULL,
		CHAR_OCTET_LENGTH = 
		case 
			when d.data_type = 4 then convert(smallint,NULL)
		else
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
			convert(smallint,
		    	substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
			/* calculate the precision */
			isnull(convert(int, c.prec),
		    	isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		   	 +isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
		end,
		ORDINAL_POSITION = convert(int,c.colid),
		IS_NULLABLE = 'YES'
			/* rtrim(substring('NO YES',
			(convert(smallint, convert(bit, c.status&8))*3)+1, 3))*/
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sysprocedures p
	where
		o.id = @procedure_id
		and c.id = o.id
		and c.type = d.ss_dtype
		and c.name like @column_name
		and d.ss_dtype in (111, 109, 38, 110)	/* Just *N types */
		and c.number = @group_num
	union
	select
		PROCEDURE_CAT = db_name(),
		PROCEDURE_SCHEM = user_name(o.uid),
		PROCEDURE_NAME = o.name ,
		COLUMN_NAME = 'RETURN_VALUE',
		COLUMN_TYPE = convert(smallint, 5), /* return parameter */
		DATA_TYPE = 
		case 
			when d.data_type = 11
				then convert(smallint,93)
		else
			d.data_type+convert(smallint,
					  isnull(d.aux,
					     ascii(substring("666AAA@@@CB??GG",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
						          -60))
		end,
		TYPE_NAME = d.type_name,
		COLUMN_SIZE = isnull(d.data_precision, convert(int,d.length))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
							  -60)),
		BUFFER_LENGTH = isnull(d.length, convert(int,t.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						    	     2*(d.ss_dtype%35
							     +1)+2-8/t.length,
						             1))-64)),
		DECIMAL_DIGITS = d.numeric_scale +convert(smallint,
					   isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
						        2*(d.ss_dtype%35+1)
							+2-8/d.length,
						        1))-60)),
		NUM_PREC_RADIX = d.numeric_radix,
		NULLABLE = convert(smallint, 1),
		REMARKS = convert(varchar(254),NULL),	/* Remarks are NULL */
                COLUMN_DEF = convert(varchar(254),NULL),
                SQL_DATA_TYPE = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/d.length,1))
                        -60))),
                SQL_DATETIME_SUB = NULL,
                CHAR_OCTET_LENGTH = NULL,
                ORDINAL_POSITION = convert(tinyint, 0),
                IS_NULLABLE = 'YES'
	from
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.id = @procedure_id
		and d.ss_dtype = 56  /* int for return code */
		and t.type = 56
		and o.type = 'P'
		and (@column_name = '%' or @column_name = 'RETURN_VALUE')
	union
	select		   /* All other types including user data types */
		PROCEDURE_CAT = db_name(),
		PROCEDURE_SCHEM = user_name(o.uid),
		PROCEDURE_NAME = o.name,
		COLUMN_NAME = 	
			case	
		 	    when c.name = 'Return Type' then 'RETURN_VALUE'
			    else c.name
			end,
		COLUMN_TYPE = 
		case 
			when c.name = 'Return Type' 
				then convert(smallint, 5)
		when c.status2 = 1
			then convert(smallint, 1)
		when c.status2 = 2
			then convert(smallint, 4)
		when c.status2 = 4			     		
			then  convert(smallint, 2)
		else convert(smallint, 0)	
		end,		

		/*   Map systypes.type to ODBC type	       		*/
		/*   SS-Type "				 1	      "	*/
		/*	     "33 3 3 4 44 5 5 2 5 55666"	        */
		/*	     "45 7 9	5 78 0 2 2 6 89012"             */
		DATA_TYPE = 
		case 
			when t.name = "date"
				then convert(smallint,91)
			when t.name = "time"
				then convert(smallint,92)
			when t.name = "datetime"
				then convert(smallint,93)
		else
			d.data_type+convert(smallint,
			isnull(d.aux, ascii(substring("666AAA@@@CB??GG",
			2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60))
		end,
		TYPE_NAME = 
			case 
			    when t.name = 'extended type' 
				then isnull(get_xtypename(c.xtype, c.xdbid), 
									t.name)
			    when t.type = 58
			    	then "smalldatetime"
			    when t.usertype in (44,45,46)
				then "unsigned "+substring(t.name,
				charindex("u",t.name) + 1,
				charindex("t",t.name))
			    else 
				t.name
			end,
		COLUMN_SIZE = 
		case 
			when d.data_precision = 0
			then convert(int,0)
		else		
		isnull(convert(int, c.prec),
			isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						       2*(d.ss_dtype%35+1)
						       +2-8/c.length,1))
						       -60))
		end,
		BUFFER_LENGTH = isnull(d.length, convert(int,c.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						             2*(d.ss_dtype%35
							     +1)+2-8/c.length,
						             1))-64)),
		DECIMAL_DIGITS = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale))
			+ convert(smallint,
					  isnull(d.aux,
					    ascii(substring("<<<<<<<<<<<<<<?",
							    2*(d.ss_dtype%35+1)
							    +2-8/c.length,
							    1))-60)),
		NUM_PREC_RADIX = d.numeric_radix,

		/* set nullability from status flag */
		NULLABLE = convert(smallint,1),/*convert(smallint, convert(bit, c.status&8)),*/
		REMARKS = convert(varchar(254),NULL),	/* Remarks are NULL */
                COLUMN_DEF = convert(varchar(254),NULL),
                SQL_DATA_TYPE = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60))),
                SQL_DATETIME_SUB = 
		case
			when (isnull(d.sql_data_type,d.data_type+convert(smallint,
				isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
				2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)))) = 91
				then convert(smallint,1)
			when (isnull(d.sql_data_type,d.data_type+convert(smallint,
				isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
				2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)))) = 92
				then convert(smallint,2)
			when (isnull(d.sql_data_type,d.data_type+convert(smallint,
	                	isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
	                        2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)))) = 93
		                then convert(smallint,3)
                	end,
		CHAR_OCTET_LENGTH = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		case 
			when d.data_type = 4 then convert(smallint,NULL)
		else
			convert(smallint,
		    	substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
			/* calculate the precision */
			isnull(convert(int, c.prec),
		    	isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		   	+isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
                end,
		ORDINAL_POSITION = convert(int,c.colid),
		IS_NULLABLE = 'YES'/*rtrim(substring('NO YES',
                        (convert(smallint, convert(bit, c.status&8))*3)+1, 3))*/
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.id = @procedure_id
		and c.id = o.id
		and c.type *= d.ss_dtype
		and c.usertype *= t.usertype
		and c.name like @column_name
		and c.number = @group_num
		and d.ss_dtype not in (111, 109, 38, 110) /* No *N types */

	 order by convert(int,colid)
end
else
begin
	/* 
	** this block is for the case where there IS pattern
	** matching done on the table name
	*/
	if @procedure_owner is null
		select @procedure_owner = '%'

	select	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		PROCEDURE_CAT = db_name(),
		PROCEDURE_SCHEM = user_name(o.uid),
		PROCEDURE_NAME = o.name,
                COLUMN_NAME =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                COLUMN_TYPE =
		case
			when c.name = 'Return Type'
                             	then convert(smallint, 5)
		when c.status2 = 1
			then convert(smallint, 1)
		when c.status2 = 2
			then convert(smallint, 4)
		when c.status2 = 4			     		
			then  convert(smallint, 2)
                  else convert(smallint, 0)
		end,
		DATA_TYPE = 
		case 
			when d.data_type = 11
				then convert(smallint,93)
		else
			d.data_type+convert(smallint,
					  isnull(d.aux,
					     ascii(substring("666AAA@@@CB??GG",
						          2*(d.ss_dtype%35+1)
							  +2-8/c.length,1))
						          -60))
		end,
		TYPE_NAME = rtrim(substring(d.type_name,
				    1+isnull(d.aux,
					     ascii(substring("III<<<MMMI<<A<A",
					                  2*(d.ss_dtype%35+1)
							  +2-8/c.length,
						          1))-60), 18)),
		COLUMN_SIZE = isnull(convert(int, c.prec), 
				isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						           2*(d.ss_dtype%35+1)
							   +2-8/c.length,1))
						           -60)),
		BUFFER_LENGTH = isnull(d.length, convert(int,c.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
							   2*(d.ss_dtype%35+1)
							   +2-8/c.length,
							   1))-64)),
		DECIMAL_DIGITS = isnull(convert(smallint, c.scale),
				convert(smallint, d.numeric_scale))
				+ convert(smallint,
					    isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
							   2*(d.ss_dtype%35+1)
							   +2-8/c.length,
							   1))-60)),
		NUM_PREC_RADIX = d.numeric_radix,
		/* set nullability from status flag */
		NULLABLE = convert(smallint,1), /*convert(smallint, convert(bit, c.status&8)),*/
		REMARKS = convert(varchar(254),NULL),	/* Remarks are NULL */
                COLUMN_DEF = convert(varchar(254),NULL),
                SQL_DATA_TYPE = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60))),
                SQL_DATETIME_SUB = NULL,
		CHAR_OCTET_LENGTH = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		case 
			when d.data_type = 4 then convert(smallint,NULL)
		else
			convert(smallint,
		    	substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
			/* calculate the precision */
			isnull(convert(int, c.prec),
		    	isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		    	+isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
		end,
                ORDINAL_POSITION = convert(int,c.colid),
                IS_NULLABLE = 'YES' /* rtrim(substring('NO YES',
                        (convert(smallint, convert(bit, c.status&8))*3)+1, 3))*/
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_owner
		and o.id = c.id
		and c.type = d.ss_dtype
		and c.name like @column_name
		
		/* Just procs & sqlj procs and funcs */
		and o.type in ('P', 'F')
		and d.ss_dtype in (111, 109, 38, 110)	/* Just *N types */
	union
	select distinct
		PROCEDURE_CAT = db_name(),
		PROCEDURE_SCHEM = user_name(o.uid),
		PROCEDURE_NAME = o.name ,
		COLUMN_NAME = 'RETURN_VALUE',
		COLUMN_TYPE = convert(smallint, 5), /* return parameter */
		DATA_TYPE = 
		case 
			when d.data_type = 11
			then convert(smallint,93)
		else
			d.data_type+convert(smallint,
					  isnull(d.aux,
					     ascii(substring("666AAA@@@CB??GG",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
						          -60))
		end,
		TYPE_NAME = d.type_name,
		COLUMN_SIZE = isnull(d.data_precision, convert(int,d.length))
			     +isnull(d.aux, convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
						          2*(d.ss_dtype%35+1)
							  +2-8/d.length,1))
							  -60)),
		BUFFER_LENGTH = isnull(d.length, convert(int,t.length))
			 +convert(int, isnull(d.aux,
					     ascii(substring("AAA<BB<DDDHJSPP",
						    	     2*(d.ss_dtype%35
							     +1)+2-8/t.length,
						             1))-64)),
		DECIMAL_DIGITS = d.numeric_scale +convert(smallint,
					   isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
						        2*(d.ss_dtype%35+1)
							+2-8/d.length,
						        1))-60)),
		NUM_PREC_RADIX = d.numeric_radix,
		NULLABLE = convert(smallint, 1),
		REMARKS = convert(varchar(254),NULL),	/* Remarks are NULL */
                COLUMN_DEF = convert(varchar(254),NULL),
                SQL_DATA_TYPE = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/d.length,1))
                        -60))),
                SQL_DATETIME_SUB = NULL,
                CHAR_OCTET_LENGTH = NULL,
                ORDINAL_POSITION = convert(tinyint, 0),
                IS_NULLABLE = 'YES'
	from
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sysprocedures p
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_owner
		and d.ss_dtype = 56  /* int for return code */
		and t.type = 56
		and o.type = 'P'			/* Just Procedures */
		and p.id = o.id
		and 'RETURN_VALUE' like @column_name
	union
	select		   /* All other types including user data types */
		PROCEDURE_CAT = db_name(),
		PROCEDURE_SCHEM = user_name(o.uid),
		PROCEDURE_NAME = o.name,
                COLUMN_NAME =
		case
			when c.name = 'Return Type' then 'RETURN_VALUE'
			else c.name
		end,
                COLUMN_TYPE =
		case
			when c.name = 'Return Type'
				then convert(smallint, 5)
		when c.status2 = 1
			then convert(smallint, 1)
		when c.status2 = 2
			then convert(smallint, 4)
		when c.status2 = 4			     		
			then  convert(smallint, 2)                                        
			else convert(smallint, 0)
		end,
		/*   Map systypes.type to ODBC type    			*/
		/*   SS-Type  "				 1	      " */
		/*	      "33 3 3 4 44 5 5 2 5 55666"		*/
		/*	      "45 7 9 5 78 0 2 2 6 89012"    		*/
		DATA_TYPE = 
		case 
			when t.name = "date"
			then convert(smallint,91)
			when t.name = "time"
			then convert(smallint,92)
			when t.name = "datetime"
			then convert(smallint,93)
			
		   else		
			convert(smallint,
			       ascii(substring("8;<9<H<<<<<:<=6<5<A<?<@<GC?GD",
					       t.type%34+1,1))-60)
		end,
		TYPE_NAME =
                        case 
                            when t.name = 'extended type' 
                                then isnull(get_xtypename(c.xtype, c.xdbid),
									t.name)
			    when t.type = 58
			    	then "smalldatetime"
			    when t.usertype in (44,45,46)
				then "unsigned "+substring(t.name,
				charindex("u",t.name) + 1,
				charindex("t",t.name))
                            else 
                                t.name
                        end,


		COLUMN_SIZE = 
		case 
			when d.data_precision = 0
			then convert(int,0)
		else
		isnull(convert(int, c.prec),
			isnull(d.data_precision, convert(int,c.length)))
			     +isnull(d.aux, 
				     convert(int,
					     ascii(substring("???AAAFFFCKFOLS",
					                   2*(d.ss_dtype%35+1)
							   +2-8/c.length,1))
					           -60))
		end,
		BUFFER_LENGTH = isnull(d.length, convert(int,c.length))
			 +convert(int,
				  isnull(d.aux,
					 ascii(substring("AAA<BB<DDDHJSPP",
					                 2*(d.ss_dtype%35+1)
							 +2-8/c.length,
					                 1))-64)),
		DECIMAL_DIGITS = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale))
			+ convert(smallint,
				 isnull(d.aux,
					ascii(substring("<<<<<<<<<<<<<<?",
					                2*(d.ss_dtype%35+1)
							+2-8/c.length,
					                1))-60)),
		NUM_PREC_RADIX = d.numeric_radix,
		/* set nullability from status flag */
		NULLABLE = convert(smallint,1), /*convert(smallint, convert(bit, c.status&8)),*/
		REMARKS = convert(varchar(254),NULL),	/* Remarks are NULL */
                COLUMN_DEF = convert(varchar(254),NULL),
                SQL_DATA_TYPE = isnull(d.sql_data_type,
			d.data_type+convert(smallint,
                	isnull(d.aux,
                        ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1))
                        -60))),
                SQL_DATETIME_SUB = 
                case
                	when (isnull(d.sql_data_type,d.data_type+convert(smallint,
                	isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)))) = 91
                        then convert(smallint,1)
                	when (isnull(d.sql_data_type,d.data_type+convert(smallint,
                	isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)))) = 92
                        then convert(smallint,2)
                	when (isnull(d.sql_data_type,d.data_type+convert(smallint,
                	isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
                        2*(d.ss_dtype%35+1)+2-8/c.length,1)) -60)))) = 93
                        then convert(smallint,3)
                end,
		CHAR_OCTET_LENGTH = 
		/*
		** check if in the list
		** if so, return a 1 and multiply it by the precision
		** if not, return a 0 and multiply it by the precision
		*/
		case 
			when d.data_type = 4 then convert(smallint,NULL)
		else
			convert(smallint,
		    	substring('0111111',
			charindex(char(c.type),
			@char_bin_types)+1, 1)) *
			/* calculate the precision */
			isnull(convert(int, c.prec),
		    	isnull(convert(int, d.data_precision),
			convert(int, c.length)))
		    	+isnull(d.aux, convert(int,
			ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
		end,
                ORDINAL_POSITION = convert(int,c.colid),
                IS_NULLABLE = 'YES' /*rtrim(substring('NO YES',
                        (convert(smallint, convert(bit, c.status&8))*3)+1, 3))*/
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_owner
		and o.id = c.id
		and c.type *= d.ss_dtype
		and c.usertype *= t.usertype

                /* Just procs & sqlj procs and funcs */
		and o.type in ('P', 'F')
		and c.name like @column_name
		and d.ss_dtype not in (111, 109, 38, 110) /* No *N types */

	order by PROCEDURE_SCHEM, PROCEDURE_NAME, convert(int,colid)
end


go
exec sp_procxmode 'sp_odbc_getprocedurecolumns', 'anymode'
go
grant execute on sp_odbc_getprocedurecolumns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

print ""
go
print "Installed odbc_mda Stored Procedures ..."
go
declare @retval int
declare @version_string varchar(255) 
select @version_string = '15.0.0.346/'+ 'Fri 01-16-2009 17:45:38.79' 
exec @retval = sp_version 'ODBC MDA Scripts', NULL, @version_string, 'end'
if (@retval != 0) select syb_quit()
go
go
dump transaction sybsystemprocs with truncate_only
go
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_computeprivs')
begin
	drop procedure sp_oledb_computeprivs
end
go
print "Installing sp_oledb_computeprivs"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_datatype_info')
begin
	drop procedure sp_oledb_datatype_info
end
go
print "Installing sp_oledb_datatype_info"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_gettableprivileges')
begin
	drop procedure sp_oledb_gettableprivileges
end
go
print "Installing sp_oledb_gettableprivileges"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_tables')
begin
	drop procedure sp_oledb_tables
end
go
print "Installing sp_oledb_tables"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_statistics')
begin
	drop procedure sp_oledb_statistics
end
go
print "Installing sp_oledb_statistics"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_stored_procedures')
begin
	drop procedure sp_oledb_stored_procedures
end
go
print "Installing sp_oledb_stored_procedures"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_getprocedurecolumns')
begin
	drop procedure sp_oledb_getprocedurecolumns
end
go
print "Installing sp_oledb_getprocedurecolumns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_getindexinfo')
begin
	drop procedure sp_oledb_getindexinfo
end
go
print "Installing sp_oledb_getindexinfo"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_primarykey')
begin
	drop procedure sp_oledb_primarykey
end
go
print "Installing sp_oledb_primarykey"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_fkeys')
begin
	drop procedure sp_oledb_fkeys
end
go
print "Installing sp_oledb_fkeys"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_columns')
begin
	drop procedure sp_oledb_columns
end
go
print "Installing sp_oledb_columns"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_getcolumnprivileges')
begin
	drop procedure sp_oledb_getcolumnprivileges
end
go
print "Installing sp_oledb_getcolumnprivileges"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_databases')
begin
	drop procedure sp_oledb_databases
end
go
print "Installing sp_oledb_databases"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_views')
begin
	drop procedure sp_oledb_views
end
go
print "Installing sp_oledb_views"
go

/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*
**  OLEDB_INSTALL
**  This file contains the metadata Stored Procedures used by the OLEDB drivers.
**
*/

/*
 ** Stored procedures created:
 **
 ** Name                          	Default Location	Comments
 ** --------------------------------------------------------------------------------------------------
 ** 1>  sp_oledb_server_info		sybsystemprocs
 ** 2>  sp_oledb_databases		sybsystemprocs
 ** 3>  sp_oledb_columns		sybsystemprocs
 ** 4>  sp_oledb_datatype_info		sybsystemprocs
 ** 5>  sp_oledb_getversioncolumns	sybsystemprocs		
 ** 6>  sp_oledb_getcolumnprivileges	sybsystemprocs
 ** 7>  sp_oledb_tables			sybsystemprocs
 ** 8>  sp_oledb_gettableprivileges	sybsystemprocs
 ** 9>  sp_oledb_getindexinfo		sybsystemprocs
 ** 10> sp_oledb_primarykey		sybsystemprocs
 ** 11> sp_oledb_fkeys			sybsystemprocs
 ** 12> sp_oledb_stored_procedures	sybsystemprocs
 ** 13> sp_oledb_getprocedurecolumns	sybsystemprocs
 ** 14> sp_oledb_computeprivs		sybsystemprocs	added to support 
 ** 15> sp_oledb_gettableprivileges
 ** 16> sp_oledb_getcolumnprivileges
 ** 17> sp_oledb_views
 ** 18> sp_version			sybsystemprocs
 */
 
set flushmessage on
go

print ""
go


-- select @version_string = "@oledbMajorVersion@.@oledbMinorVersion1@.@oledbMinorVersion2@.@BuildNumber@"
declare @version_string varchar(255) 
select @version_string = '15.0.0.346/'+ 'Fri 01-16-2009 17:45:38.79' 
print "OLEDB - Build Version : %1!", @version_string 
declare @retval int
exec @retval = sp_version 'OLEDB MDA Scripts', NULL, @version_string, 'start'
if (@retval != 0) select syb_quit()
go
use sybsystemprocs
go



if exists (select * from sysobjects where name = 'spt_sybdrv')
begin			
	drop table spt_sybdrv
end
go
print "Creating spt_sybdrv"
go

create table spt_sybdrv
(type_name varchar(20) Primary Key,
  data_type int, tds_type int null)
go
begin 
 insert into spt_sybdrv values("smallint",2,52)
 insert into spt_sybdrv values("int",3, 56)
 insert into spt_sybdrv values("real",4, 59)
 insert into spt_sybdrv values("float",5, 62)
 insert into spt_sybdrv values("money",6, 60)
 insert into spt_sybdrv values("smallmoney",6,122)
 insert into spt_sybdrv values("bit",11, 50)
 insert into spt_sybdrv values("tinyint",17,48)
 insert into spt_sybdrv values("binary",128,45)
 insert into spt_sybdrv values("image",128,34)
 insert into spt_sybdrv values("varbinary",128,37)
 insert into spt_sybdrv values("char",129, 47)
 insert into spt_sybdrv values("varchar",129,39)
 insert into spt_sybdrv values("text",129,35) 
 insert into spt_sybdrv values("nchar",129,47)
 insert into spt_sybdrv values("nvarchar",129,39)
 insert into spt_sybdrv values("unitext",130,174)
 insert into spt_sybdrv values("unichar",130, 135)
 insert into spt_sybdrv values("univarchar",130, 155)
 insert into spt_sybdrv values("numeric",131,63)
 insert into spt_sybdrv values("decimal",131,55)
 insert into spt_sybdrv values("date",133,49)
 insert into spt_sybdrv values("time",134,51)
 insert into spt_sybdrv values("datetime",135,61)
 insert into spt_sybdrv values("smalldatetime",135,58)
  insert into spt_sybdrv values("bigint",20,191)
  insert into spt_sybdrv values("unsigned smallint",18,65)
  insert into spt_sybdrv values("unsigned int",19,66)
  insert into spt_sybdrv values("unsigned bigint",21,67)


end
 
 print "spt_sybdrv created!"
go


grant select on spt_sybdrv to public
go

if exists (select * from sysobjects where name = 'sp_oledb_computeprivs')
    begin
        drop procedure sp_oledb_computeprivs
    end
go



/*
** Results Table needs to be created so that sp_oledb_computeprivs has a temp
** table to reference when the procedure is compiled.  Otherwise, the calling
** stored procedure will create the temp table for sp_oledb_computeprivs.
*/
create table #results_table
    (table_qualifier        varchar (32),
     table_owner            varchar (32),
     table_name             varchar (255),
     column_name            varchar (255) NULL,
     grantor                varchar (32),
     grantee                varchar (32),
     privilege              varchar (32),
     is_grantable           varchar (3))
go

 

create procedure sp_oledb_computeprivs (
                        @table_name             varchar(255),
                        @table_owner            varchar(32),
                        @table_qualifier        varchar(32),
                        @column_name            varchar(255),
                        @calledfrom_colpriv     tinyint,
                        @tab_id                 int)

AS

/* Don't delete the following line. It is the checkpoint for sed */
/* Server dependent stored procedure add here ad ADDPOINT_COMPUTE_PRIVS */
--    declare @low 		int		/* range of userids to check */
--    declare @high 		int
--    declare @max_uid		smallint        /* max uid allowed for a user */

    declare @grantor_name       varchar (32)    /* the ascii name of grantor.
                                                   used for output */
    declare @grantee_name       varchar (32)    /* the ascii name of grantee.
                                                   used for output */
    declare @col_count          smallint        /* number of columns in
                                                   @table_name */
    declare @grantee            int             /* id of the grantee */
    declare @action             smallint        /* action refers to select,
                                                   update...*/
    declare @columns            varbinary (133) /* bit map of column
                                                   privileges */
    declare @protecttype        tinyint         /* grant/revoke or grant with
                                                   grant option */
    declare @grantor            int             /* id of the grantor of the
                                                   privilege */
    declare @grp_id             int             /* the group a user belongs
                                                   to */
    declare @grant_type         tinyint         /* used as a constant */
    declare @revoke_type        tinyint         /* used as a constant */
    declare @select_action      smallint        /* used as a constant */
    declare @update_action      smallint        /* used as a constant */
    declare @reference_action   smallint        /* used as a constant */
    declare @insert_action      smallint        /* used as a constant */
    declare @delete_action      smallint        /* used as a constant */
    declare @public_select      varbinary (133) /* stores select column bit map
                                                   for public */
    declare @public_reference   varbinary (133) /* stores reference column bit
                                                   map for public */
    declare @public_update      varbinary (133) /* stores update column bit map
                                                   for public */
    declare @public_insert      tinyint         /* stores if insert has been
                                                   granted to public */
    declare @public_delete      tinyint         /* store if delete has been
                                                   granted to public */
    declare @grp_select         varbinary (133) /* stores select column bit map
                                                   for group */
    declare @grp_update         varbinary (133) /* stores update column bit map
                                                   for group */
    declare @grp_reference      varbinary (133) /* stores reference column bit
                                                   map for group */
    declare @grp_delete         tinyint         /* if group hs been granted
                                                   delete privilege */
    declare @grp_insert         tinyint         /* if group has been granted
                                                   insert privilege */
    declare @inherit_select     varbinary (133) /* stores select column bit map
                                                   for inherited privs*/
    declare @inherit_update     varbinary (133) /* stores update column bit map
                                                   for inherited privs */
    declare @inherit_reference  varbinary (133) /* stores reference column bit
                                                   map for inherited privs */
    declare @inherit_insert     tinyint         /* inherited insert priv */
    declare @inherit_delete     tinyint         /* inherited delete priv */
    declare @select_go          varbinary (133) /* user column bit map of
                                                   select with grant */
    declare @update_go          varbinary (133) /* user column bit map of
                                                   update with grant */
    declare @reference_go       varbinary (133) /* user column bitmap of
                                                   reference with grant */
    declare @insert_go          tinyint         /* user insert priv with
                                                   grant option */
    declare @delete_go          tinyint         /* user delete priv with grant
                                                   option  */
    declare @prev_grantor       int             /* used to detect if the
                                                   grantor has changed between
                                                   two consecutive tuples */
    declare @col_pos            smallint        /* col_pos of the column we are
                                                   interested in. It is used to
                                                   find the col-bit in the
                                                   bitmap */
    declare @owner_id           int             /* id of the owner of the
                                                   table */
    declare @dbid               smallint        /* dbid for the table */
    declare @grantable          varchar (3)     /* 'YES' or 'NO' if the
                                                   privilege is grantable or
                                                   not */
    declare @is_printable       tinyint         /* 1, if the privilege info is
                                                   to be outputted */
     
     
     
    declare @startedInTransaction bit
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0
                                                       

    if (@startedInTransaction = 1)
	save transaction oledb_keep_temptable_tx    

/* 
** Initialize all constants to be used in this procedure
*/

    select @grant_type = 1

    select @revoke_type = 2
   
    select @select_action = 193

    select @reference_action = 151

    select @update_action = 197

    select @delete_action = 196

    select @insert_action = 195

--    select @max_uid = 16383

--    select @low = -32768, @high = 32767
/*
** compute the table owner id
*/

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id

/*



** create a temporary sysprotects table that only has grant/revoke tuples
** for the requested table. This is done as an optimization as the sysprotects
** table may need to be traversed several times
*/

    create table #sysprotects
        (uid            int,
         action         smallint,
         protecttype    tinyint,
         columns        varbinary (133) NULL,
         grantor        int)

/*
** This table contains all the groups including PUBLIC that users, who
** have been granted privilege on this table, belong to. Also it includes
** groups that have been explicitly granted privileges on the table object
*/
    create table #useful_groups
        (grp_id         int)

/*
** create a table that contains the list of grantors for the object requested.
** We will do a cartesian product of this table with sysusers in the
** current database to capture all grantor/grantee tuples
*/

    create table #distinct_grantors
        (grantor        int)

/*
** We need to create a table which will contain a row for every object
** privilege to be returned to the client.  
*/

    create table #column_privileges 
        (grantee_gid    int,
         grantor        int,
         grantee        int,
         insertpriv     tinyint,
         insert_go      tinyint NULL,
         deletepriv     tinyint,
         delete_go      tinyint NULL,
         selectpriv     varbinary (133) NULL,
         select_go      varbinary (133) NULL,
         updatepriv     varbinary (133) NULL,
         update_go      varbinary (133) NULL,
         referencepriv  varbinary (133) NULL,
         reference_go   varbinary (133) NULL)

/*
** this cursor scans the distinct grantor, group_id pairs
*/
    declare grp_cursor cursor for
        select distinct grp_id, grantor 
        from #useful_groups, #distinct_grantors
        order by grantor

/* 
** this cursor scans all the protection tuples that represent
** grant/revokes to users only
*/
    declare user_protect cursor for
        select uid, action, protecttype, columns, grantor
        from   #sysprotects
        where  (uid != 0) and
--              (uid <= @max_uid)
               ((uid >= @@minuserid and uid < @@mingroupid) or 
               (uid > @@maxgroupid and uid <= @@maxuserid)) 


/*
** this cursor is used to scan #column_privileges table to output results
*/
    declare col_priv_cursor cursor for
          select grantor, grantee, insertpriv, insert_go, deletepriv,
              delete_go, selectpriv, select_go, updatepriv, update_go,
              referencepriv, reference_go
          from #column_privileges



/*
** column count is needed for privilege bit-map manipulation
*/
    select @col_count = count (*) 
    from   syscolumns
    where  id = @tab_id


/* 
** populate the temporary sysprotects table #sysprotects
*/

        insert into #sysprotects 
                select uid, action, protecttype, columns, grantor
                from sysprotects
                where (id = @tab_id)               and
                      ((action = @select_action)   or
                      (action = @update_action)    or
                      (action = @reference_action) or
                      (action = @insert_action)    or
                      (action = @delete_action))

/* 
** insert privilege tuples for the table owner. There is no explicit grants
** of these privileges to the owner. So these tuples are not there in
** sysprotects table
*/

if not exists (select * from #sysprotects where (action = @select_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @select_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @update_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @update_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @reference_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @reference_action, 0, 0x01, @owner_id)
end

if not exists (select * from #sysprotects where (action = @insert_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @insert_action, 0, NULL, @owner_id)
end

if not exists (select * from #sysprotects where (action = @delete_action) and
                (protecttype = @revoke_type) and (uid = @owner_id))
begin
        insert into #sysprotects
             values (@owner_id, @delete_action, 0, NULL, @owner_id)
end


/* 
** populate the #distinct_grantors table with all grantors that have granted
** the privilege to users or to gid or to public on the table_name
*/

    insert into #distinct_grantors 
          select distinct grantor from #sysprotects

/* 
** Populate the #column_privilegs table as a cartesian product of the table
** #distinct_grantors and all the users, other than groups, in the current
** database
*/


    insert into #column_privileges
          select gid, g.grantor, su.uid, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00,
              0x00, 0x00
          from sysusers su, #distinct_grantors g
        where  (su.uid != 0) and
--                (su.uid <= @max_uid)        
               ((su.uid >= @@minuserid and su.uid < @@mingroupid) or
               (su.uid > @@maxgroupid and su.uid <= @@maxuserid)) 

/*
** populate #useful_groups with only those groups whose members have been
** granted/revoked privileges on the @tab_id in the current database. It also
** contains those groups that have been granted/revoked privileges explicitly
*/

    insert into #useful_groups
        select distinct gid
        from   sysusers su, #sysprotects sp
        where  (su.uid = sp.uid) 


    open grp_cursor

    fetch grp_cursor into @grp_id, @grantor

    /* 
    ** This loop computes all the inherited privilegs of users due
    ** their membership in a group
    */

    while (@@sqlstatus != 2)
   
    begin

         /* 
         ** initialize variables 
         */
         select @public_select = 0x00
         select @public_update = 0x00
         select @public_reference = 0x00
         select @public_delete = 0
         select @public_insert = 0


         /* get the select privileges granted to PUBLIC */

         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @select_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_select = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @select_action)
         end


         /* get the update privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @update_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_update = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @update_action)
         end

         /* get the reference privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @reference_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_reference = columns
              from #sysprotects
              where (grantor = @grantor) and 
                    (uid = 0) and
                    (action = @reference_action)
         end


         /* get the delete privilege granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @delete_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_delete = 1
         end

         /* get the insert privileges granted to public */
         if (exists (select * from #sysprotects 
                     where (grantor = @grantor) and 
                           (uid = 0) and
                           (action = @insert_action)))
         begin
              /* note there can't be any revoke row for PUBLIC */
              select @public_insert = 1
         end


         /*
         ** initialize group privileges 
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** if the group id is other than PUBLIC, we need to find the grants to
         ** the group also 
         */

         if (@grp_id <> 0)
         begin
                /* find select privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @select_action)
                end

                /* find update privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @update_action)
                end

                /* find reference privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @grant_type) and 
                              (action = @reference_action)
                end

                /* find delete privileges granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @delete_action)))
                begin

                        select @grp_delete = 1
                end

                /* find insert privilege granted to group */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @grant_type) and
                                  (action = @insert_action)))
                begin

                        select @grp_insert = 1

                end

         end

         /* at this stage we have computed all the grants to PUBLIC as well as
         ** the group by a specific grantor that we are interested in. Now we
         ** will use this info to compute the overall inherited privileges by
         ** the users due to their membership to the group or to PUBLIC 
         */


         exec sybsystemprocs.dbo.syb_aux_privunion @public_select, @grp_select,
             @col_count, @inherit_select output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_update, @grp_update, 
             @col_count, @inherit_update output
         exec sybsystemprocs.dbo.syb_aux_privunion @public_reference,
             @grp_reference, @col_count, @inherit_reference output

         select @inherit_insert = @public_insert + @grp_insert
         select @inherit_delete = @public_delete + @grp_delete

         /*
         ** initialize group privileges to store revokes
         */

         select @grp_select = 0x00
         select @grp_update = 0x00
         select @grp_reference = 0x00
         select @grp_insert = 0
         select @grp_delete = 0

         /* 
         ** now we need to find if there are any revokes on the group under
         ** consideration. We will subtract all privileges that are revoked
         ** from the group from the inherited privileges
         */

         if (@grp_id <> 0)
         begin
                /* check if there is a revoke row for select privilege*/
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @select_action)))
                begin
                        select @grp_select = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @select_action)
                end

                /* check if there is a revoke row for update privileges */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @update_action)))
                begin
                        select @grp_update = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @update_action)
                end

                /* check if there is a revoke row for reference privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @reference_action)))
                begin
                        select @grp_reference = columns
                        from #sysprotects
                        where (grantor = @grantor) and 
                              (uid = @grp_id) and
                              (protecttype = @revoke_type) and 
                              (action = @reference_action)
                end

                /* check if there is a revoke row for delete privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @delete_action)))
                begin
                        select @grp_delete = 1
                end

                /* check if there is a revoke row for insert privilege */
                if (exists (select * from #sysprotects 
                            where (grantor = @grantor) and 
                                  (uid = @grp_id) and
                                  (protecttype = @revoke_type) and
                                  (action = @insert_action)))
                begin
                        select @grp_insert = 1

                end


                /* 
                ** now subtract the revoked privileges from the group
                */

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                                                 @grp_select,
                                                 @col_count,
                                                 @inherit_select output

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                                                 @grp_update,
                                                 @col_count,
                                                 @inherit_update output

                exec sybsystemprocs.dbo.syb_aux_privexor @inherit_reference,
                                                 @grp_reference,
                                                 @col_count,
                                                 @inherit_reference output

                if (@grp_delete = 1)
                        select @inherit_delete = 0

                if (@grp_insert = 1)
                        select @inherit_insert = 0

         end

         /*
         ** now update all the tuples in #column_privileges table for this
         ** grantor and group id
         */

         update #column_privileges
         set
                insertpriv      = @inherit_insert,
                deletepriv      = @inherit_delete,
                selectpriv      = @inherit_select,
                updatepriv      = @inherit_update,
                referencepriv   = @inherit_reference

         where (grantor     = @grantor) and
               (grantee_gid = @grp_id)


         /*
         ** the following update updates the privileges for those users
         ** whose groups have not been explicitly granted privileges by the
         ** grantor. So they will all have all the privileges of the PUBLIC
         ** that were granted by the current grantor
         */

         select @prev_grantor = @grantor         
         fetch grp_cursor into @grp_id, @grantor

         if ((@prev_grantor <> @grantor) or (@@sqlstatus = 2))

         begin
         /* Either we are at the end of the fetch or we are switching to
         ** a different grantor. 
         */

               update #column_privileges 
               set
                        insertpriv      = @public_insert,
                        deletepriv      = @public_delete,
                        selectpriv      = @public_select,
                        updatepriv      = @public_update,
                        referencepriv   = @public_reference
                from #column_privileges cp
                where (cp.grantor = @prev_grantor) and
                      (not EXISTS (select * 
                                   from #useful_groups ug
                                   where ug.grp_id = cp.grantee_gid))

         end
    end


    close grp_cursor


    /* 
    ** At this stage, we have populated the #column_privileges table with
    ** all the inherited privileges
    */
    /*
    ** update #column_privileges to give all access to the table owner that way
    ** if there are any revoke rows in sysprotects, then the calculations will
    ** be done correctly.  There will be no revoke rows for table owner if
    ** privileges are revoked from a group that the table owner belongs to.
    */
    update #column_privileges
    set
        insertpriv      = 0x01, 
        deletepriv      = 0x01, 
        selectpriv      = 0x01,
        updatepriv      = 0x01,
        referencepriv   = 0x01

        where grantor = grantee
          and grantor = @owner_id

    
    /* 
    ** Now we will go through each user grant or revoke in table #sysprotects
    ** and update the privileges in #column_privileges table
    */
    open user_protect

    fetch user_protect into @grantee, @action, @protecttype, @columns, @grantor

    while (@@sqlstatus != 2)
    begin
        /*
        ** In this loop, we can find grant row, revoke row or grant with grant
        ** option row. We use protecttype to figure that. If it is grant, then
        ** the user specific privileges are added to the user's inherited
        ** privileges. If it is a revoke, then the revoked privileges are
        ** subtracted from the inherited privileges. If it is a grant with
        ** grant option, we just store it as is because privileges can
        ** only be granted with grant option to individual users
        */

        /* 
        ** for select action
        */
        if (@action = @select_action)
        begin
             /* get the inherited select privilege */
             select @inherit_select = selectpriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)

             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_select,
                    @columns, @col_count, @inherit_select output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_select,
                         @columns, @col_count, @inherit_select output

                else
                     /* it is a grant with grant option */

                     select @select_go = @columns

             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set selectpriv = @inherit_select
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin

                  update #column_privileges
                  set select_go = @select_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /*
        ** update action
        */
        if (@action = @update_action)
        begin
             /* find out the inherited update privilege */
             select @inherit_update = updatepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* user has an individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_update,
                    @columns, @col_count, @inherit_update output

             else 
                if (@protecttype = @revoke_type)
                     exec sybsystemprocs.dbo.syb_aux_privexor @inherit_update,
                         @columns, @col_count, @inherit_update output

                else
                     /* it is a grant with grant option */
                     select @update_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set updatepriv = @inherit_update
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set update_go = @update_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
        end

        /* it is the reference privilege */
        if (@action = @reference_action)
        begin
             select @inherit_reference = referencepriv
             from   #column_privileges
             where  (grantee = @grantee) and
                    (grantor = @grantor)


             if (@protecttype = @grant_type)
             /* the grantee has a individual grant */
                exec sybsystemprocs.dbo.syb_aux_privunion @inherit_reference,
                    @columns, @col_count, @inherit_reference output

             else 
                if (@protecttype = @revoke_type)
                /* it is a revoke row */
                     exec sybsystemprocs.dbo.syb_aux_privexor
                        @inherit_reference, @columns, @col_count,
                        @inherit_reference output

                else
                     /* it is a grant with grant option */
                     select @reference_go = @columns


             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set referencepriv = @inherit_reference
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set reference_go = @reference_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /*
        ** insert action
        */

        if (@action = @insert_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_insert = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_insert = 0
                 else
                      select @insert_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set insertpriv = @inherit_insert
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set insert_go = @insert_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        /* 
        ** delete action
        */

        if (@action = @delete_action)
        begin
             if (@protecttype = @grant_type)
                   select @inherit_delete = 1
             else
                 if (@protecttype = @revoke_type)
                      select @inherit_delete = 0
                 else
                      select @delete_go = 1

             
             /* modify the privileges for this user */

             if ((@protecttype = @revoke_type) or (@protecttype = @grant_type))
             begin
                  update #column_privileges
                  set deletepriv = @inherit_delete
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end
             else
             begin
                  update #column_privileges
                  set delete_go = @delete_go
                  where (grantor = @grantor) and
                        (grantee = @grantee)
             end

        end

        fetch user_protect into @grantee, @action, @protecttype, @columns,
            @grantor
    end

    close user_protect

open col_priv_cursor
fetch col_priv_cursor into @grantor, @grantee, @inherit_insert, @insert_go,
                         @inherit_delete, @delete_go, @inherit_select,
                         @select_go, @inherit_update, @update_go,
                         @inherit_reference, @reference_go

while (@@sqlstatus != 2)
begin

      /* 
      ** name of the grantor
      */
      select @grantor_name = name 
      from   sysusers
      where  uid = @grantor


      /*
      ** name of the grantee
      */

      select @grantee_name = name
      from   sysusers
      where  uid = @grantee

      /* 
      ** At this point, we are either printing privilege information for a
      ** a specific column or for table_privileges
      */

            select @col_pos = 0

            if (@calledfrom_colpriv = 1)
            begin
            /* 
            ** find the column position
            */
                 select @col_pos = colid
                 from syscolumns
                 where (id = @tab_id) and
                       (name = @column_name)
            end

            /* 
            ** check for insert privileges
            */
            /* insert privilege is only a table privilege */
            if (@calledfrom_colpriv = 0)
            begin
                    exec sybsystemprocs.dbo.syb_aux_printprivs 
                        @calledfrom_colpriv, @col_pos, @inherit_insert,
                        @insert_go, 0x00, 0x00, 0, @grantable output,
                        @is_printable output

                    if (@is_printable = 1)
                    begin
                          insert into #results_table
                               values (@table_qualifier, @table_owner,
                                       @table_name, @column_name,
                                       @grantor_name, @grantee_name, 'INSERT',
                                       @grantable)
                    end
            end

            /* 
            ** check for delete privileges
            */

            if (@calledfrom_colpriv = 0)
            /* delete privilege need only be printed if called from
               sp_table_privileges */
            begin
                    exec sybsystemprocs.dbo.syb_aux_printprivs 
                         @calledfrom_colpriv, @col_pos, @inherit_delete,
                         @delete_go, 0x00, 0x00, 0, @grantable output,
                         @is_printable output

                    if (@is_printable = 1)
                    begin
                        insert into #results_table
                                values (@table_qualifier, @table_owner,
                                        @table_name, @column_name,
                                        @grantor_name, @grantee_name, 'DELETE',
                                        @grantable)
                    end
            end

            /* 
            ** check for select privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                        @calledfrom_colpriv, @col_pos, 0, 0, @inherit_select,
                        @select_go, 1, @grantable output, @is_printable output


            if (@is_printable = 1)
            begin
                  insert into #results_table
                         values (@table_qualifier, @table_owner, @table_name,
                                 @column_name, @grantor_name, @grantee_name,
                                 'SELECT', @grantable)
            end
            /* 
            ** check for update privileges
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                @calledfrom_colpriv, @col_pos, 0, 0, @inherit_update,
                @update_go, 1, @grantable output, @is_printable output

            if (@is_printable = 1)
            begin
                  insert into #results_table
                        values (@table_qualifier, @table_owner, @table_name,
                                @column_name, @grantor_name, @grantee_name,
                                'UPDATE', @grantable)
            end
            /*
            ** check for reference privs
            */
            exec sybsystemprocs.dbo.syb_aux_printprivs 
                @calledfrom_colpriv, @col_pos, 0, 0, @inherit_reference,
                @reference_go, 1, @grantable output, @is_printable output

            if (@is_printable = 1)
            begin
                insert into #results_table
                        values (@table_qualifier, @table_owner, @table_name,
                                @column_name, @grantor_name, @grantee_name,
                                'REFERENCE', @grantable)
            end



      fetch col_priv_cursor into @grantor, @grantee, @inherit_insert,
          @insert_go, @inherit_delete, @delete_go, @inherit_select, @select_go,
          @inherit_update, @update_go, @inherit_reference, @reference_go
end

close col_priv_cursor
    drop table #column_privileges
    drop table #distinct_grantors
    drop table #sysprotects
    drop table #useful_groups
   
if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx    

go

/*
** Drop temp table used for creation of sp_oledb_computeprivs
*/
drop table #results_table
go

exec sp_procxmode 'sp_oledb_computeprivs', 'anymode'
go

grant execute on sp_oledb_computeprivs to public
go


if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_datatype_info')
begin
	drop procedure sp_oledb_datatype_info
end
go

create procedure sp_oledb_datatype_info
@data_type int = 0,			/* Provide datatype_info for type # */
@best_match bit  = 0
as
declare @startedInTransaction bit

if (@@trancount > 0)
	select @startedInTransaction = 1
else
	select @startedInTransaction = 0

if (@startedInTransaction = 1)
 	save transaction oledb_keep_temptable_tx    

 create table #oledb_results_table
 (
  TYPE_NAME		varchar (255)  null,
  DATA_TYPE		smallint null,
  COLUMN_SIZE		int  null,
  LITERAL_PREFIX	varchar (32) null,
  LITERAL_SUFFIX		varchar (32) null,
  CREATE_PARAMS		varchar (32) null,
  IS_NULLABLE		bit,
  CASE_SENSITIVE	bit,
  SEARCHABLE		int null,
  UNSIGNED_ATTRIBUTE	bit,
  FIXED_PREC_SCALE	bit,
  AUTO_UNIQUE_VALUE	bit,
  LOCAL_TYPE_NAME	varchar (128) null,
  MINIMUM_SCALE 	smallint null,
  MAXIMUM_SCALE		smallint null,
  GUID			varchar (32) null,
  TYPELIB		varchar (32) null,
  VERSION		varchar (32) null,
  IS_LONG		bit,
  BEST_MATCH		bit,
  IS_FIXEDLENGTH	bit

  )

insert #oledb_results_table
select	/* Real SQL Server data types */
	TYPE_NAME = case
			when t.usertype in (44,45,46)
			then "unsigned "+substring(t.name,
			charindex("u",t.name) + 1,
			charindex("t",t.name))
		     else		
			t.name
		    end,
	DATA_TYPE = d.ss_dtype,
	COLUMN_SIZE = isnull(d.data_precision, 
			    convert(int,t.length)),
	LITERAL_PREFIX = d.literal_prefix,
	LITERAL_SUFFIX = d.literal_suffix,
	CREATE_PARAMS = e.create_params,
	IS_NULLABLE = convert(bit,d.nullable),
	CASE_SENSITIVE = d.case_sensitive,
	SEARCHABLE = d.searchable + 1,
	UNSIGNED_ATTRIBUTE = isnull(d.unsigned_attribute, convert(bit,1)),
	FIXED_PREC_SCALE = convert(bit,d.money),
	AUTO_UNIQUE_VALUE = isnull(d.auto_increment,convert(bit,0)),
	LOCAL_TYPE_NAME = d.local_type_name,
	MINIMUM_SCALE = d.minimum_scale,
	MAXIMUM_SCALE = d.maximum_scale,
	GUID = convert(varchar(255), null),
	TYPE_LIB =  convert(varchar(255), null),
	VERSION =  convert(varchar(255), null),
	ISLONG = convert(bit,0),
	BEST_MATCH = convert(bit,0),
	IS_FIXEDLENGTH = convert(bit,0)

from 	sybsystemprocs.dbo.spt_datatype_info d, syscolumns c,
	sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where
	d.ss_dtype = t.type
	and t.usertype *= e.user_type
	    /* restrict results to "real" datatypes */
	and t.name not in ("nchar","nvarchar",
			   "sysname","longsysname","timestamp",
			   "datetimn","floatn","intn","uintn","moneyn",
			   "extended type")
	and t.usertype < 100	/* No user defined types */
UNION
select	/* SQL Server user data types */
	TYPE_NAME = t.name,
	DATA_TYPE = d.ss_dtype,
	COLUMN_SIZE = isnull(d.data_precision, 
			    convert(int,t.length)),
	LITERAL_PREFIX = d.literal_prefix,
	LITERAL_SUFFIX = d.literal_suffix,
	CREATE_PARAMS = e.create_params,
	IS_NULLABLE = convert(bit,d.nullable),
	CASE_SENSITIVE = d.case_sensitive,
	SEARCHABLE = d.searchable + 1,
	UNSIGNED_ATTRIBUTE = isnull(d.unsigned_attribute, convert(bit,1)),
	FIXED_PREC_SCALE = convert(bit,d.money),
	AUTO_UNIQUE_VALUE = isnull(d.auto_increment,convert(bit,0)),
	LOCAL_TYPE_NAME = t.name,
	MINIMUM_SCALE = d.minimum_scale,
	MAXIMUM_SCALE = d.maximum_scale,
	GUID = convert(varchar(255), null),
	TYPE_LIB =  convert(varchar(255), null),
	VERSION =  convert(varchar(255), null),
	ISLONG = convert(bit,0),
	BEST_MATCH = convert(bit,0),
	IS_FIXEDLENGTH = convert(bit,0)
from 	sybsystemprocs.dbo.spt_datatype_info d, syscolumns c,
	sybsystemprocs.dbo.spt_datatype_info_ext e, systypes t
where
	d.ss_dtype = t.type
	and t.usertype *= e.user_type
	    /* 
	    ** Restrict to user defined types (value > 100)
	    ** and Sybase user defined types (listed)
	    */
	and (t.name in ("nchar","nvarchar",
			    "sysname","timestamp")
	    and t.usertype < 100)      /* User defined types */
order by  TYPE_NAME
	
delete 	from #oledb_results_table where DATA_TYPE = 0	
update #oledb_results_table set o.DATA_TYPE = m.data_type   from
	sybsystemprocs.dbo.spt_sybdrv m, #oledb_results_table  o
	where o.TYPE_NAME =  m.type_name 

update #oledb_results_table set IS_FIXEDLENGTH = 1 where DATA_TYPE not in (37,39,35,155) and TYPE_NAME not in ("varchar", "varbinary", "univarchar", "text", "unitext", "image", "nvarchar")
update #oledb_results_table set IS_LONG = 1 where DATA_TYPE  in (34,35,174) or TYPE_NAME  in ("text",  "image", "unitext")


	
update #oledb_results_table set o.DATA_TYPE = m.data_type   from
	sybsystemprocs.dbo.spt_sybdrv m, #oledb_results_table  o
	where o.TYPE_NAME not in  (select type_name from sybsystemprocs.dbo.spt_sybdrv) and
	o.DATA_TYPE = m.tds_type

update #oledb_results_table set BEST_MATCH = 1 where DATA_TYPE not in (6, 128, 129, 130,131,135) 
update #oledb_results_table set BEST_MATCH = 1 where TYPE_NAME  = "money"
update #oledb_results_table set BEST_MATCH = 1 where TYPE_NAME  = "char"
update #oledb_results_table set BEST_MATCH = 1 where TYPE_NAME  = "unichar"
update #oledb_results_table set BEST_MATCH = 1 where TYPE_NAME  = "numeric"
update #oledb_results_table set BEST_MATCH = 1 where TYPE_NAME  = "binary"
update #oledb_results_table set BEST_MATCH = 1 where TYPE_NAME  = "datetime"

if(@data_type = 0)
select * from  #oledb_results_table order by DATA_TYPE, TYPE_NAME
else


if(@best_match = 0)
select * from  #oledb_results_table where DATA_TYPE = @data_type
else
select * from  #oledb_results_table where DATA_TYPE = @data_type 
and @best_match = 1

drop table  #oledb_results_table
if (@startedInTransaction = 1)
    rollback transaction oledb_keep_temptable_tx    

return (0)
go
exec sp_procxmode 'sp_oledb_datatype_info', 'anymode'
go
grant execute on sp_oledb_datatype_info to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go
print " Installed sp_oledb_datatype_info"
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_gettableprivileges')
begin
	drop procedure sp_oledb_gettableprivileges
end
go

/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_oledb_gettableprivileges ( 
                        @table_name  varchar(771) = null,
                        @table_schema varchar(32) = null,
                        @table_catalog varchar(32)= null,
                        @grantor varchar(32)= null,
                        @grantee varchar(32)= null)
as        
 
    declare @owner_id    		int
    declare @full_table_name    	varchar(1543)
    declare @tab_id 			int	    /* object id of the table specified */

    declare @tab_name                   varchar(255)
    declare @tab_owner                  varchar(32)
    declare @table_id 			int	    /* object id of the
                                                       table specified */
    declare @startedInTransaction bit
    
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

 
    set nocount on
    set transaction isolation level 1
    
    if (@startedInTransaction = 1)
 	save transaction oledb_keep_temptable_tx   
    

    /*
    **  Check to see that the table is qualified with the database name
    */
    if @table_name like "%.%.%"
    begin
	/* 18021, "Object name can only be qualified with owner name." */
	raiserror 18021
	return (1)
    end

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like "#%" and db_name() != db_name(tempdb_id()))
    begin
	/* 
	** 17676, "This may be a temporary object. Please execute 
	** procedure from your temporary database."
	*/
	raiserror 17676
	return (1)
    end

   /*
   ** Results Table needs to be created so that sp_oledb_computeprivs has a temp
   ** table to reference when the procedure is compiled.  Otherwise, the calling
   ** stored procedure will create the temp table for sp_oledb_computeprivs.
   */
  create table #results_table
  	 (TABLE_CATALOG	varchar (32),
  	  TABLE_SCHEMA		varchar (32),
  	  TABLE_NAME		varchar (255),
  	  column_name		varchar (255) NULL,
  	  GRANTOR		varchar (32),
  	  GRANTEE 		varchar (32),
  	  PRIVILEGE_TYPE	varchar (32),
  	  IS_GRANTABLE		varchar (3))
  	  
    /*
    ** The table_catalog should be same as the database name. Do the sanity check
    ** if it is specified
    */
    if (@table_catalog is null) or (@table_catalog = '')
	/* set the table qualifier name */
	select @table_catalog = db_name ()
    else
    begin
        if db_name() != @table_catalog
        begin
	     /* 18039, "Table qualifier must be name of current database." */
		goto SelectFKClause
	end
    end
   
    /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name prefixed
    ** by the owner id
    */
    if (@table_schema is null) or (@table_schema = '')
        select @full_table_name = @table_name
    else
    begin
	if (@table_name like "%.%") and
	    substring (@table_name, 1, charindex(".", @table_name) -1) != @table_schema
	begin
	 	/* 18011, Object name must be qualified with the owner name */
		raiserror 18011
		return (1)
	end
	
	if not (@table_name like "%.%")
        	select @full_table_name = @table_schema + '.' + @table_name
	else
	        select @full_table_name = @table_name
    end

    /* 
    ** check to see if the specified table exists or not
    */

    select @tab_id = object_id(@full_table_name)
    if (@tab_id is null)
    begin
	/* 17492, "The table or view named doesn't exist in the current database." */
		goto SelectFKClause
    end


    /*
    ** check to see if the @tab_id indeeed represents a table or a view
    */

    if not exists (select * 
                  from   sysobjects
                  where (@tab_id = id) and
	                ((type = 'U') or
                        (type = 'S') or
		        (type = 'V')))
    begin
	/* 17492, "The table or view named doesn't exist in the current database." */
		goto SelectFKClause
    end

   /* 
   ** compute the table owner id
   */

    select @owner_id = uid
    from   sysobjects
    where  id = @tab_id



   /*
   ** get table owner name
   */

    select @table_schema = name 
    from sysusers 
    where uid = @owner_id

    /* Now, create a temporary table to hold a list of all the possible
       tables that we could get with the trio of table name, table owner and
       table catalog. Then, populate that table. */

    create table #odbc_tprivs
        (tab_id         int primary key,
         tab_name       varchar (255),
         tab_owner      varchar (32) null,
         uid            int,
         type           varchar (10))

    insert #odbc_tprivs 
        SELECT id, name, user_name(uid), uid, type 
        FROM sysobjects s 
        WHERE name LIKE @table_name ESCAPE '\'
            AND user_name (uid) LIKE @table_schema ESCAPE '\'
            AND charindex(substring(type,1,1), 'SUV') != 0

    declare tablepriv_cursor cursor for
        select tab_name, tab_owner, tab_id from #odbc_tprivs

    open tablepriv_cursor
   
    fetch tablepriv_cursor into @tab_name, @tab_owner, @table_id
 
    while (@@sqlstatus != 2)
    begin

        exec sp_oledb_computeprivs @tab_name, @tab_owner, @table_catalog, 
			     NULL, 0, @table_id
        fetch tablepriv_cursor into @tab_name, @tab_owner, @table_id

    end

    close tablepriv_cursor
    drop table #odbc_tprivs
      /* Output the results table */
    update #results_table set IS_GRANTABLE = '0' where IS_GRANTABLE="NO"
    update #results_table set IS_GRANTABLE = '1' where IS_GRANTABLE="YES"

SelectFKClause: 
    select GRANTOR, GRANTEE, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME , 
    PRIVILEGE_TYPE = case when r.PRIVILEGE_TYPE = 'REFERENCE' then "REFERENCES"
      		        else r.PRIVILEGE_TYPE end,  
    IS_GRANTABLE=convert(bit, IS_GRANTABLE) from  #results_table r
	 order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PRIVILEGE_TYPE
	 
 set nocount off 	
 drop table #results_table
 drop table #odbc_tprivs
if (@startedInTransaction = 1)
    rollback transaction oledb_keep_temptable_tx   

return (0)

go
exec sp_procxmode 'sp_oledb_gettableprivileges', 'anymode'
go
grant execute on sp_oledb_gettableprivileges to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go





if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_tables')
begin
	drop procedure sp_oledb_tables
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	10.0	1.1	06/16/93	sproc/tables */

/*
** Messages for "sp_oledb_tables"         18039
**
** 17676, "This may be a temporary object. Please execute procedure from tempdb."
**
** 18039, "Table qualifier must be name of current database"
**
*/
create procedure sp_oledb_tables
@table_catalog	 	varchar(32)  = null,
@table_schema     	varchar(32)  = null,
@table_name		varchar(771)  = null,
@table_type		varchar(100) = null
as

declare @type1 varchar(3)
declare @tableindex int
declare @startedInTransaction bit
if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0

if @@trancount = 0
begin
	set chained off
end


set transaction isolation level 1

if (@startedInTransaction = 1)
   save transaction oledb_keep_temptable_tx 


/* temp table */
if (@table_name like "#%" and
   db_name() != db_name(tempdb_id()))
begin
	/*
        ** Can return data about temp. tables only in tempdb
        */
		raiserror 17676
	return(1)
end

create table #oledb_results_table
	 (
	  
	  TABLE_CATALOG		varchar (32) null,
	  TABLE_SCHEMA		varchar (32) null,
	  TABLE_NAME		varchar (255) null,
	  TABLE_TYPE		varchar (32) null,
	  TABLE_GUID		varchar	(32) null,
	  DESCRIPTION		varchar(255) null,
	  TABLE_PROPID		int null,
	  DATE_CREATED		datetime null,
	  DATE_MODIFIED		datetime null
	 )

/*
** Special feature #1:	enumerate databases when owner and name
** are blank but qualifier is explicitly '%'.  
*/
if @table_catalog = '%' and
	@table_schema = '' and
	@table_name = ''
begin	

	/*
	** If enumerating databases 
	*/
	insert #oledb_results_table
	select
		TABLE_CATALOG = name,
		TABLE_SCHEMA = null,
		TABLE_NAME = null,
		TABLE_TYPE = 'Database',
		TABLE_GUID = convert(varchar(32), null),
		DESCRIPTION = convert(varchar(255), null),
		TABLE_PROPID = convert(int, null),
		DATE_CREATED = convert(datetime, null),
	  	DATE_MODIFIED = convert(datetime, null)

		
		from master..sysdatabases

		/*
		** eliminate MODEL database 
		*/
		where name != 'model'
		order by TABLE_CATALOG
end

/*
** Special feature #2:	enumerate owners when qualifier and name
** are blank but owner is explicitly '%'.
*/
else if @table_catalog = '' and
	@table_schema = '%' and
	@table_name = ''
	begin	

		/*
		** If enumerating owners 
		*/
		insert #oledb_results_table
		select distinct
			TABLE_CATALOG = null,
			TABLE_SCHEMA = user_name(uid),
			TABLE_NAME = null,
			TABLE_TYPE = 'Owner',
			TABLE_GUID = convert(varchar(32), null),
			DESCRIPTION = convert(varchar(255), null),
			TABLE_PROPID = convert(int, null),
			DATE_CREATED = convert(datetime, null),
			DATE_MODIFIED = convert(datetime, null)


		

		from sysobjects
		order by TABLE_SCHEMA
	end
	else
	begin 

		/*
		** end of special features -- do normal processing 
		*/
		if @table_catalog is not null
	
begin
			if db_name() != @table_catalog
			begin
				if @table_catalog = ''
				begin  	

					/*
					** If empty qualifier supplied
					** Force an empty result set 
					*/
					select @table_name = ''
					select @table_schema = ''
				end
				else
				begin

					/*
					** If qualifier doesn't match current 
					** database. 
					*/
					raiserror 18039
					return 1
				end
			end
		end
		if @table_type is null
	
begin	

			/*
			** Select all oledb supported table types 
			*/
			select @type1 = 'SUV'
		end
		else
		begin
			/*
			** TableType are case sensitive if CS server 
			*/
			select @type1 = null

		
/*
			** Add System Tables 
			*/
			if (patindex("%SYSTEM TABLE%",@table_type) != 0)
				select @type1 =  'S'

			/*
			** Add User Tables 
			*/
			if (patindex("%TABLE%",@table_type) != 0)
				select @type1 = @type1 + 'U'

			/*
			** Add Views 
			*/
			if (patindex("%VIEW%",@table_type) != 0)
				select @type1 = @type1 + 'V'
		end
		if @table_name is null
	
begin	

			/*
			** If table name not supplied, match all 
			*/
			select @table_name = '%'
		end
		else
		begin
			if (@table_schema is null) and 
			   (charindex('%', @table_name) = 0)
			begin	

			/*
			** If owner not specified and table is specified 
			*/
				if exists (select * from sysobjects
					where uid = user_id()
					and id = object_id(@table_name)
					and (type = 'U' or type = 'V' 
						or type = 'S'))
				begin	

				/*
				** Override supplied owner w/owner of table 
				*/
					select @table_schema = user_name()
				end
			end
		end

		/*
		** If no owner supplied, force wildcard 
		*/
		if @table_schema is null 
		 select @table_schema = '%'
		insert #oledb_results_table
		select
			TABLE_CATALOG = db_name(),
			TABLE_SCHEMA = user_name(o.uid),
			TABLE_NAME = o.name,
			TABLE_TYPE = rtrim ( 
					substring('SYSTEM TABLE            TABLE       VIEW       ',
					/*
					** 'S'=0,'U'=2,'V'=3 
					*/
					(ascii(o.type)-83)*12+1,12)),

			
			TABLE_GUID  = convert(varchar(32), null),
			DESCRIPTION = convert(varchar(255),null),
			TABLE_PROPID = convert(int,null),
			DATE_CREATED = convert(datetime, null),
			DATE_MODIFIED = convert(datetime, null)

		from sysusers u, sysobjects o
		where
			/* Special case for temp. tables.  Match ids */
			(o.name like @table_name or o.id=object_id(@table_name))
			and user_name(o.uid) like @table_schema

			/*
			** Only desired types
			*/
			and charindex(substring(o.type,1,1),@type1)! = 0 

			/*
			** constrain sysusers uid for use in subquery 
			*/
			and u.uid = user_id() 
		and (
                suser_id() = 1          /* User is the System Administrator */
                or o.uid = user_id()    /* User created the object */
                                        /* here's the magic..select the highest
                                        ** precedence of permissions in the
                                        ** order (user,group,public)
                                        */
 
                /*
                ** The value of protecttype is
                **
                **      0  for grant with grant
                **      1  for grant and,
                **      2  for revoke
                **
                ** As protecttype is of type tinyint, protecttype/2 is
                ** integer division and will yield 0 for both types of
                ** grants and will yield 1 for revoke, i.e., when
                ** the value of protecttype is 2.  The XOR (^) operation
                ** will reverse the bits and thus (protecttype/2)^1 will
                ** yield a value of 1 for grants and will yield a
                ** value of zero for revoke.
                **
	        ** For groups, uid = gid. We shall use this to our advantage.
                **
                ** If there are several entries in the sysprotects table
                ** with the same Object ID, then the following expression
                ** will prefer an individual uid entry over a group entry
                **
                ** For example, let us say there are two users u1 and u2
                ** with uids 4 and 5 respectiveley and both u1 and u2
                ** belong to a group g12 whose uid is 16390.  table t1
                ** is owned by user u0 and user u0 performs the following
                ** actions:
                **
                **      grant select on t1 to g12
                **      revoke select on t1 from u1
                **
                ** There will be two entries in sysprotects for the object t1,
                ** one for the group g12 where protecttype = grant (1) and
                ** one for u1 where protecttype = revoke (2).
                **
                ** For the group g12, the following expression will
                ** evaluate to:
                **
                **      ((abs(16390-16390)*2) + ((1/2)^1)
                **      = ((0) + (0)^1) = 0 + 1 = 1
                **
                ** For the user entry u1, it will evaluate to:
                **
                **      (((+)*abs(4-16390)*2) + ((2/2)^1))
                **      = (abs(-16386)*2 + (1)^1)
                **      = 16386*2 + 0 = 32772
                **
                ** As the expression evaluates to a bigger number for the
                ** user entry u1, select max() will chose 32772 which,
                ** ANDed with 1 gives 0, i.e., sp_oledb_tables will not display
                ** this particular table to the user.
                **
                ** When the user u2 invokes sp_oledb_tables, there is only one
                ** entry for u2, which is the entry for the group g12, and
                ** so the group entry will be selected thus allowing the
                ** table t1 to be displayed.
                **
		** ((select max((abs(uid-u.gid)*2)
	        ** 		+ ((protecttype/2)^1))
         	**
                ** Notice that multiplying by 2 makes the number an
                ** even number (meaning the last digit is 0) so what
                ** matters at the end is (protecttype/2)^1.
                **
                **/
 
                or ((select max((abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
                        from sysprotects p, sysusers u2
                        where p.id = o.id      /* outer join to correlate
                                                ** with all rows in sysobjects
                                                */
			and u2.uid = user_id()
			/*
			** get rows for public, current users, user's groups
			*/
		      	and (p.uid = 0 or 		/* public */
			     p.uid = user_id() or	/* current user */ 
			     p.uid = u2.gid)		/* users group */ 

			/*
			** check for SELECT, EXECUTE privilege.
			*/
		 	and (p.action in (193,224)))&1

			/*
			** more magic...normalise GRANT
			** and final magic...compare
			** Grants.
			*/
			) = 1
		/*
			** If one of any user defined roles or contained roles for the
			** user has permission, the user has the permission
			*/
			or exists(select 1
				from sysprotects p1,
					master.dbo.syssrvroles srvro,
					sysroles ro
				where p1.id = o.id
				and p1.uid = ro.lrid
				and ro.id = srvro.srid
		and has_role(srvro.name, 1) > 0
				and p1.action = 193))
		
		order by TABLE_TYPE, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
end
if (patindex("%VIEW%",@table_type) != 0)
	select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, null, null, null, 
	DESCRIPTION, DATE_CREATED, DATE_MODIFIED from #oledb_results_table
else
	select * from #oledb_results_table
drop table #oledb_results_table
if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx

return (0)
go
exec sp_procxmode 'sp_oledb_tables', 'anymode'
go
grant execute on sp_oledb_tables to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_statistics')
begin
	drop procedure sp_oledb_statistics
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
/*	10.0	1.1	06/16/93	sproc/tables */

/*
** Messages for "sp_oledb_statistics"         18039
**
** 17676, "This may be a temporary object. Please execute procedure from tempdb."
**
** 18039, "Table qualifier must be name of current database"
**
*/
create procedure sp_oledb_statistics
@table_catalog	 	varchar(32)  = null,
@table_schema     	varchar(32)  = null,
@table_name		varchar(255)  = null

as

declare @type1 varchar(3)
declare @tname varchar(255)
declare @startedInTransaction bit

if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

if (@startedInTransaction = 1)
 save transaction oledb_keep_temptable_tx

/* temp table */
if (@table_name like "#%" and
   db_name() != db_name(tempdb_id()))
begin
	/*
        ** Can return data about temp. tables only in tempdb
        */
		raiserror 17676
	return(1)
end

create table #oledb_results_table
	 (
	  
	  TABLE_CATALOG		varchar (32) null,
	  TABLE_SCHEMA		varchar (32) null,
	  TABLE_NAME		varchar (255) null,
	  CARDINALITY		int null
	 )
	  		 	
		 		
     				
/*
** Special feature #1:	enumerate databases when owner and name
** are blank but catalog is explicitly '%'.  
*/
if @table_catalog = '%' and
	@table_schema = '' and
	@table_name = ''
begin	

	/*
	** If enumerating databases 
	*/
	insert #oledb_results_table
	select
		TABLE_CATALOG = name,
		TABLE_SCHEMA = null,
		TABLE_NAME = null,
		CARDINALITY = null
		from master..sysdatabases

		/*
		** eliminate MODEL database 
		*/
		where name != 'model'
		order by TABLE_CATALOG
end

/*
** Special feature #2:	enumerate owners when qualifier and name
** are blank but owner is explicitly '%'.
*/
else if @table_catalog = '' and
	@table_schema = '%' and
	@table_name = ''
	begin	

		/*
		** If enumerating owners 
		*/
		insert #oledb_results_table
		select distinct
			TABLE_CATALOG = null,
			TABLE_SCHEMA = user_name(uid),
			TABLE_NAME = null,
			CARDINALITY = null
		from sysobjects
		order by TABLE_CATALOG
	end
	else
	begin 

		/*
		** end of special features -- do normal processing 
		*/
		if @table_catalog is not null
	
		begin
			if db_name() != @table_catalog
			begin
				if @table_catalog = ''
				begin  	

					/*
					** If empty qualifier supplied
					** Force an empty result set by 
					** going directly to select
					*/
					goto SelectClause
				end
			end
		end
		
		select @type1 = 'SUV'
	
		
		if @table_name is null
	
		begin	

			/*
			** If table name not supplied, match all 
			*/
			select @table_name = '%'
		end
		else
		begin
			if (@table_schema is null) and 
			   (charindex('%', @table_name) = 0)
			begin	

			/*
			** If owner not specified and table is specified 
			*/
				if exists (select * from sysobjects
					where uid = user_id()
					and id = object_id(@table_name)
					and (type = 'U' or type = 'V' 
						or type = 'S'))
				begin	

				/*
				** Override supplied owner w/owner of table 
				*/
					select @table_schema = user_name()
				end
			end
		end

		/*
		** If no owner supplied, force wildcard 
		*/
		if @table_schema is null 
		 select @table_schema = '%'
		/*
		** If no catalog supplied, force wildcard 
		*/
		if @table_catalog is null 
		 select @table_catalog = '%'
		 
		
		insert #oledb_results_table
		select
			TABLE_CATALOG = db_name(),
			TABLE_SCHEMA = user_name(o.uid),
			TABLE_NAME = o.name,
--		CARDINALITY = rowcnt(x.doampg)
 		CARDINALITY = row_count(db_id(), x.id)

			from sysusers u, sysobjects o, sysindexes x
		where
			/* Special case for temp. tables.  Match ids */
			(o.name like @table_name or o.id=object_id(@table_name))
			and user_name(o.uid) like @table_schema

			/*
			** Only desired types
			*/
			and charindex(substring(o.type,1,1),@type1)! = 0 
			and o.name = x.name

			/*
			** constrain sysusers uid for use in subquery 
			*/
			and u.uid = user_id() 
		and (
                suser_id() = 1          /* User is the System Administrator */
                or o.uid = user_id()    /* User created the object */
                                        /* here's the magic..select the highest
                                        ** precedence of permissions in the
                                        ** order (user,group,public)
                                        */
 
                /*
                ** The value of protecttype is
                **
                **      0  for grant with grant
                **      1  for grant and,
                **      2  for revoke
                **
                ** As protecttype is of type tinyint, protecttype/2 is
                ** integer division and will yield 0 for both types of
                ** grants and will yield 1 for revoke, i.e., when
                ** the value of protecttype is 2.  The XOR (^) operation
                ** will reverse the bits and thus (protecttype/2)^1 will
                ** yield a value of 1 for grants and will yield a
                ** value of zero for revoke.
                **
	        ** For groups, uid = gid. We shall use this to our advantage.
                **
                ** If there are several entries in the sysprotects table
                ** with the same Object ID, then the following expression
                ** will prefer an individual uid entry over a group entry
                **
                ** For example, let us say there are two users u1 and u2
                ** with uids 4 and 5 respectiveley and both u1 and u2
                ** belong to a group g12 whose uid is 16390.  table t1
                ** is owned by user u0 and user u0 performs the following
                ** actions:
                **
                **      grant select on t1 to g12
                **      revoke select on t1 from u1
                **
                ** There will be two entries in sysprotects for the object t1,
                ** one for the group g12 where protecttype = grant (1) and
                ** one for u1 where protecttype = revoke (2).
                **
                ** For the group g12, the following expression will
                ** evaluate to:
                **
                **      ((abs(16390-16390)*2) + ((1/2)^1)
                **      = ((0) + (0)^1) = 0 + 1 = 1
                **
                ** For the user entry u1, it will evaluate to:
                **
                **      (((+)*abs(4-16390)*2) + ((2/2)^1))
                **      = (abs(-16386)*2 + (1)^1)
                **      = 16386*2 + 0 = 32772
                **
                ** As the expression evaluates to a bigger number for the
                ** user entry u1, select max() will chose 32772 which,
                ** ANDed with 1 gives 0, i.e., sp_oledb_statistics will not display
                ** this particular table to the user.
                **
                ** When the user u2 invokes sp_oledb_statistics, there is only one
                ** entry for u2, which is the entry for the group g12, and
                ** so the group entry will be selected thus allowing the
                ** table t1 to be displayed.
                **
		** ((select max((abs(uid-u.gid)*2)
	        ** 		+ ((protecttype/2)^1))
         	**
                ** Notice that multiplying by 2 makes the number an
                ** even number (meaning the last digit is 0) so what
                ** matters at the end is (protecttype/2)^1.
                **
                **/
 
                or ((select max((abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
                        from sysprotects p, sysusers u2
                        where p.id = o.id      /* outer join to correlate
                                                ** with all rows in sysobjects
                                                */
			and u2.uid = user_id()
			/*
			** get rows for public, current users, user's groups
			*/
		      	and (p.uid = 0 or 		/* public */
			     p.uid = user_id() or	/* current user */ 
			     p.uid = u2.gid)		/* users group */ 

			/*
			** check for SELECT, EXECUTE privilege.
			*/
		 	and (p.action in (193,224)))&1

			/*
			** more magic...normalise GRANT
			** and final magic...compare
			** Grants.
			*/
			) = 1)
		order by  TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
		
end

SelectClause:       
select * from #oledb_results_table where TABLE_CATALOG like @table_catalog 
AND TABLE_SCHEMA like @table_schema
AND TABLE_NAME like @table_name order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME

drop table #oledb_results_table
if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx 

return (0)
go
exec sp_procxmode 'sp_oledb_statistics', 'anymode'
go
grant execute on sp_oledb_statistics to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_stored_procedures')
begin
	drop procedure sp_oledb_stored_procedures
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_oledb_stored_procedures"	18041
**
** 18041, "Stored Procedure qualifier must be name of current database."
**
*/
create procedure sp_oledb_stored_procedures
@sp_name	varchar(771) = null,	/* stored procedure name */
@sp_owner	varchar(32) = null,	/* stored procedure owner */
@sp_qualifier	varchar(32) = null,	/* stored procedure qualifier; 
					** For the SQL Server, the only valid
					** values are NULL or the current 
					** database name
					*/
@type varchar(2)= null,		/* used for ado.net2 and do nothing here */		
@is_ado    int = 1
	
					
as


if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

/* If qualifier is specified */
if @sp_qualifier is not null
begin
	/* If qualifier doesn't match current database */
	if db_name() != @sp_qualifier
	begin
		/* If qualifier is not specified */
		if @sp_qualifier = ''
		begin
			/* in this case, we need to return an empty 
			** result set because the user has requested a 
			** database with an empty name 
			*/
			select @sp_name = ''
			select @sp_owner = ''
		end

		/* qualifier is specified and does not match current database */
		else
		begin	
			/* 
			** 18041, "Stored Procedure qualifer must be name of
			** current database"
			*/
			raiserror 18041
			return (1)
		end
	end
end

/* If procedure name not supplied, match all */
if @sp_name is null
begin  
	select @sp_name = '%'
end
else 
begin
	/* If owner name is not supplied, but procedure name is */ 
	if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
	begin
		/* If procedure exists and is owned by the current user */
		if exists (select * 
			   from sysobjects
			   where uid = user_id()
				and name = @sp_name
				and type = 'P') /* Object type of Procedure */
		begin
			/* Set owner name to current user */
			select @sp_owner = user_name()
		end
	end
end

/* If procedure owner not supplied, match all */
if @sp_owner is null	
	select @sp_owner = '%'

/* 
** Retrieve the stored procedures and associated info on them
*/
select  PROCEDURE_CATALOG = db_name(),
	PROCEDURE_SCHEMA = user_name(o.uid),
	PROCEDURE_NAME = o.name +';'+ ltrim(str(p.number,5)),
	PROCEDURE_TYPE = case when o.type='P' then convert(smallint, 1) when o.type='F' then convert(smallint, 2) end,
	PROCEDURE_DEFINITION= convert(varchar(254),null),
	DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
	DATE_CREATED = case when @is_ado = 2 then convert(datetime, o.crdate) when @is_ado = 1 then convert(datetime, null) end,
	DATE_MODIFIED = case when @is_ado = 2 then convert(datetime,o.expdate) when @is_ado = 1 then convert(datetime, null) end
from sysobjects o,sysprocedures p,sysusers u
where o.name like @sp_name
	and p.sequence = 0
	and user_name(o.uid) like @sp_owner
	and o.type in ('P','F')  /* Object type of Procedure or Function */
	and p.id = o.id
	and u.uid = user_id()		/* constrain sysusers uid for use in 
					** subquery 
					*/

	and (suser_id() = 1 		/* User is the System Administrator */
	     or  o.uid = user_id()	/* User created the object */
					/* here's the magic..select the highest 
					** precedence of permissions in the 
					** order (user,group,public)  
					*/

	     /*
	     ** The value of protecttype is
	     **
	     **		0  for grant with grant
	     **		1  for grant and,
	     **		2  for revoke
	     **
	     ** As protecttype is of type tinyint, protecttype/2 is
	     ** integer division and will yield 0 for both types of
	     ** grants and will yield 1 for revoke, i.e., when
	     ** the value of protecttype is 2.  The XOR (^) operation
	     ** will reverse the bits and thus (protecttype/2)^1 will
	     ** yield a value of 1 for grants and will yield a
	     ** value of zero for revoke.
	     **
	     ** For groups, uid = gid. We shall use this to our advantage.
             ** 	
	     ** If there are several entries in the sysprotects table
	     ** with the same Object ID, then the following expression
	     ** will prefer an individual uid entry over a group entry
	     **
	     ** For example, let us say there are two users u1 and u2
	     ** with uids 4 and 5 respectiveley and both u1 and u2
	     ** belong to a group g12 whose uid is 16390.  procedure p1
	     ** is owned by user u0 and user u0 performs the following
	     ** actions:
	     **
	     **		grant exec on p1 to g12
	     **		revoke grant on p1 from u1
	     **
	     ** There will be two entries in sysprotects for the object
	     ** p1, one for the group g12 where protecttype = grant (1)
	     ** and one for u1 where protecttype = revoke (2).
	     **
	     ** For the group g12, the following expression will
	     ** evaluate to:
	     **
	     **		((abs(16390-16390)*2) + ((1/2)^1))
	     **		= ((0) + (0)^1) = 0 + 1 = 1
	     **
	     ** For the user entry u1, it will evaluate to:
	     **
	     **		((abs(4-16390)*2) + ((2/2)^1))
	     **		= ((abs(-16386)*2 + (1)^1)
	     **		= 16386*2 + 0 = 32772 
	     **
	     ** As the expression evaluates to a bigger number for the
	     ** user entry u1, select max() will chose 32772 which,
	     ** ANDed with 1 gives 0, i.e., sp_oledb_stored_procedures will
	     ** not display this particular procedure to the user.
	     **
	     ** When the user u2 invokes sp_oledb_stored_procedures, there is
	     ** only one entry for u2, which is the entry for the group
	     ** g12, and so this entry will be selected thus allowing
	     ** the procedure in question to be displayed.
	     **
             ** NOTE: With the extension of the uid's into negative space, 
             ** and uid limits going beyond 64K, the original expression 
	     ** has been modified from
	     ** ((select max(((sign(uid)*abs(uid-16383))*2)
	     **		+ ((protecttype/2)^1))
	     ** to
	     ** ((select max((abs(uid-u.gid)*2)
	     **		+ ((protecttype/2)^1))
	     ** 
	     ** Notice that multiplying by 2 makes the number an
	     ** even number (meaning the last digit is 0) so what
	     ** matters at the end is (protecttype/2)^1.
	     **
	     */

	     or ((select max( (abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
		   from sysprotects p, sysusers u2
		   where p.id = o.id
		   and u2.uid = user_id()
		   /*
		   ** get rows for public, current users, user's groups
		   */
		   and (p.uid = 0  		/* get rows for public */
		        or p.uid = user_id()	/* current user */
		        or p.uid = u2.gid) 	/* users group */
			     
		   /*
		   ** check for SELECT, EXECUTE privilege.
		   */
	           and (p.action in (193,224))	/* check for SELECT,EXECUTE 
						** privilege 
						*/
		   )&1 			/* more magic...normalize GRANT */
	    	  ) = 1	 		/* final magic...compare Grants	*/
	     /*
	     ** If one of any user defined roles or contained roles for the
	     ** user has permission, the user has the permission
	     */
	     or exists(select 1
		from	sysprotects p1,
			master.dbo.syssrvroles srvro,
			sysroles ro
		where	p1.id = o.id
			and p1.uid = ro.lrid
			and ro.id = srvro.srid
	and has_role(srvro.name, 1) > 0		
			and p1.action = 224))
			
order by PROCEDURE_CATALOG, PROCEDURE_SCHEMA, PROCEDURE_NAME
go
exec sp_procxmode 'sp_oledb_stored_procedures', 'anymode'
go
grant execute on sp_oledb_stored_procedures to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go







if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_getprocedurecolumns')
begin
	drop procedure sp_oledb_getprocedurecolumns
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_oledb_getprocedurecolumns"
**
** 18039, "Table qualifier must be name of current database"
*/

create procedure sp_oledb_getprocedurecolumns
@procedure_name		varchar(771) = '%', 	/* name of stored procedure  */
@procedure_schema	varchar(32) = null,	/* owner of stored procedure */
@procedure_catalog	varchar(32) = null,	/* name of current database  */
@parameter_name		varchar(771) = null,	/* col name or param name    */
@is_ado             int = 1
as

declare @msg 		  varchar(255)
declare @group_num		int
declare @semi_position		int
declare @full_procedure_name	varchar(1543)
declare @procedure_id		int
declare @char_bin_types   varchar(30) 
declare @sptlang 			int
declare @startedInTransaction bit
if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1

if (@startedInTransaction = 1)
 save transaction oledb_keep_temptable_tx
 
select @sptlang = @@langid

 if @@langid != 0
 begin
         if not exists (
                 select * from master.dbo.sysmessages where error
                 between 17100 and 17109
                 and langid = @@langid)
             select @sptlang = 0
 end
 
create table #oledb_results_table
(
  	PROCEDURE_CATALOG  varchar (32) null,
  	PROCEDURE_SCHEMA  varchar (32) null,
  	PROCEDURE_NAME  varchar (255) null,
  	PARAMETER_NAME  varchar (255) null,
  	ORDINAL_POSITION	smallint null,
  	PARAMETER_TYPE 		smallint null,
  	PARAMETER_HASDEFAULT	bit ,
  	PARAMETER_DEFAULT	varchar (255) null,
  	IS_NULLABLE		bit ,
  	DATA_TYPE		smallint null,
  	CHARACTER_MAXIMUM_LENGTH	int null,
  	CHARACTER_OCTET_LENGTH		int null,
  	NUMERIC_PRECISION		smallint null,
  	NUMERIC_PRECISION_RADIX  smallint null,
  	NUMERIC_SCALE			smallint null,
  	DESCRIPTION		varchar(255) null,
  	TYPE_NAME		varchar (32) null,
  	LOCAL_TYPE_NAME		varchar (32) null,
  	
)

/* If column name not supplied, match all */
if @parameter_name is null 
	select @parameter_name = '%'

/* The qualifier must be the name of current database or null */
if @procedure_catalog is not null
begin
	if db_name() != @procedure_catalog
	begin
	if @procedure_catalog = ''
		begin
			/* in this case, we need to return an empty result 
			** set because the user has requested a database with
			** an empty name
			*/
			select @procedure_name = ''
			select @procedure_schema= ''
		end
		else
		begin
			/*
			** 18039, Table qualifier must be name of current database
			*/
			exec sp_getmessage 18039, @msg output
			print @msg
			return
		end
	end
end


/* first we need to extract the procedure group number, if one exists */
select @semi_position = charindex(';',@procedure_name)
if (@semi_position > 0)
begin	/* If group number separator (;) found */
	select @group_num = convert(int,substring(@procedure_name, 
						  @semi_position + 1, 2))
	select @procedure_name = substring(@procedure_name, 1, 
					   @semi_position -1)
end
else
begin	/* No group separator, so default to group number of 1 */
	select @group_num = 1
end

/* character and binary datatypes */
select @char_bin_types =
	char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

if @procedure_schema is null
begin	/* If unqualified procedure name */
	select @full_procedure_name = @procedure_name
end
else
begin	/* Qualified procedure name */
	select @full_procedure_name = @procedure_schema+ '.' + @procedure_name
end

/*
** If the @parameter_name parameter is "RETURN_VALUE" and this is a sqlj
** function, then we should be looking for column name "Return Type"
*/
if @parameter_name = "RETURN_VALUE"
	and exists (select 1 from sysobjects
		    where id = object_id(@full_procedure_name)
		    and type = 'F')
begin	
	select @parameter_name = "Return Type"
end

/*	Get Object ID */
select @procedure_id = object_id(@full_procedure_name)

if ((charindex('%',@full_procedure_name) = 0) and
	(charindex('_',@full_procedure_name) = 0)  and
	@procedure_id != 0)
begin
/*
** this block is for the case where there is no pattern
** matching required for the procedure name
*/
	insert #oledb_results_table
	select	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		PROCEDURE_CATALOG = db_name(),
		PROCEDURE_SCHEMA = user_name(o.uid),
		PROCEDURE_NAME = o.name,
                PARAMETER_NAME =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                ORDINAL_POSITION = convert(int,c.colid),
                PARAMETER_TYPE =
		case
			when c.name = 'Return Type'			
				then convert(smallint, 4) /*DBPARAMTYPE_RETURNVALUE*/
		when c.status2 = 1
			then convert(smallint, 1) /*DBPARAMTYPE_INPUT*/
		when c.status2 = 2
			then convert(smallint, 3) /*DBPARAMTYPE_OUTPUT*/
		when c.status2 = 4			     		
			then  convert(smallint, 2) /*DBPARAMTYPE_INPUTOUTPUT*/
		else null
		end,
		PARAMETER_HASDEFAULT = convert(bit,0),
		PARAMETER_DEFAULT = convert(varchar(255),null),
		IS_NULLABLE =	/* set nullability from status flag */
			convert(smallint, 1),

		DATA_TYPE = 0,
					   
		CHARACTER_MAXIMUM_LENGTH = isnull(convert(int, c.prec),
					isnull(d.data_precision, convert(int,c.length)))
					     +isnull(d.aux, convert(int,
							     ascii(substring("???AAAFFFCKFOLS",
								          2*(d.ss_dtype%35+1)
									  +2-8/c.length,1))
							  -60)),
		CHARACTER_OCTET_LENGTH = 
				/*
				** check if in the list
				** if so, return a 1 and multiply it by the precision
				** if not, return a 0 and multiply it by the precision
				*/
				convert(smallint,
				    substring('0111111',
					charindex(char(c.type),
					@char_bin_types)+1, 1)) *
				/* calculate the precision */
				isnull(convert(int, c.prec),
				    isnull(convert(int, d.data_precision),
					convert(int, c.length)))
				    +isnull(d.aux, convert(int,
					ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		
		NUMERIC_PRECISION = d.data_precision,
		NUMERIC_PRECISION_RADIX = d.numeric_radix,
		NUMERIC_SCALE = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale)) +
			convert(smallint, 
				isnull(d.aux, ascii(substring("<<<<<<<<<<<<<<?",
					        2*(d.ss_dtype%35+1)
						+2-8/c.length,
					        1))-60)),
				
		DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
		TYPE_NAME = rtrim(substring(d.type_name,
							1+isnull(d.aux,
							     ascii(substring("III<<<MMMI<<A<A",
									2*(d.ss_dtype%35+1)
									+2-8/c.length,
						        1)) - 60), 18)),
		LOCAL_TYPE_NAME = rtrim(substring(d.type_name,
									1+isnull(d.aux,
									     ascii(substring("III<<<MMMI<<A<A",
											2*(d.ss_dtype%35+1)
											+2-8/c.length,
						        1)) - 60), 18))
		
		
		
		
		
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sysprocedures p
		
	where
		o.id = @procedure_id
		and c.id = o.id
		and c.type = d.ss_dtype
		and c.name like @parameter_name
		and d.ss_dtype in (111, 109, 38, 110)	/* Just *N types */
		and c.number = @group_num
		
	union
	select
		PROCEDURE_CATALOG = db_name(),
		PROCEDURE_SCHEMA = user_name(o.uid),
		PROCEDURE_NAME = o.name,
		PARAMETER_NAME = 'RETURN_VALUE',
		ORDINAL_POSITION = convert(tinyint, 0),
		PARAMETER_TYPE = convert(smallint, 4), /* return parameter */
		PARAMETER_HASDEFAULT = convert(bit,0),
		PARAMETER_DEFAULT = convert(varchar(255),null),
		IS_NULLABLE = convert(smallint, 1),
		DATA_TYPE =  0,
		CHARACTER_MAXIMUM_LENGTH = isnull(d.data_precision, convert(int,d.length))
					     +isnull(d.aux, convert(int,
							     ascii(substring("???AAAFFFCKFOLS",
								          2*(d.ss_dtype%35+1)
									  +2-8/d.length,1))
							  -60)),
		CHARACTER_OCTET_LENGTH = NULL,
		NUMERIC_PRECISION = d.data_precision,
		NUMERIC_PRECISION_RADIX = d.numeric_radix,
		NUMERIC_SCALE = d.numeric_scale +convert(smallint,
					   isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
						        2*(d.ss_dtype%35+1)
							+2-8/d.length,
						        1))-60)),
				
		DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
		TYPE_NAME = d.type_name,
		LOCAL_TYPE_NAME = d.type_name
		
             
               
               
                
                
	from
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
		
	where
		o.id = @procedure_id
		and d.ss_dtype = 56  /* int for return code */
		and t.type = 56
		and o.type = 'P'
		and (@parameter_name = '%' or @parameter_name = 'RETURN_VALUE')
		
	union
	select		   /* All other types including user data types */
		PROCEDURE_CATALOG = db_name(),
		PROCEDURE_SCHEMA = user_name(o.uid),
		PROCEDURE_NAME = o.name,
		PARAMETER_NAME = 	
			case	
		 	    when c.name = 'Return Type' then 'RETURN_VALUE'
			    else c.name
			end,
		ORDINAL_POSITION = convert(int,c.colid),
		PARAMETER_TYPE = 
		case
			when c.name = 'Return Type'			
				then convert(smallint, 4) /*DBPARAMTYPE_RETURNVALUE*/
		when c.status2 = 1
			then convert(smallint, 1) /*DBPARAMTYPE_INPUT*/
		when c.status2 = 2
			then convert(smallint, 3) /*DBPARAMTYPE_OUTPUT*/
		when c.status2 = 4			     		
			then  convert(smallint, 2) /*DBPARAMTYPE_INPUTOUTPUT*/
		else null
		end,		
		PARAMETER_HASDEFAULT = convert(bit,0),
		PARAMETER_DEFAULT = convert(varchar(255),null),
		IS_NULLABLE = convert(smallint, 1),
		DATA_TYPE = 0,
		CHARACTER_MAXIMUM_LENGTH = 
				case 
					when d.data_precision = 0
					then convert(int,0)
				else		
				isnull(convert(int, c.prec),
					isnull(d.data_precision, convert(int,c.length)))
					     +isnull(d.aux, convert(int,
							     ascii(substring("???AAAFFFCKFOLS",
								       2*(d.ss_dtype%35+1)
								       +2-8/c.length,1))
								       -60))
		end,
		CHARACTER_OCTET_LENGTH = 
				/*
				** check if in the list
				** if so, return a 1 and multiply it by the precision
				** if not, return a 0 and multiply it by the precision
				*/
				convert(smallint,
				    substring('0111111',
					charindex(char(c.type),
					@char_bin_types)+1, 1)) *
				/* calculate the precision */
				isnull(convert(int, c.prec),
				    isnull(convert(int, d.data_precision),
					convert(int, c.length)))
				    +isnull(d.aux, convert(int,
					ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
			
		
		NUMERIC_PRECISION = d.data_precision,
		NUMERIC_PRECISION_RADIX = d.numeric_radix,
		NUMERIC_SCALE = isnull(convert(smallint, c.scale),
			convert(smallint, d.numeric_scale))
			+ convert(smallint,
					  isnull(d.aux,
					    ascii(substring("<<<<<<<<<<<<<<?",
							    2*(d.ss_dtype%35+1)
							    +2-8/c.length,
							    1))-60)),
		
		/* set nullability from status flag */
		
		DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
		TYPE_NAME = 
					case 
					    when t.name = 'extended type' 
						then isnull(get_xtypename(c.xtype, c.xdbid), 
											t.name)
					    when t.type = 58
					    	then "smalldatetime"
					    when t.usertype in (44,45,46)
					    	then "unsigned "+substring(t.name,
					    			charindex("u",t.name) + 1,
					    			charindex("t",t.name))
					    else 
						t.name
			end,
		LOCAL_TYPE_NAME = case when t.name = 'extended type' 
				then isnull(get_xtypename(c.xtype, c.xdbid), t.name)
				when t.type = 58  	then "smalldatetime"
			        when t.usertype in (44,45,46)
				then "unsigned "+substring(t.name,
					charindex("u",t.name) + 1,
					charindex("t",t.name))
				 else t.name
			end
               
               
               
                
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
		
	where
		o.id = @procedure_id
		and c.id = o.id
		and c.type *= d.ss_dtype
		and c.usertype *= t.usertype
		and c.name like @parameter_name
		and c.number = @group_num
		and d.ss_dtype not in (111, 109, 38, 110) /* No *N types */
		

	 order by convert(int,colid)
end
else
begin
	/* 
	** this block is for the case where there IS pattern
	** matching done on the table name
	*/
	if @procedure_schema is null
		select @procedure_schema= '%'
	 insert #oledb_results_table
	select	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		PROCEDURE_CATALOG = db_name(),
		PROCEDURE_SCHEMA = user_name(o.uid),
		PROCEDURE_NAME = o.name,
                PARAMETER_NAME =
                        case
                            when c.name = 'Return Type' then 'RETURN_VALUE'
                            else c.name
                        end,
                ORDINAL_POSITION = convert(int,c.colid),
                PARAMETER_TYPE =
		case
			when c.name = 'Return Type'			
				then convert(smallint, 4) /*DBPARAMTYPE_RETURNVALUE*/
		when c.status2 = 1
			then convert(smallint, 1) /*DBPARAMTYPE_INPUT*/
		when c.status2 = 2
			then convert(smallint, 3) /*DBPARAMTYPE_OUTPUT*/
		when c.status2 = 4			     		
			then  convert(smallint, 2) /*DBPARAMTYPE_INPUTOUTPUT*/
		else null
		end,
		PARAMETER_HASDEFAULT = convert(bit,0),
		PARAMETER_DEFAULT = convert(varchar(255),null),
		IS_NULLABLE = convert(smallint, 1),
		DATA_TYPE = 0,
		CHARACTER_MAXIMUM_LENGTH = isnull(convert(int, c.prec), 
						isnull(d.data_precision, convert(int,c.length)))
					     +isnull(d.aux, convert(int,
							     ascii(substring("???AAAFFFCKFOLS",
								           2*(d.ss_dtype%35+1)
									   +2-8/c.length,1))
						           -60)),
		CHARACTER_OCTET_LENGTH = 
				/*
				** check if in the list
				** if so, return a 1 and multiply it by the precision
				** if not, return a 0 and multiply it by the precision
				*/
				convert(smallint,
				    substring('0111111',
					charindex(char(c.type),
					@char_bin_types)+1, 1)) *
				/* calculate the precision */
				isnull(convert(int, c.prec),
				    isnull(convert(int, d.data_precision),
					convert(int, c.length)))
				    +isnull(d.aux, convert(int,
					ascii(substring('???AAAFFFCKFOLS',
			   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
		
		
		NUMERIC_PRECISION = d.data_precision,
		NUMERIC_PRECISION_RADIX = d.numeric_radix,
		NUMERIC_SCALE = isnull(convert(smallint, c.scale),
				convert(smallint, d.numeric_scale))
				+ convert(smallint,
					    isnull(d.aux,
					     ascii(substring("<<<<<<<<<<<<<<?",
							   2*(d.ss_dtype%35+1)
							   +2-8/c.length,
							   1))-60)),
		
		/* set nullability from status flag */
		
		DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
		TYPE_NAME = rtrim(substring(d.type_name,
						    1+isnull(d.aux,
							     ascii(substring("III<<<MMMI<<A<A",
							                  2*(d.ss_dtype%35+1)
									  +2-8/c.length,
						          1))-60), 18)),
		LOCAL_TYPE_NAME = rtrim(substring(d.type_name,
								    1+isnull(d.aux,
									     ascii(substring("III<<<MMMI<<A<A",
									                  2*(d.ss_dtype%35+1)
											  +2-8/c.length,
						          1))-60), 18))
                
		
               
                
	from
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t
		
	where
		o.name like @procedure_name
		and user_name(o.uid) like @procedure_schema
		and o.id = c.id
		and c.type = d.ss_dtype
		and c.name like @parameter_name
		
		/* Just procs & sqlj procs and funcs */
		and o.type in ('P', 'F')
		and d.ss_dtype in (111, 109, 38, 110)	/* Just *N types */
	union
		select distinct
			PROCEDURE_CATALOG = db_name(),
			PROCEDURE_SCHEMA = user_name(o.uid),
			PROCEDURE_NAME = o.name,
			PARAMETER_NAME = 'RETURN_VALUE',
			ORDINAL_POSITION = convert(tinyint, 0),
			PARAMETER_TYPE = convert(smallint, 4), /* return parameter */
			PARAMETER_HASDEFAULT = convert(bit,0),
			PARAMETER_DEFAULT = convert(varchar(255),null),
			IS_NULLABLE = convert(smallint, 1),
			DATA_TYPE = 0,
			CHARACTER_MAXIMUM_LENGTH = isnull(d.data_precision, convert(int,d.length))
						     +isnull(d.aux, convert(int,
								     ascii(substring("???AAAFFFCKFOLS",
									          2*(d.ss_dtype%35+1)
										  +2-8/d.length,1))
								  -60)),
			CHARACTER_OCTET_LENGTH = NULL,
			
			NUMERIC_PRECISION = d.data_precision,
			NUMERIC_PRECISION_RADIX = d.numeric_radix,
			NUMERIC_SCALE = d.numeric_scale +convert(smallint,
						   isnull(d.aux,
						     ascii(substring("<<<<<<<<<<<<<<?",
							        2*(d.ss_dtype%35+1)
								+2-8/d.length,
							        1))-60)),
			
			
			DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
			TYPE_NAME = d.type_name,
			LOCAL_TYPE_NAME = d.type_name
			
	                     
	                
		from
			sysobjects o,
			sybsystemprocs.dbo.spt_datatype_info d,
			systypes t,
			sysprocedures p
			
		where
			o.name like @procedure_name
			and user_name(o.uid) like @procedure_schema
			and d.ss_dtype = 56  /* int for return code */
			and t.type = 56
			and o.type = 'P'			/* Just Procedures */
			and p.id = o.id
		and 'RETURN_VALUE' like @parameter_name
		union
			select		   /* All other types including user data types */
				PROCEDURE_CATALOG = db_name(),
				PROCEDURE_SCHEMA = user_name(o.uid),
				PROCEDURE_NAME = o.name,
		                PARAMETER_NAME =
				case
					when c.name = 'Return Type' then 'RETURN_VALUE'
					else c.name
				end,
				ORDINAL_POSITION = convert(int,c.colid),
		                PARAMETER_TYPE =
				case
					when c.name = 'Return Type'
						then convert(smallint, 4)
				when c.status2 = 1
					then convert(smallint, 1)
				when c.status2 = 2
					then convert(smallint, 3)
				when c.status2 = 4			     		
					then  convert(smallint, 2)                                        
					else null
				end,
				PARAMETER_HASDEFAULT = convert(bit,0),
				PARAMETER_DEFAULT = convert(varchar(255),null),
				IS_NULLABLE = convert(smallint, 1),
				DATA_TYPE =  0,
				CHARACTER_MAXIMUM_LENGTH = 
						case 
							when d.data_precision = 0
							then convert(int,0)
						else
						isnull(convert(int, c.prec),
							isnull(d.data_precision, convert(int,c.length)))
							     +isnull(d.aux, 
								     convert(int,
									     ascii(substring("???AAAFFFCKFOLS",
									                   2*(d.ss_dtype%35+1)
											   +2-8/c.length,1))
									           -60))
				end,
				CHARACTER_OCTET_LENGTH = 
						/*
						** check if in the list
						** if so, return a 1 and multiply it by the precision
						** if not, return a 0 and multiply it by the precision
						*/
						convert(smallint,
						    substring('0111111',
							charindex(char(c.type),
							@char_bin_types)+1, 1)) *
						/* calculate the precision */
						isnull(convert(int, c.prec),
						    isnull(convert(int, d.data_precision),
							convert(int, c.length)))
						    +isnull(d.aux, convert(int,
							ascii(substring('???AAAFFFCKFOLS',
					   2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
				
						
				NUMERIC_PRECISION = d.data_precision,
				NUMERIC_PRECISION_RADIX = d.numeric_radix,
				NUMERIC_SCALE = isnull(convert(smallint, c.scale),
					convert(smallint, d.numeric_scale))
					+ convert(smallint,
						 isnull(d.aux,
							ascii(substring("<<<<<<<<<<<<<<?",
							                2*(d.ss_dtype%35+1)
									+2-8/c.length,
							                1))-60)),
				
				/* set nullability from status flag */
				
				DESCRIPTION = convert(varchar(254),null),	/* Remarks are NULL */
				TYPE_NAME =
					case 
					    when t.name = 'extended type' 
						then isnull(get_xtypename(c.xtype, c.xdbid),
											t.name)
					    when t.type = 58
						then "smalldatetime"
					    when t.usertype in (44,45,46)
						then "unsigned "+substring(t.name,
						charindex("u",t.name) + 1,
						charindex("t",t.name))
					    else 
						t.name
		                        end,
		              	LOCAL_TYPE_NAME =
					case 
					    when t.name = 'extended type' 
						then isnull(get_xtypename(c.xtype, c.xdbid),
											t.name)
					    when t.type = 58
						then "smalldatetime"
					    when t.usertype in (44,45,46)
						then "unsigned "+substring(t.name,
						charindex("u",t.name) + 1,
						charindex("t",t.name))
					    else 
						t.name
		                        end
		              
		                
			from
				syscolumns c,
				sysobjects o,
				sybsystemprocs.dbo.spt_datatype_info d,
				systypes t
				
			where
				o.name like @procedure_name
				and user_name(o.uid) like @procedure_schema
				and o.id = c.id
				and c.type *= d.ss_dtype
				and c.usertype *= t.usertype
		
		                /* Just procs & sqlj procs and funcs */
				and o.type in ('P', 'F')
				and c.name like @parameter_name
				and d.ss_dtype not in (111, 109, 38, 110) /* No *N types */
				
		
	order by PROCEDURE_SCHEMA, PROCEDURE_NAME, convert(int,colid)
end


update #oledb_results_table set o.DATA_TYPE = m.data_type   from
	sybsystemprocs.dbo.spt_sybdrv m, #oledb_results_table  o
	where o.TYPE_NAME =  m.type_name 
if(@is_ado = 2)
begin
select * from #oledb_results_table order by PROCEDURE_CATALOG, PROCEDURE_SCHEMA, PROCEDURE_NAME
end
else if(@is_ado = 1)
begin
select 
PROCEDURE_CATALOG ,
  	PROCEDURE_SCHEMA ,
  	PROCEDURE_NAME  ,
  	PARAMETER_NAME  ,
  	ORDINAL_POSITION ,
  	PARAMETER_TYPE 		,
  	PARAMETER_HASDEFAULT	,
  	PARAMETER_DEFAULT	,
  	IS_NULLABLE		,
  	DATA_TYPE		,
  	CHARACTER_MAXIMUM_LENGTH	,
  	CHARACTER_OCTET_LENGTH		,
  	NUMERIC_PRECISION		,
  	NUMERIC_SCALE			,
  	DESCRIPTION		,
  	TYPE_NAME		,
  	LOCAL_TYPE_NAME	
    from #oledb_results_table order by PROCEDURE_CATALOG, PROCEDURE_SCHEMA, PROCEDURE_NAME
  	
end
drop table #oledb_results_table
if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx  

go
exec sp_procxmode 'sp_oledb_getprocedurecolumns', 'anymode'
go
grant execute on sp_oledb_getprocedurecolumns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


/*---------INDEXES-----------------------------------------------------------*/

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_getindexinfo')
begin
	drop procedure sp_oledb_getindexinfo
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

/*
** Messages for "sp_oledb_getindexinfo"          18039
**
** 18039, "Table qualifier must be name of current database."
** 18040, "Catalog procedure '%1!' can not be run in a transaction.
**
*/

create procedure sp_oledb_getindexinfo (
	@table_name		varchar(771) = null,
	@table_owner		varchar(32) = null,
	@table_qualifier	varchar(32) = null,
	@index_name		varchar(771) = '%',
	@type			smallint = null)
as
declare @indid			int
declare @lastindid		int
declare @full_table_name	varchar(1543)
declare @startedInTransaction bit
declare @cmd	varchar(5000)

if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0

if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
if (@startedInTransaction = 1)
 save transaction oledb_keep_temptable_tx    

if @table_name is null
begin
	select @cmd = "select
		TABLE_CATALOG=db_name(),					-- table_catalog
		TABLE_SCHEMA=user_name(o.uid),					-- table_schema
		TABLE_NAME=o.name,						-- table_name
		INDEX_CATALOG=db_name(),					-- index_catalog
		INDEX_SCHEMA=o.name,						-- index_schema
		INDEX_NAME=x.name,						-- index_name
		PRIMARY_KEY=	case 
				when x.status&2048 = 2048 then convert(bit,1)
				else
				convert(bit,0)
				end,						-- primary_key
		'UNIQUE' =	case 
				when x.status&2 != 2 then convert(bit,0)
				else
				    convert(bit,1)
				end,						-- uniqueval
		'CLUSTERED' =	case
				when x.status2&512 = 512 then convert(bit,1)
				else
				convert(bit,1)
				end,						-- clusteredval
		TYPE=		case 
				when x.indid > 1 then convert(smallint,4)
				when x.status2&512 = 512 then convert(smallint,1)
				else
				convert(smallint,1)
				end,						-- type
		FILL_FACTOR=x.fill_factor,					-- fill_factor
		INITIAL_SIZE=null,						-- initial_size
		NULLS=4,							-- nulls
		SORT_BOOKMARKS=convert(bit,0),						-- sort_bookmarks
		AUTO_UPDATE=convert(bit,1),					-- auto_update
		NULL_COLLATION=4,						-- null_collation
		ORDINAL_POSITION=convert(int,colid),						-- ordinal_position
		COLUMN_NAME=INDEX_COL(o.name,indid,colid),			-- column name
		COLUMN_GUID = convert(varchar(36), null),
		COLUMN_PROPID=null,						-- column propid
		COLLATION=1,							-- collation
		CARDINALITY=case
			when x.indid > 1 then NULL
			else
--		rowcnt(x.doampg)			
 		row_count(db_id(), x.id)
			end, 							-- cardinality
		PAGES=case 
			when x.indid > 1 then NULL
			else
--		data_pgs(x.id,doampg)			
  		data_pages(db_id(), x.id,
 		case
 			when x.indid = 1
 			then 0
 			else x.indid
 		end)
 			end,							-- pages
       		FILTER_CONDITION=null,						-- filter condition
       		INTEGRATED=convert(bit,1)					-- integrated
	from sysindexes x, syscolumns c, sysobjects o
	where   x.id = o.id
		and x.id = c.id
		and c.colid < keycnt+(x.status&16)/16
		and o.type = 'U' and x.id = object_id(o.name)
		and x.indid < 255
		and o.name like @table_name
		and (x.name like '"+@index_name+"' or x.name is null)"   
end
else
begin
	/*
	** Fully qualify table name.
	*/
	if @table_owner is null
	begin	/* If unqualified table name */
		select @full_table_name = @table_name
		select @table_owner = '%'
	end
	else
	begin	/* Qualified table name */
		select @full_table_name = @table_owner + '.' + @table_name
	end

	if @table_qualifier is null
		select @table_qualifier = '%'

	select @cmd = "select
		TABLE_CATALOG=db_name(),					-- table_catalog
		TABLE_SCHEMA=user_name(o.uid),					-- table_schema
		TABLE_NAME=o.name,						-- table_name
		INDEX_CATALOG=db_name(),					-- index_catalog
		INDEX_SCHEMA=o.name,						-- index_schema
		INDEX_NAME=x.name,						-- index_name
		PRIMARY_KEY=	case 
				when x.status&2048 = 2048 then convert(bit,1)
				else
				convert(bit,0)
				end,						-- primary_key
		'UNIQUE' =	case 
				when x.status&2 != 2 then convert(bit,0)
				else
				    convert(bit,1)
				end,						-- uniqueval
		'CLUSTERED' =	case
				when x.status2&512 = 512 then convert(bit,1)
				else
				convert(bit,1)
				end,						-- clusteredval
		TYPE=		case 
				when x.indid > 1 then 4
				when x.status2&512 = 512 then 1
				else
				1
				end,						-- type
		FILL_FACTOR=x.fill_factor,					-- fill_factor
		INITIAL_SIZE=null,						-- initial_size
		NULLS=4,							-- nulls
		SORT_BOOKMARKS=convert(bit,0),						-- sort_bookmarks
		AUTO_UPDATE=convert(bit,1),					-- auto_update
		NULL_COLLATION=4,						-- null_collation
		ORDINAL_POSITION=convert(int,colid),						-- ordinal_position
		COLUMN_NAME=INDEX_COL('"+@full_table_name+"',indid,colid),		-- column name
		COLUMN_GUID = convert(varchar(36), null),
		COLUMN_PROPID=null,						-- column propid
		COLLATION=case 
			when index_colorder('"+@full_table_name+"',indid,colid) = 'ASC' then convert(smallint, 1)
			when index_colorder('"+@full_table_name+"',indid,colid) = 'DESC' then convert(smallint, 2)
			else convert(smallint, 0)
			end,							-- collation
		CARDINALITY=case
			when x.indid > 1 then NULL
			else
--		rowcnt(x.doampg)			
 		row_count(db_id(), x.id)
			end, 							-- cardinality
		PAGES=case 
			when x.indid > 1 then NULL
			else
--		data_pgs(x.id,doampg)			
  		data_pages(db_id(), x.id,
 		case
  			when x.indid = 1
  			then 0
  			else x.indid
  			end)
 			end,							-- pages
       		FILTER_CONDITION=null,						-- filter condition
       		INTEGRATED=convert(bit,1)					-- integrated
	from sysindexes x, syscolumns c, sysobjects o
	where x.id = object_id('"+@full_table_name+"')
		and x.id = o.id
		and x.id = c.id
		and c.colid < keycnt+(x.status&16)/16
		and (x.indid > 0 and x.indid < 255)
		and db_name() like '"+@table_qualifier+"'
		and user_name(o.uid) like '"+@table_owner+"'
		and (x.name like '"+@index_name+"' or x.name is null)"
	
end /*for the @table_name is not null*/

if @type is not null
	select @cmd=@cmd+" and @type in (1,4)"
select @cmd = @cmd+" order by TABLE_CATALOG, TABLE_SCHEMA, INDEX_NAME, TYPE, TABLE_NAME"
execute(@cmd)

if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx    

return (0)
go
exec sp_procxmode 'sp_oledb_getindexinfo', 'anymode'
go
grant execute on sp_oledb_getindexinfo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go



/*--------------------Primary Key-----------------------------*/
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_primarykey')
begin
	drop procedure sp_oledb_primarykey
end
go


/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** note: there is one raiserror message: 18040
**
** messages for "sp_oledb_primarykey"               18039, 18040
**
** 17461, "Object does not exist in this database."
** 18039, "table qualifier must be name of current database."
** 18040, "catalog procedure %1! can not be run in a transaction.", sp_oledb_primarykey
**
*/

create procedure sp_oledb_primarykey
			   @table_name		varchar(771) = null,
			   @table_owner 	varchar(32) = null,
			   @table_qualifier varchar(32) = null 
as
declare @keycnt smallint
declare @indexid smallint
declare @indexname varchar(771)
declare @i int
declare @id int
declare @uid int
select @id = NULL
declare @startedInTransaction bit

    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

	set nocount on

	if (@@trancount = 0)
	begin
		set chained off
	end

	set transaction isolation level 1

    if (@startedInTransaction = 1)
	save transaction oledb_keep_temptable_tx    

	if @table_owner is null
	begin
		select @id = id , @uid = uid
		from sysobjects 
		where name = @table_name
			and uid = user_id()
		if (@id is null)
		begin
			select @id = id ,@uid = uid
			from sysobjects 
			where name = @table_name
			and uid = 1
		end
	end
	else
	begin
		select @id = id , @uid = uid
		from sysobjects 
		where name = @table_name and uid = user_id(@table_owner)
	end

    select 
	TABLE_CATALOG=db_name(),
	TABLE_SCHEMA=user_name(@uid),
	TABLE_NAME=@table_name,
	COLUMN_NAME=index_col(@table_name, i.indid, c.colid, @uid),
	COLUMN_GUID=convert(varchar(30),null),
	COLUMN_PROPID=convert(int,null),
	ORDINAL=c.colid,
	PK_NAME=i.name
	from sysobjects o,sysindexes i,syscolumns c 
	where o.id=i.id 
		and c.id=i.id 
		and i.id=@id 
		and o.uid= @uid
		and i.indid > 0 
		and i.status2 & 2 = 2 
		and i.status & 2048 = 2048
		and index_col(@table_name, i.indid, c.colid, @uid) != null
	order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
	
if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx    
	
return (0)
go
exec sp_procxmode 'sp_oledb_primarykey', 'anymode'
go
grant execute on sp_oledb_primarykey to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

/*-----------------------Foreign Key----------------------------*/
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_fkeys')
begin
	drop procedure sp_oledb_fkeys
end
go


/* sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
/*
** note: there is one raiserror message: 18040
**
** messages for "sp_oledb_fkeys"               18039, 18040
**
** 17461, "Object does not exist in this database." 
** 18040, "Catalog procedure %1! can not be run in a transaction.", sp_oledb_fkeys
** 18043 " Primary key table name or foreign key table name or both must be 
** given"
** 18044, "%1! table qualifier must be name of current database." [Primary
** key | Foreign key]
**
*/
CREATE PROCEDURE sp_oledb_fkeys
			   @pktable_name		varchar(255) = null,
			   @pktable_owner		varchar(32) = null,
			   @pktable_qualifier	varchar(32) = null,
			   @fktable_name		varchar(255) = null,
			   @fktable_owner		varchar(32) = null,
			   @fktable_qualifier	varchar(32) = null 
as
declare @ftabid int, @ptabid int, @constrid int,@keycnt int, @i int
declare @fokey1 int,  @fokey2 int,  @fokey3 int,  @fokey4 int,  @fokey5  int
declare @fokey6 int,  @fokey7 int,  @fokey8 int,  @fokey9 int,  @fokey10 int
declare @fokey11 int, @fokey12 int, @fokey13 int, @fokey14 int, @fokey15 int
declare @refkey1 int, @refkey2 int, @refkey3 int, @refkey4 int, @refkey5  int
declare @refkey6 int, @refkey7 int, @refkey8 int, @refkey9 int, @refkey10 int
declare @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
declare @refkey15 int, @refkey16 int, @fokey16 int, @status int
declare @msg varchar(1024)
declare @msg2 varchar(1024)
declare @ordpkey	int
declare @notDeferrable smallint
declare @startedInTransaction bit

	if (@@trancount > 0)
	    select @startedInTransaction = 1
	else
	    select @startedInTransaction = 0


	set nocount on

	if (@@trancount = 0)
	begin
		set chained off
	end


	set transaction isolation level 1
	if (@startedInTransaction = 1)
	    save transaction oledb_keep_temptable_tx    

	select @notDeferrable = 3

	create table #ofkey_res( PK_TABLE_CATALOG varchar(32),
				PK_TABLE_SCHEMA       varchar(32),
				PK_TABLE_NAME       varchar(255),
				PK_COLUMN_NAME      varchar(255),
				PK_COLUMN_PROP_ID   int null,
				FK_TABLE_CATALOG varchar(32),
				FK_TABLE_SCHEMA       varchar(32),
				FK_TABLE_NAME       varchar(255),
				FK_COLUMN_NAME       varchar(255),
				FK_COLUMN_PROP_ID   int null,
				ORDINAL           int,	
				UPDATE_RULE varchar(32), 
				DELETE_RULE varchar(32),
				FK_NAME	varchar(255),
				PK_NAME	varchar(255),
				DEFERRABILITY smallint)
				
	if (@pktable_name is null) and (@fktable_name is null)
	begin	
		/* If neither primary key nor foreign key table names given */
		/* goto select directly and return no rows
		*/
		goto SelectClause
	end

	if @fktable_qualifier is not null
	begin
		if db_name() != @fktable_qualifier
		begin	
			goto SelectClause
		end
	end
	else
	begin
		/*
		** Now make sure that foreign table qualifier is pointing to the
		** current database in case it is not specified.
		*/
		select @fktable_qualifier = db_name()
	end

	if @pktable_qualifier is not null
	begin
		if db_name() != @pktable_qualifier
		begin	
			goto SelectClause
		end
	end
	else
	begin
		/*
		** Now make sure that primary table qualifier is pointing to the
		** current database in case it is not specified.
		*/
		select @pktable_qualifier = db_name()
	end


	create table #opid (pid int, uid int, name varchar(255))
	create table #ofid (fid int, uid int, name varchar(255))

	/* we will sort by fkey		*/
	/* unless pktable is null	*/

	select @ordpkey = 0

	if @pktable_name is not null
	begin 

		if (@pktable_owner is null)
		begin
			/* 
			** owner is NULL, so default to the current user
			** who owns this table, otherwise default to dbo
			** who owns this table.
			*/
			insert into #opid 
			select id, uid, name
			from sysobjects 
			where name = @pktable_name and uid = user_id()
			and type in ("S", "U")
			
			/* 
			** If the current user does not own the table, see
			** if the DBO of the current database owns the table.
			*/

			if ((select count(*) from #opid ) = 0)
			begin
				insert into #opid 
				select id, uid, name
				from sysobjects 
				where name = @pktable_name and uid = 1
				and type in ("S", "U")
			end
		end
		else
		begin
			insert into #opid
			select id, uid, name
			from sysobjects
			where name = @pktable_name 
			and uid = user_id(@pktable_owner)
			and type in ("S", "U")
		end
	end
	else 
	begin
		if (@pktable_owner is null)
		begin
		/* 
		** If neither pktable_name nor pktable_owner is specified,
		** then we are interested in every user or system table.
		*/
			insert into #opid 
			select id, uid, name
			from sysobjects 
			where type in ("S", "U")
		end
		else
		begin
			insert into #opid
			select id, uid, name
			from sysobjects
			where  uid = user_id(@pktable_owner)
			and type in ("S", "U")
		end
	end
		
	if @fktable_name is not null
	begin 
		/* sort by pkey	*/
		select @ordpkey = 1

		if (@fktable_owner is null)
		begin
			/* 
			** owner is NULL, so default to the current user
			** who owns this table, otherwise default to dbo
			** who owns this table.
			*/
			insert into #ofid 
			select id, uid, name
			from sysobjects 
			where name = @fktable_name and uid = user_id()
			and type in ("S", "U")

			/* 
			** If the current user does not own the table, see
			** if the DBO of the current database owns the table.
			*/

			if ((select count(*) from #opid ) = 0)
			begin
				insert into #ofid 
				select id, uid, name
				from sysobjects 
				where name = @fktable_name and uid = 1
				and type in ("S", "U")
			end
		end
		else
		begin
			insert into #ofid
			select id, uid, name
			from sysobjects
			where name = @fktable_name 
			and uid = user_id(@fktable_owner)
			and type in ("S", "U")
		end
	end
	else
	begin
		if (@fktable_owner is null)
		begin
		/* 
		** If neither fktable_name nor fktable_owner is specified,
		** then we are interested in every user table or systme 
		** table.
		*/			
			insert into #ofid 
			select id, uid, name
			from sysobjects 
			where type in ("S", "U")
		end
		else
		begin
			insert into #ofid
			select id, uid, name
			from sysobjects
			where  uid = user_id(@fktable_owner)
			and type in ("S", "U")
		end
	end

	if (((select count(*) from #ofid ) = 0) or
		((select count(*) from #opid) = 0))
	begin
		goto SelectClause
	end


	create table #opkeys(seq int,  keys varchar(255) null)
	create table #ofkeys(seq int, keys varchar(255) null)

	/*
	** Since there are possibly multiple rows in sysreferences
	** that describe foreign and primary key relationships among
	** two tables, so we declare a cursor on the selection from
	** sysreferences and process the output at row by row basis.
	*/
		
	declare curs_sysreferences cursor
	for
	select tableid, reftabid, constrid, keycnt,
	fokey1, fokey2, fokey3, fokey4, fokey5, fokey6, fokey7, fokey8, 
	fokey9, fokey10, fokey11, fokey12, fokey13, fokey14, fokey15,
	fokey16, refkey1, refkey2, refkey3, refkey4, refkey5,
	refkey6, refkey7, refkey8, refkey9, refkey10, refkey11,
	refkey12, refkey13, refkey14, refkey15, refkey16
	from sysreferences
	where tableid in (
		select fid from #ofid)
	and reftabid in (
		select pid from #opid)
	and frgndbname is NULL and pmrydbname is NULL
	for read only

	open  curs_sysreferences

	fetch  curs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt,@fokey1, 
	@fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8, 
	@fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15, 
	@fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6, 
	@refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12, 
	@refkey13, @refkey14, @refkey15, @refkey16

	while (@@sqlstatus = 0)
	begin
		/*
		** For each row of sysreferences which describes a foreign-
		** primary key relationship, do the following.
		*/

		/*
		** First store the column names that belong to primary keys
		** in table #pkeys for later retrieval.
		*/

		delete #opkeys
		insert #opkeys values(1, col_name(@ptabid,@refkey1))
		insert #opkeys values(2, col_name(@ptabid,@refkey2))
		insert #opkeys values(3, col_name(@ptabid,@refkey3))
		insert #opkeys values(4, col_name(@ptabid,@refkey4))
		insert #opkeys values(5, col_name(@ptabid,@refkey5))
		insert #opkeys values(6, col_name(@ptabid,@refkey6))
		insert #opkeys values(7, col_name(@ptabid,@refkey7))
		insert #opkeys values(8, col_name(@ptabid,@refkey8))
		insert #opkeys values(9, col_name(@ptabid,@refkey9))
		insert #opkeys values(10, col_name(@ptabid,@refkey10))
		insert #opkeys values(11, col_name(@ptabid,@refkey11))
		insert #opkeys values(12, col_name(@ptabid,@refkey12))
		insert #opkeys values(13, col_name(@ptabid,@refkey13))
		insert #opkeys values(14, col_name(@ptabid,@refkey14))
		insert #opkeys values(15, col_name(@ptabid,@refkey15))
		insert #opkeys values(16, col_name(@ptabid,@refkey16))
	
		/*
		** Second store the column names that belong to foreign keys
		** in table #fkeys for later retrieval.
		*/
		
		delete #ofkeys
		insert #ofkeys values(1, col_name(@ftabid,@fokey1))
		insert #ofkeys values(2, col_name(@ftabid,@fokey2))
		insert #ofkeys values(3, col_name(@ftabid,@fokey3))
		insert #ofkeys values(4, col_name(@ftabid,@fokey4))
		insert #ofkeys values(5, col_name(@ftabid,@fokey5))
		insert #ofkeys values(6, col_name(@ftabid,@fokey6))
		insert #ofkeys values(7, col_name(@ftabid,@fokey7))
		insert #ofkeys values(8, col_name(@ftabid,@fokey8))
		insert #ofkeys values(9, col_name(@ftabid,@fokey9))
		insert #ofkeys values(10, col_name(@ftabid,@fokey10))
		insert #ofkeys values(11, col_name(@ftabid,@fokey11))
		insert #ofkeys values(12, col_name(@ftabid,@fokey12))
		insert #ofkeys values(13, col_name(@ftabid,@fokey13))
		insert #ofkeys values(14, col_name(@ftabid,@fokey14))
		insert #ofkeys values(15, col_name(@ftabid,@fokey15))
		insert #ofkeys values(16, col_name(@ftabid,@fokey16))
	
		/* 
		** For each column of the current foreign-primary key relation,
		** create a row into result table: #fkey_res.
		*/

		select @i = 1
		while (@i <= @keycnt)
		begin
			insert into #ofkey_res 
				select @pktable_qualifier,
				(select user_name(uid) from #opid where pid = @ptabid),
				object_name(@ptabid),
				(select keys from #opkeys where seq = @i),
				null,
				@fktable_qualifier,
				(select user_name(uid) from #ofid where fid = @ftabid),
				object_name(@ftabid), 
				(select keys from #ofkeys where seq = @i), null, @i,
				"NO_ACTION", "NO_ACTION",
			/* Foreign Key */				
				object_name(@constrid),
			/* Primary key name */
		                (select name from sysindexes where id = @ptabid
		                    and status > 2048 and status < 32768),
		           @notDeferrable      
			select @i = @i + 1
		end
		
		/* 
		** Go to the next foreign-primary key relationship if any.
		*/

		fetch  curs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt,@fokey1, 
		@fokey2, @fokey3,  @fokey4, @fokey5, @fokey6, @fokey7, @fokey8, 
		@fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15, 
		@fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6, 
		@refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12, 
		@refkey13, @refkey14, @refkey15, @refkey16
	end

	close curs_sysreferences
	deallocate cursor curs_sysreferences

	/*
	** Everything is now in the result table #fkey_res, so go ahead
	** and select from the table now.
	*/

SelectClause:
	select PK_TABLE_CATALOG, 
		PK_TABLE_SCHEMA, 
		PK_TABLE_NAME,
		PK_COLUMN_NAME, 
		PK_COLUMN_GUID = convert(varchar(36), null),
		PK_COLUMN_PROP_ID = convert(int, null),
		FK_TABLE_CATALOG, 
		FK_TABLE_SCHEMA, 
		FK_TABLE_NAME, 
		FK_COLUMN_NAME, 
		FK_COLUMN_GUID = convert(varchar(36), null),
		FK_COLUMN_PROP_ID = convert(int, null),			
		ORDINAL, 
		UPDATE_RULE, 
		DELETE_RULE,
		FK_NAME,
		PK_NAME,
		DEFERRABILITY
	from #ofkey_res fkey
	order by FK_TABLE_CATALOG,FK_TABLE_SCHEMA, FK_TABLE_NAME

drop table #ofkey_res
drop table #opkeys
drop table #ofkeys

if (@startedInTransaction = 1)
   rollback transaction oledb_keep_temptable_tx    

go
exec sp_procxmode 'sp_oledb_fkeys', 'anymode'
go
grant execute on sp_oledb_fkeys to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go



/* --------------COLUMNS ------------------------------------- */

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_columns')
begin
	drop procedure sp_oledb_columns
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G% " */
/*      10.0        07/20/93        sproc/columns */
 

/* This is the version for servers which support UNION */

/* This routine is intended for support of oledb connectivity.  Under no
** circumstances should changes be made to this routine unless they are
** to fix oledb related problems.  All other users are at there own risk!
**
** Please be aware that any changes made to this file (or any other oledb
** support routine) will require Sybase to recertify the SQL server as
** oledb compliant.  This process is currently being managed internally
** by the "Interoperability Engineering Technology Solutions Group" here
** within Sybase.
*/

CREATE PROCEDURE sp_oledb_columns (
				 @table_name		varchar(771) = null,
				 @table_owner		varchar(32) = null,
				 @table_qualifier	varchar(32) = null,
				 @column_name		varchar(771) = null,
				 @is_ado            int =1 )
AS
    declare @full_table_name    varchar(1543)
    declare @table_id int
    declare @char_bin_types   varchar(32)
    declare @startedInTransaction bit
    
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0    
        
    set transaction isolation level 1

    if (@startedInTransaction = 1)
	save transaction oledb_keep_temptable_tx      
 
/* character and binary datatypes */
	select @char_bin_types =
		char(47)+char(39)+char(45)+char(37)+char(35)+char(34)

    create table #results_table
		(TABLE_CATALOG  varchar(32) null,
		TABLE_SCHEMA varchar(32) null,
		TABLE_NAME   varchar(255) null,
		COLUMN_NAME  varchar(255) null,
		COLUMN_GUID  varchar(36)  null,
		COLUMN_PROPID int null,
		ORDINAL_POSITION int null,
		COLUMN_HASDEFAULT bit default 1,
		COLUMN_DEFAULT varchar(255) null,
		COLUMN_FLAGS int null,
		usertype int null,
        	IS_NULLABLE bit default 1,
		DATA_TYPE smallint null,
		TYPE_GUID varchar(36) null,
		CHARACTER_MAXIMUM_LENGTH int null,
            	CHARACTER_OCTET_LENGTH int null, 
		NUMERIC_PRECISION smallint null,
		NUMERIC_PRECISION_RADIX  smallint null,
		TYPE_NAME varchar (255) null,
		NUMERIC_SCALE smallint null,
		DATETIME_PRECISION int null,									
		CHARACTER_SET_CATALOG varchar(32) null,
		CHARACTER_SET_SCHEMA varchar(32) null,
		CHARACTER_SET_NAME varchar(255) null,
		COLLATION_CATALOG varchar(32) null,
		COLLATION_SCHEMA varchar(32) null,
		COLLATION_NAME varchar(32) null,
		DOMAIN_CATALOG varchar(32) null,
		DOMAIN_SCHEMA varchar(32) null,
		DOMAIN_NAME varchar(32) null,
		DESCRIPTION varchar(255) null,
		tds_type smallint null,
		id int null,
		col_len int null)
		
    if @column_name is null /*	If column name not supplied, match all */
	select @column_name = '%'

    /* Check if the current database is the same as the one provided */
    if @table_qualifier is not null
    begin
		if db_name() != @table_qualifier
		begin	/* 
			** If qualifier doesn't match current database 
			** force a no-row selection
			*/
			goto SelectClause
		end
    end

    if @table_name is null
    begin	/*	If table name not supplied, match all */
		select @table_name = '%'
    end

    if @table_owner is null
    begin	/* If unqualified table name */
		SELECT @full_table_name = @table_name
    end
    else
    begin	/* Qualified table name */
		SELECT @full_table_name = @table_owner + '.' + @table_name
    end

    /* Get Object ID */
    SELECT @table_id = object_id(@full_table_name)


    /* If the table name parameter is valid, get the information */ 
    if ((charindex('%',@full_table_name) = 0) and
		(charindex('_',@full_table_name) = 0)  and
		@table_id != 0)
    begin
    insert into #results_table
	SELECT	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		TABLE_CATALOG = DB_NAME(),
		TABLE_SCHEMA = USER_NAME(o.uid),
		TABLE_NAME = o.name,
		COLUMN_NAME = c.name,
		COLUMN_GUID = convert(varchar(36), null),
		COLUMN_PROPID = convert(int, null),
		ORDINAL_POSITION = convert(int,c.colid),
		COLUMN_HASDEFAULT = convert(bit,c.cdefault&1),
		COLUMN_DEFAULT = convert(varchar(254), null),
		/*CT: IsNullable 0x20 (c.status&8 * 4),
		      MaybeNullable 0x40 (c.status&8 * 8) - always MaybeNullable if IsNullable
		      IsFixedLength 0x10 - yes
		      IsLong 0x80 - no
		*/
		COLUMN_FLAGS = convert(int, c.status&8) * 12 + 16,
		usertype = t.usertype,
                IS_NULLABLE = convert(bit, c.status&8),
		DATA_TYPE = convert(smallint, m.data_type) ,
		TYPE_GUID = convert(varchar(36), null),
		CHARACTER_MAXIMUM_LENGTH = convert(int, null),  /*CT: only for char, binary and bit in oledb */
            	CHARACTER_OCTET_LENGTH = convert(int, null), /*CT: only for char, binary and bit in oledb */
		/* CT: MONEYN, INTN, DATETIMN and FLOATN will all be included */
		NUMERIC_PRECISION = isnull(convert(smallint, c.prec),
			         isnull(convert(smallint, d.data_precision),
			        convert(smallint,c.length)))
				+isnull(d.aux, convert(smallint,
				ascii(substring("???AAAFFFCKFOLS",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),

		NUMERIC_PRECISION_RADIX = d.numeric_radix,
        	TYPE_NAME = 
		case 
			when convert(bit, (c.status & 0x80)) = 1 then 
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))+' identity'
		         else
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))
                 end,
		NUMERIC_SCALE = convert(smallint, null),  /*CT: only for decimal and numeric in oledb*/
		/*CT: in ss_dtype 111, 109, 38, 110, only 111 has non null value for this item
		  it is the datetime type scale, UI4 type*/
		DATETIME_PRECISION = case 
					when d.ss_dtype = 111  /*CT:  also the type is changed to UI4*/
						then 
						isnull(convert(int, c.scale), 
					        convert(int, d.numeric_scale))
						+convert(int,
						isnull(d.aux,
						ascii(substring("<<<<<<<<<<<<<<?",
						2*(d.ss_dtype%35+1)+2-8/c.length,
						1))-60))
					else
						convert(int, null)
				     end,					
				
		CHARACTER_SET_CATALOG = null,
		CHARACTER_SET_SCHEMA = null, 
		CHARACTER_SET_NAME = null,
		COLLATION_CATALOG = null,
		COLLATION_SCHEMA = null,
		COLLATION_NAME = null,
		DOMAIN_CATALOG = null,
		DOMAIN_SCHEMA = null,
		DOMAIN_NAME = null,
		DESCRIPTION = null,	/* Description are NULL */
		tds_type = c.type,
		id = c.id,
		col_len = c.length
		
	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sybsystemprocs.dbo.spt_sybdrv m
	WHERE
		o.id = @table_id
		AND c.id = o.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		AND t.type = d.ss_dtype
		AND c.name like @column_name
--	AND d.ss_dtype IN (111, 109, 38, 110)	/* Just *N types */
 	AND d.ss_dtype IN (111, 109, 38, 110, 68)	/* Just *N types */
		AND c.usertype < 100		/* No user defined types */
		AND m.type_name = 
		rtrim(substring(d.type_name,
		1+isnull(d.aux,
		ascii(substring("III<<<MMMI<<A<A",
		2*(d.ss_dtype%35+1)+2-8/c.length,
		1))-60), 18))
	UNION
	SELECT	/* All other types including user data types */
		TABLE_CATALOG = DB_NAME(),
		TABLE_SCHEMA = USER_NAME(o.uid),
		TABLE_NAME = o.name,
		COLUMN_NAME = c.name,
		COLUMN_GUID = convert(varchar(36), null),
		COLUMN_PROPID = convert(int, null),
		ORDINAL_POSITION = convert(int,c.colid),
		COLUMN_HASDEFAULT = convert(bit,c.cdefault&1),
		COLUMN_DEFAULT = convert(varchar(254), null),
		/*CT: IsNullable 0x20 (c.status&8 * 4),
		      MaybeNullable 0x40 (c.status&8 * 8) - always MaybeNullable if IsNullable
		      IsFixedLength 0x10 - yes
		      IsLong 0x80 - no
		*/
		COLUMN_FLAGS = convert(int, c.status&8) * 12 + 
			case when c.type in (37, 39, 155, 34, 35, 174) then 0
			else 16 end +
			case when c.type in (34, 35, 174) then 128 /*text, image and unitext type*/
			else 0 end,
		usertype = t.usertype,
                IS_NULLABLE = convert(bit, c.status&8),
		DATA_TYPE = convert(smallint, m.data_type) ,
		TYPE_GUID = convert(varchar(36), null),
		/*CT: only for char, binary and bit in oledb, see spec*/
		CHARACTER_MAXIMUM_LENGTH = case
						when c.type in (135, 155)
							then
								(isnull(convert(int, c.prec),
								 isnull(convert(int, d.data_precision),
								convert(int,c.length)))
								+isnull(d.aux, convert(int,
								ascii(substring("???AAAFFFCKFOLS",
								2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)))/2
						when c.type in (47, 39, 45, 37, 35, 34, 50)
							then 
								isnull(convert(int, c.prec),
								 isnull(convert(int, d.data_precision),
								convert(int,c.length)))
								+isnull(d.aux, convert(int,
								ascii(substring("???AAAFFFCKFOLS",
								2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
						else
							convert(int, null)
					   end,
												 
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(c.type is in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   if (c.type is in (135, 155)
            	**       set char_octet_length = prec * 2;
            	**   else
            	**       set char_octet_length = null;
            	*/
           	CHARACTER_OCTET_LENGTH = case
					when c.type in (47, 39, 45, 37, 35, 34, 50)
						then /*same size as the CHARACTER_MAXIMUM_LENGTH */
							isnull(convert(int, c.prec),
							 isnull(convert(int, d.data_precision),
							convert(int,c.length)))
							+isnull(d.aux, convert(int,
							ascii(substring("???AAAFFFCKFOLS",
							2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
					when c.type in (135, 155)
						then /* CHARACTER_MAXIMUM_LENGTH * 2 for the unichar, univarchar*/
							isnull(convert(int, c.prec),
							 isnull(convert(int, d.data_precision),
							convert(int,c.length)))
							+isnull(d.aux, convert(int,
							ascii(substring("???AAAFFFCKFOLS",
							2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
					else
						convert(int, null)
				   end,
		NUMERIC_PRECISION = case 
					when c.type in (47, 39, 45, 37, 35, 34, 135, 155, 50, 58, 61, 123, 147,174)
						then convert(smallint,null)
					else
						isnull(convert(smallint, c.prec),
						 isnull(convert(smallint, d.data_precision),
						convert(smallint,c.length)))
						+isnull(d.aux, convert(smallint,
						ascii(substring("???AAAFFFCKFOLS",
						2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
					end,
		NUMERIC_PRECISION_RADIX = d.numeric_radix,				
		TYPE_NAME = 
		case 
			when convert(bit, (c.status & 0x80)) = 1 then 
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))+' identity'
		         else
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))
                 end,
		
      		NUMERIC_SCALE = case 
					when c.type in (63, 108, 55, 106) then
						isnull(convert(smallint, c.scale), 
					       convert(smallint, d.numeric_scale)) +
						convert(smallint, isnull(d.aux,
						ascii(substring("<<<<<<<<<<<<<<?",
						2*(d.ss_dtype%35+1)+2-8/c.length,
						1))-60))
					else
						convert(smallint, null)
				end,
		DATETIME_PRECISION = case 
					when c.type in (58, 61, 123, 147, 111) then 
						isnull(convert(int, c.scale), 
					        convert(int, d.numeric_scale)) +
						convert(int, isnull(d.aux,
						ascii(substring("<<<<<<<<<<<<<<?",
						2*(d.ss_dtype%35+1)+2-8/c.length,
						1))-60))
					else
						convert(int, null)
				     end,
		CHARACTER_SET_CATALOG = null,
		CHARACTER_SET_SCHEMA = null, 
		CHARACTER_SET_NAME = null,
		COLLATION_CATALOG = null,
		COLLATION_SCHEMA = null,
		COLLATION_NAME = null,
		DOMAIN_CATALOG = null,
		DOMAIN_SCHEMA = null,
		DOMAIN_NAME = null,
		DESCRIPTION = null,	/* Description are NULL */
		tds_type = c.type,
		id = c.id,
		col_len = c.length


	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sybsystemprocs.dbo.spt_sybdrv m
	WHERE
		o.id = @table_id
		AND c.id = o.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		/*
		** We need a equality join with 
		** sybsystemprocs.dbo.spt_datatype_info here so that
		** there is only one qualified row returned from 
		** sybsystemprocs.dbo.spt_datatype_info, thus avoiding
		** duplicates.
		*/
		AND t.type = d.ss_dtype
		AND c.name like @column_name
--	AND (d.ss_dtype NOT IN (111, 109, 38, 110) /* No *N types */
 	AND (d.ss_dtype NOT IN (111, 109, 38, 110, 68) /* No *N types */

			OR c.usertype >= 100) /* User defined types */
		AND m.type_name = 
		rtrim(substring(d.type_name,
		1+isnull(d.aux,
		ascii(substring("III<<<MMMI<<A<A",
		2*(d.ss_dtype%35+1)+2-8/c.length,
		1))-60), 18))

		ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
	end
	else
    begin
	/* 
	** This block is for the case where there IS pattern
	** matching done on the table name. 
	*/
	if @table_owner is null /* If owner not supplied, match all */
			select @table_owner = '%'

	insert into #results_table
	SELECT	/* INTn, FLOATn, DATETIMEn and MONEYn types */
		TABLE_CATALOG = DB_NAME(),
		TABLE_SCHEMA = USER_NAME(o.uid),
		TABLE_NAME = o.name,
		COLUMN_NAME = c.name,
		COLUMN_GUID = convert(varchar(36), null),
		COLUMN_PROPID = convert(int, null),
		ORDINAL_POSITION = convert(int,c.colid),
		COLUMN_HASDEFAULT = convert(bit,c.cdefault&1),
		COLUMN_DEFAULT = convert(varchar(254), null),
		/*CT: IsNullable 0x20 (c.status&8 * 4),
		      MaybeNullable 0x40 (c.status&8 * 8) - always MaybeNullable if IsNullable
		      IsFixedLength 0x10 - yes
		      IsLong 0x80 - no
		*/
		COLUMN_FLAGS = convert(int, c.status&8) * 12 + 16,
		usertype = t.usertype,
                IS_NULLABLE = convert(bit, c.status&8),
		DATA_TYPE = convert(smallint, m.data_type) ,
		TYPE_GUID = convert(varchar(36), null),
		CHARACTER_MAXIMUM_LENGTH = convert(int, null),  /*CT: only for char, binary and bit in oledb */
            	CHARACTER_OCTET_LENGTH = convert(int, null), /*CT: only for char, binary and bit in oledb */
		/* CT: MONEYN, INTN, DATETIMN and FLOATN will all be included */
		NUMERIC_PRECISION = isnull(convert(smallint, c.prec),
			         isnull(convert(smallint, d.data_precision),
			        convert(smallint,c.length)))
				+isnull(d.aux, convert(smallint,
				ascii(substring("???AAAFFFCKFOLS",
				2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
        	NUMERIC_PRECISION_RADIX = d.num_prec_radix,
         	TYPE_NAME = 
		case 
			when convert(bit, (c.status & 0x80)) = 1 then 
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))+' identity'
		         else
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))
                 end,
		NUMERIC_SCALE = convert(smallint, null),  /*CT: only for decimal and numeric in oledb*/
		/*CT: in ss_dtype 111, 109, 38, 110, only 111 has non null value for this item
		  it is the datetime type scale, UI4 type*/
		DATETIME_PRECISION = case 
					when d.ss_dtype = 111  /*CT:  also the type is changed to UI4*/
						then 
						isnull(convert(int, c.scale), 
					        convert(int, d.numeric_scale))
						+convert(int,
						isnull(d.aux,
						ascii(substring("<<<<<<<<<<<<<<?",
						2*(d.ss_dtype%35+1)+2-8/c.length,
						1))-60))
					else
						convert(int, null)
				     end,
		CHARACTER_SET_CATALOG = null,
		CHARACTER_SET_SCHEMA = null, 
		CHARACTER_SET_NAME = null,
		COLLATION_CATALOG = null,
		COLLATION_SCHEMA = null,
		COLLATION_NAME = null,
		DOMAIN_CATALOG = null,
		DOMAIN_SCHEMA = null,
		DOMAIN_NAME = null,
		DESCRIPTION = null,	/* Description are NULL */
		tds_type = c.type,
		id = c.id,
		col_len = c.length

	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sybsystemprocs.dbo.spt_sybdrv m
	WHERE
		o.name like @table_name
		AND user_name(o.uid) like @table_owner
		AND o.id = c.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		AND t.type = d.ss_dtype
		AND o.type != 'P'
		AND c.name like @column_name
--	AND d.ss_dtype IN (111, 109, 38, 110)	/* Just *N types */
 	AND d.ss_dtype IN (111, 109, 38, 110, 68)	/* Just *N types */	
		AND c.usertype < 100
		AND m.type_name = 
		rtrim(substring(d.type_name,
		1+isnull(d.aux,
		ascii(substring("III<<<MMMI<<A<A",
		2*(d.ss_dtype%35+1)+2-8/c.length,
		1))-60), 18))
	UNION
	SELECT /* All other types including user data types */
		TABLE_CATALOG = DB_NAME(),
		TABLE_SCHEMA = USER_NAME(o.uid),
		TABLE_NAME = o.name,
		COLUMN_NAME= c.name,
		COLUMN_GUID = convert(varchar(36), null),
		COLUMN_PROPID = convert(int, null),
		ORDINAL_POSITION = convert(int,c.colid),
		COLUMN_HASDEFAULT = convert(bit,c.cdefault&1),
		COLUMN_DEFAULT = convert(varchar(254), null),
		/*CT: IsNullable 0x20 (c.status&8 * 4),
		      MaybeNullable 0x40 (c.status&8 * 8) - always MaybeNullable if IsNullable
		      IsFixedLength 0x10 - yes
		      IsLong 0x80 - no
		*/
		COLUMN_FLAGS = convert(int, c.status&8) * 12 + 
			case when c.type in (37, 39, 155, 34, 35, 174) then 0
			else 16 end +
			case when c.type in (34, 35, 174) then 128 /*text, image and unitext type*/
			else 0 end,
		usertype = t.usertype,
		IS_NULLABLE = convert(bit, c.status&8),
		DATA_TYPE = convert(smallint, m.data_type) ,
		TYPE_GUID = convert(varchar(36), null),
		/*CT: only for char, binary and bit in oledb, see spec*/
		CHARACTER_MAXIMUM_LENGTH = case
						when c.type in (135, 155)
							then
								(isnull(convert(int, c.prec),
								 isnull(convert(int, d.data_precision),
								convert(int,c.length)))
								+isnull(d.aux, convert(int,
								ascii(substring("???AAAFFFCKFOLS",
								2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)))/2
						when c.type in (47, 39, 45, 37, 35, 34, 50)
							then 
								isnull(convert(int, c.prec),
								 isnull(convert(int, d.data_precision),
								convert(int,c.length)))
								+isnull(d.aux, convert(int,
								ascii(substring("???AAAFFFCKFOLS",
								2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
						else
							convert(int, null)
					   end,
												 
            	/*
            	** if the datatype is of type CHAR or BINARY
            	** then set char_octet_length to the same value
            	** assigned in the "prec" column.
            	**
            	** The first part of the logic is:
            	**
            	**   if(c.type in (47, 39, 45, 37, 35, 34))
            	**       set char_octet_length = prec;
            	**   if (c.type in (135, 155)
            	**       set char_octet_length = prec * 2;
            	**   else
            	**       set char_octet_length = null;
            	*/
           	CHARACTER_OCTET_LENGTH = case
					when c.type in (47, 39, 45, 37, 35, 34, 50)
						then /*same size as the CHARACTER_MAXIMUM_LENGTH */
							isnull(convert(int, c.prec),
							 isnull(convert(int, d.data_precision),
							convert(int,c.length)))
							+isnull(d.aux, convert(int,
							ascii(substring("???AAAFFFCKFOLS",
							2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
					when c.type in (135, 155)
						then /* CHARACTER_MAXIMUM_LENGTH * 2 for the unichar, univarchar*/
							isnull(convert(int, c.prec),
							 isnull(convert(int, d.data_precision),
							convert(int,c.length)))
							+isnull(d.aux, convert(int,
							ascii(substring("???AAAFFFCKFOLS",
							2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
					else
						convert(int, null)
				   end,
		NUMERIC_PRECISION = case 
					when c.type in (47, 39, 45, 37, 35, 34, 135, 155, 50, 58, 61, 123, 147,174)
						then convert(smallint,null)
					else
						isnull(convert(smallint, c.prec),
						 isnull(convert(smallint, d.data_precision),
						convert(smallint,c.length)))
						+isnull(d.aux, convert(smallint,
						ascii(substring("???AAAFFFCKFOLS",
						2*(d.ss_dtype%35+1)+2-8/c.length,1))-60))
					end,
		NUMERIC_PRECISION_RADIX = d.numeric_radix,
         	TYPE_NAME = 
		case 
			when convert(bit, (c.status & 0x80)) = 1 then 
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))+' identity'
		         else
				rtrim(substring(d.type_name,
		                        1+isnull(d.aux,
		                        ascii(substring('III<<<MMMI<<A<A',
		                        2*(d.ss_dtype%35+1)+2-8/c.length,
		                        1))-60), 18))
                 end,
		NUMERIC_SCALE = case 
					when c.type in (63, 108, 55, 106) then 
						isnull(convert(smallint, c.scale), 
					       convert(smallint, d.numeric_scale)) +
						convert(smallint, isnull(d.aux,
						ascii(substring("<<<<<<<<<<<<<<?",
						2*(d.ss_dtype%35+1)+2-8/c.length,
						1))-60))
					else
						convert(smallint, null)
				end,
		DATETIME_PRECISION = case 
					when c.type in (58, 61, 123, 147, 111) then
						isnull(convert(int, c.scale), 
					        convert(int, d.numeric_scale)) +
						convert(int, isnull(d.aux,
						ascii(substring("<<<<<<<<<<<<<<?",
						2*(d.ss_dtype%35+1)+2-8/c.length,
						1))-60))				
					else
						convert(int, null)
				     end,
		CHARACTER_SET_CATALOG = null,
		CHARACTER_SET_SCHEMA = null, 
		CHARACTER_SET_NAME = null,
		COLLATION_CATALOG = null,
		COLLATION_SCHEMA = null,
		COLLATION_NAME = null,
		DOMAIN_CATALOG = null,
		DOMAIN_SCHEMA = null,
		DOMAIN_NAME = null,
		DESCRIPTION  = null,
		tds_type = c.type,
		id = c.id,
		col_len = c.length

	FROM
		syscolumns c,
		sysobjects o,
		sybsystemprocs.dbo.spt_datatype_info d,
		systypes t,
		sybsystemprocs.dbo.spt_sybdrv m
	WHERE
		o.name like @table_name
		AND user_name(o.uid) like @table_owner
		AND o.id = c.id
		/*
		** We use syscolumn.usertype instead of syscolumn.type
		** to do join with systypes.usertype. This is because
		** for a column which allows null, type stores its
		** Server internal datatype whereas usertype still
		** stores its user defintion datatype.  For an example,
		** a column of type 'decimal NULL', its usertype = 26,
		** representing decimal whereas its type = 106 
		** representing decimaln. nullable in the select list
		** already tells user whether the column allows null.
		** In the case of user defining datatype, this makes
		** more sense for the user.
		*/
		AND c.usertype = t.usertype
		/*
		** We need a equality join with 
		** sybsystemprocs.dbo.spt_datatype_info here so that
		** there is only one qualified row returned from 
		** sybsystemprocs.dbo.spt_datatype_info, thus avoiding
		** duplicates.
		*/
		AND t.type = d.ss_dtype
		AND c.name like @column_name
		AND o.type != 'P'
		AND c.name like @column_name
--	AND (d.ss_dtype NOT IN (111, 109, 38, 110) /* No *N types */
 	AND (d.ss_dtype NOT IN (111, 109, 38, 110, 68) /* No *N types */

			OR c.usertype >= 100) /* User defined types */
		AND m.type_name = 
		rtrim(substring(d.type_name,
		1+isnull(d.aux,
		ascii(substring("III<<<MMMI<<A<A",
		2*(d.ss_dtype%35+1)+2-8/c.length,
		1))-60), 18))

	ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
end

SelectClause:
 
 /*  usertype 3 (binary) , 80 (timestamp) */
 UPDATE #results_table set COLUMN_FLAGS = 112 where usertype in (3)
 UPDATE #results_table set DATA_TYPE = 4 where DATA_TYPE = 5 and tds_type = 59
 UPDATE #results_table set DATA_TYPE = 4 where DATA_TYPE = 5 and col_len = 4
 UPDATE #results_table set COLUMN_FLAGS = 112 where COLUMN_FLAGS = 96 and usertype = 1 and DATA_TYPE = 129
 UPDATE #results_table set COLUMN_FLAGS = 112 where COLUMN_FLAGS = 96 and usertype = 34 and DATA_TYPE = 130
 UPDATE #results_table set COLUMN_FLAGS = 112 where COLUMN_FLAGS = 96 and usertype = 24 and DATA_TYPE = 129
 UPDATE #results_table set COLUMN_FLAGS = 112 where COLUMN_FLAGS = 16 and tds_type = 62 and DATA_TYPE = 5
 UPDATE #results_table set COLUMN_FLAGS = 112 where COLUMN_FLAGS = 16 and tds_type = 59 and DATA_TYPE = 4
 if(@is_ado = 1)
 begin
 select TABLE_CATALOG,
 	TABLE_SCHEMA ,
 	TABLE_NAME ,
 	COLUMN_NAME,
 	COLUMN_GUID,
 	COLUMN_PROPID,
 	ORDINAL_POSITION ,
 	COLUMN_HASDEFAULT,
 	COLUMN_DEFAULT,
 	COLUMN_FLAGS,
-- 	USERTYPE = usertype,
         IS_NULLABLE ,
 	DATA_TYPE ,
 	--TYPE_NAME,
 	TYPE_GUID ,
 	CHARACTER_MAXIMUM_LENGTH ,
        	CHARACTER_OCTET_LENGTH ,
 	NUMERIC_PRECISION ,
 --	NUMERIC_PRECISION_RADIX,
 	NUMERIC_SCALE ,
 	DATETIME_PRECISION ,
 	CHARACTER_SET_CATALOG ,
 	CHARACTER_SET_SCHEMA ,
 	CHARACTER_SET_NAME,
 	COLLATION_CATALOG,
 	COLLATION_SCHEMA,
 	COLLATION_NAME,
 	DOMAIN_CATALOG,
 	DOMAIN_SCHEMA ,
 	DOMAIN_NAME,
 	DESCRIPTION
-- 	TDSTYPE = tds_type,
-- 	COLID = id,
--	COLLEN = col_len
 	
 	FROM
 	#results_table 
 	order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION
 
 end
 else
 if(@is_ado = 2)
 begin
 select TABLE_CATALOG,
 	TABLE_SCHEMA ,
 	TABLE_NAME ,
 	COLUMN_NAME,
 	COLUMN_GUID,
 	COLUMN_PROPID,
 	ORDINAL_POSITION ,
 	COLUMN_HASDEFAULT,
 	COLUMN_DEFAULT,
 	COLUMN_FLAGS,
-- 	USERTYPE = usertype,
   	IS_NULLABLE ,
 	--DATA_TYPE ,
 	TYPE_NAME, 
 	TYPE_GUID ,
 	CHARACTER_MAXIMUM_LENGTH ,
        	CHARACTER_OCTET_LENGTH ,
 	NUMERIC_PRECISION ,
 	NUMERIC_PRECISION_RADIX,
 	NUMERIC_SCALE ,
 	DATETIME_PRECISION ,
 	CHARACTER_SET_CATALOG ,
 	CHARACTER_SET_SCHEMA ,
 	CHARACTER_SET_NAME,
 	COLLATION_CATALOG,
 	COLLATION_SCHEMA,
 	COLLATION_NAME,
 	DOMAIN_CATALOG,
 	DOMAIN_SCHEMA ,
 	DOMAIN_NAME,
 	DESCRIPTION
-- 	TDSTYPE = tds_type,
-- 	COLID = id,
--	COLLEN = col_len
 	
 	FROM
 	#results_table 
 	order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION
    end
    
    drop table #results_table
    if (@startedInTransaction = 1)
	rollback transaction oledb_keep_temptable_tx      

return(0)
go
exec sp_procxmode 'sp_oledb_columns', 'anymode'
go
grant execute on sp_oledb_columns to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

/* ----------------ColumnPrivileges ------------------------------*/

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_getcolumnprivileges')
begin
	drop procedure sp_oledb_getcolumnprivileges
end
go


/* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */

create procedure sp_oledb_getcolumnprivileges ( 
                        @table_name  varchar(771) = null,
                        @table_owner varchar(32) = null,
                        @table_qualifier varchar(32)= null,
                        @column_name varchar(771) = null,
                        @grantor varchar(32) = null,
                        @grantee varchar(32) = null)

as        

    declare @owner_id    		int
    declare @full_table_name    	varchar(1543)
    declare @tab_id 			int	    /* object id of the table specified */
    declare @startedInTransaction bit
    if (@@trancount > 0)
  	select @startedInTransaction = 1
    else
        select @startedInTransaction = 0

    set nocount on
    /*
    ** set the transaction isolation level
    */
    if @@trancount = 0
    begin
	   set chained off
    end


    set transaction isolation level 1
    if (@startedInTransaction = 1)
	save transaction oledb_keep_temptable_tx    

    /*
    **  Check to see that the table is qualified with database name
    */
    if @table_name like "%.%.%"   /*CT: oledb can be null */
    begin
		/* 18021, "Object name can only be qualified with owner name" */
		raiserror 18021
		return (1)
    end

    /*  If this is a temporary table; object does not belong to 
    **  this database; (we should be in our temporary database)
    */
    if (@table_name like "#%" and db_name() != 'tempdb')  /*CT: tempdb*, use template*/
    begin
		/* 
		** 17676, "This may be a temporary object. Please execute 
		** procedure from your temporary database."
		*/
		raiserror 17676
		return (1)
    end

    /*
    ** The table_qualifier should be same as the database name. Do the sanity check
    ** if it is specified
    */
    if (@table_qualifier is null) or (@table_qualifier = '')
	/* set the table qualifier name */
	select @table_qualifier = db_name ()
   
   /* 
    ** if the table owner is not specified, it will be taken as the id of the
    ** user executing this procedure. Otherwise find the explicit table name prefixed
    ** by the owner id
    */
    if (@table_owner is null) or (@table_owner = '')
	        select @full_table_name = @table_name
    else
    begin
	if (@table_name like "%.%") and
	    substring (@table_name, 1, charindex(".", @table_name) -1) != @table_owner
	begin
	 	/* 18011, Object name must be qualified with the owner name * */
		raiserror 18011
		return (1)
	end
	
	if not (@table_name like "%.%")
        	select @full_table_name = @table_owner + '.' + @table_name
	else
	        select @full_table_name = @table_name

    end

   /* Create temp table to store results from sp_aux_computeprivs */
    create table #results_table
	 (table_qualifier	varchar (32),
	  table_owner		varchar (32),
	  table_name		varchar (255),
	  column_name		varchar (255) NULL,
	  grantor		varchar (32),
	  grantee 		varchar (32),
	  privilege		varchar (32),
	  is_grantable		varchar (3))
	  
    /*
    ** if the column name is not specified, set the column name to wild 
	** character such it matches all the columns in the table
    */
    if @column_name is null
        select @column_name = '%'	  
    /* 
    ** check to see if the specified table exists or not
    */
    select @tab_id = object_id(@full_table_name)
 
    if (@tab_id is not null)
	begin
	
	    /*
	    ** check to see if the @tab_id indeeed represents a table or a view
	    */

	    if exists (select * 
			  from   sysobjects
			  where (@tab_id = id) and
				((type = 'U') or
				(type = 'S') or
				(type = 'V')))
    	begin
         /*
	 ** check to see if the specified column is indeed a column belonging
	 ** to the table
	 */
         if exists (select * 
                        from syscolumns
			where (id = @tab_id) and
			      (name like @column_name))
	begin

   /*
   ** declare cursor to cycle through all possible columns
   */
   declare cursor_columns cursor
	for select name from syscolumns 
	    where (id = @tab_id) 
	      and (name like @column_name)

   /*
   ** For each column in the list, generate privileges
   */
   open cursor_columns
   fetch cursor_columns into @column_name
   while (@@sqlstatus = 0)
   begin

	/* 
	** compute the table owner id
	*/

	select @owner_id = uid
	from   sysobjects
	where  id = @tab_id


	/*
	** get table owner name
	*/

	select @table_owner = name 
	from sysusers 
	where uid = @owner_id
			     
	/*exec sp_aux_computeprivs @table_name, @table_owner, @table_qualifier, 
			     @column_name, 1, @tab_id */

	exec sp_oledb_computeprivs @table_name, @table_owner, @table_qualifier, 
			     @column_name, 1, @tab_id
			     
	set nocount off 	

	fetch cursor_columns into @column_name
   end

   close cursor_columns
   deallocate cursor cursor_columns
   end
   end
   end

   /* Print out results */ 

  if (@grantor is null) and (@grantee is null)
   select distinct GRANTOR = r.grantor,
   		   GRANTEE = r.grantee,
   		   TABLE_CATALOG = r.table_qualifier,
   		   TABLE_SCHEMA = r.table_owner,
   		   TABLE_NAME = r.table_name,
   		   COLUMN_NAME = r.column_name,
   		   COLUMN_GUID = convert(varchar(36), null),
   		   COLUMN_PROPID = convert(int,null),
   		   PRIVILEGE_TYPE = case when r.privilege = 'REFERENCE' then "REFERENCES"
      		        else r.privilege end,
		   IS_GRANTABLE = case when r.is_grantable = 'YES' then convert(bit, 1)
			else convert (bit, 0) end
   from #results_table r
   order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, PRIVILEGE_TYPE
  else
    if @grantee is null
      select distinct GRANTOR = r.grantor,
      		   GRANTEE = r.grantee,
      		   TABLE_CATALOG = r.table_qualifier,
      		   TABLE_SCHEMA = r.table_owner,
      		   TABLE_NAME = r.table_name,
      		   COLUMN_NAME = r.column_name,
      		   COLUMN_GUID = convert(varchar(36), null),
      		   COLUMN_PROPID = convert(int,null),
      		   PRIVILEGE_TYPE = case when r.privilege = 'REFERENCE' then "REFERENCES"
      		        else r.privilege end,
		   IS_GRANTABLE = case when r.is_grantable = 'YES' then convert(bit, 1)
			else convert (bit, 0) end
      from #results_table r where r.grantor = @grantor
   order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, PRIVILEGE_TYPE
   else
     if @grantor is null
           select distinct GRANTOR = r.grantor,
           		   GRANTEE = r.grantee,
           		   TABLE_CATALOG = r.table_qualifier,
           		   TABLE_SCHEMA = r.table_owner,
           		   TABLE_NAME = r.table_name,
           		   COLUMN_NAME = r.column_name,
           		   COLUMN_GUID = convert(varchar(36), null),
           		   COLUMN_PROPID = convert(int,null),
           		   PRIVILEGE_TYPE = case when r.privilege = 'REFERENCE' then "REFERENCES"
      		                else r.privilege end,
   		           IS_GRANTABLE = case when r.is_grantable = 'YES' then convert(bit, 1)
   		   		else convert (bit, 0) end
           from #results_table r where r.grantee = @grantee
   order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, PRIVILEGE_TYPE
     else
           select distinct GRANTOR = r.grantor,
           		   GRANTEE = r.grantee,
           		   TABLE_CATALOG = r.table_qualifier,
           		   TABLE_SCHEMA = r.table_owner,
           		   TABLE_NAME = r.table_name,
           		   COLUMN_NAME = r.column_name,
           		   COLUMN_GUID = convert(varchar(36), null),
           		   COLUMN_PROPID = convert(int,null),
           		   PRIVILEGE_TYPE = case when r.privilege = 'REFERENCE' then "REFERENCES"
      		                else r.privilege end,
   		           IS_GRANTABLE = case when r.is_grantable = 'YES' then convert(bit, 1)
   		   		else convert (bit, 0) end
           from #results_table r where r.grantor = @grantor and r.grantee = @grantee
   order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, PRIVILEGE_TYPE  

drop table #results_table
if (@startedInTransaction = 1)
   save transaction oledb_keep_temptable_tx    
   
return (0)
go
exec sp_procxmode 'sp_oledb_getcolumnprivileges', 'anymode'
go
grant execute on sp_oledb_getcolumnprivileges to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


/* -------------Catalog -----------------------------*/
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_databases')
begin
	drop procedure sp_oledb_databases
end
go


/* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */

create procedure sp_oledb_databases (@database_name varchar(32) = null)
as
	if @@trancount = 0
	begin
		set chained off
	end

	set transaction isolation level 1

    if @database_name is null	
    begin
	select CATALOG_NAME = name,
		DESCRIPTION = convert(varchar(254),null)  /*no description*/
	from master.dbo.sysdatabases order by name
    end
    else
    begin
	select CATALOG_NAME = name,
		DESCRIPTION = convert(varchar(254),null)  /*no description*/
	from master.dbo.sysdatabases where name = @database_name
	order by name
    end
    
	return(0)
go
go
exec sp_procxmode 'sp_oledb_databases', 'anymode'
go
grant execute on sp_oledb_databases to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


/*-----------------------VIEW------------------------------------------*/
if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_oledb_views')
begin
	drop procedure sp_oledb_views
end
go

create procedure sp_oledb_views
@table_catalog	 	varchar(32)  = null,
@table_schema     	varchar(32)  = null,
@table_name		varchar(771)  = null
as

declare @type1 varchar(3)
declare @tableindex int
declare @startedInTransaction bit
if (@@trancount > 0)
   select @startedInTransaction = 1
else
   select @startedInTransaction = 0

 
if @@trancount = 0
begin
	set chained off
end

set transaction isolation level 1
if (@startedInTransaction = 1)
    save transaction oledb_keep_temptable_tx    

/* temp table */
if (@table_name like "#%" and
   db_name() != db_name(tempdb_id()))
begin
	/*
        ** Can return data about temp. tables only in tempdb
        */
		raiserror 17676
	return(1)
end

create table #oledb_results_table
	 (
	  TABLE_CATALOG		varchar (32) null,
	  TABLE_SCHEMA		varchar (32) null,
	  TABLE_NAME		varchar (255) null,
	  VIEW_DEFINITION       varchar (255) null,
	  CHECK_OPTION          bit default 1,
	  IS_UPDATABLE          bit default 0,
	  DESCRIPTION		varchar(255) null,
	  DATE_CREATED		datetime null,
	  DATE_MODIFIED		datetime null
	 )

/*
** Special feature #1:	enumerate databases when owner and name
** are blank but qualifier is explicitly '%'.  
*/
if @table_catalog = '%' and
	@table_schema = '' and
	@table_name = ''
begin	

	/*
	** If enumerating databases 
	*/
	insert #oledb_results_table
	select
		TABLE_CATALOG = name,
		TABLE_SCHEMA = null,
		TABLE_NAME = null,
		VIEW_DEFINITION = convert(varchar(255), null),
		CHECK_OPTION = 1,
		IS_UPDATABLE = 0,
		DESCRIPTION = convert(varchar(255), null),
		DATE_CREATED = convert(datetime, null),
	  	DATE_MODIFIED = convert(datetime, null)
		
		from master..sysdatabases

		/*
		** eliminate MODEL database 
		*/
		where name != 'model'
		order by TABLE_CATALOG
end

/*
** Special feature #2:	enumerate owners when qualifier and name
** are blank but owner is explicitly '%'.
*/
else if @table_catalog = '' and
	@table_schema = '%' and
	@table_name = ''
	begin	

		/*
		** If enumerating owners 
		*/
		insert #oledb_results_table
		select distinct			
			TABLE_CATALOG = null,
			TABLE_SCHEMA = user_name(uid),
			TABLE_NAME = null,
			VIEW_DEFINITION = convert(varchar(255), null),
			CHECK_OPTION = 1,
			IS_UPDATABLE = 0,
			DESCRIPTION = convert(varchar(255), null),
			DATE_CREATED = convert(datetime, null),
			DATE_MODIFIED = convert(datetime, null)		

		from sysobjects
		order by TABLE_SCHEMA
	end
	else
	begin 

		/*
		** end of special features -- do normal processing 
		*/
		if @table_catalog is not null
	
begin
			if db_name() != @table_catalog
			begin
				if @table_catalog = ''
				begin  	

					/*
					** If empty qualifier supplied
					** Force an empty result set 
					*/
					select @table_name = ''
					select @table_schema = ''
				end
				else
				begin

					/*
					** If qualifier doesn't match current 
					** database. 
					*/
					raiserror 18039
					return 1
				end
			end
		end	

		select @type1 = 'V'

		if @table_name is null
	
		begin	

			/*
			** If table name not supplied, match all 
			*/
			select @table_name = '%'
		end
		else
		begin
			if (@table_schema is null) and 
			   (charindex('%', @table_name) = 0)
			begin	

			/*
			** If owner not specified and table is specified 
			*/
				if exists (select * from sysobjects
					where uid = user_id()
					and id = object_id(@table_name)
					and type = 'V')
				begin	

				/*
				** Override supplied owner w/owner of table 
				*/
					select @table_schema = user_name()
				end
			end
		end

		/*
		** If no owner supplied, force wildcard 
		*/
		if @table_schema is null 
		 select @table_schema = '%'
		insert #oledb_results_table
		select
			TABLE_CATALOG = db_name(),
			TABLE_SCHEMA = user_name(o.uid),
			TABLE_NAME = o.name,
			VIEW_DEFINITION = convert(varchar(255), null),
			CHECK_OPTION = 1,
			IS_UPDATABLE = 0,
			DESCRIPTION = convert(varchar(255), null),
			DATE_CREATED = convert(datetime, null),
			DATE_MODIFIED = convert(datetime, null)		
		from sysusers u, sysobjects o
		where
			/* Special case for temp. tables.  Match ids */
			(o.name like @table_name or o.id=object_id(@table_name))
			and user_name(o.uid) like @table_schema

			/*
			** Only desired types
			*/
			and charindex(substring(o.type,1,1),@type1)! = 0 

			/*
			** constrain sysusers uid for use in subquery 
			*/
			and u.uid = user_id() 
		and (
                suser_id() = 1          /* User is the System Administrator */
                or o.uid = user_id()    /* User created the object */
                                        /* here's the magic..select the highest
                                        ** precedence of permissions in the
                                        ** order (user,group,public)
                                        */
 
                /*
                ** The value of protecttype is
                **
                **      0  for grant with grant
                **      1  for grant and,
                **      2  for revoke
                **
                ** As protecttype is of type tinyint, protecttype/2 is
                ** integer division and will yield 0 for both types of
                ** grants and will yield 1 for revoke, i.e., when
                ** the value of protecttype is 2.  The XOR (^) operation
                ** will reverse the bits and thus (protecttype/2)^1 will
                ** yield a value of 1 for grants and will yield a
                ** value of zero for revoke.
                **
	        ** For groups, uid = gid. We shall use this to our advantage.
                **
                ** If there are several entries in the sysprotects table
                ** with the same Object ID, then the following expression
                ** will prefer an individual uid entry over a group entry
                **
                ** For example, let us say there are two users u1 and u2
                ** with uids 4 and 5 respectiveley and both u1 and u2
                ** belong to a group g12 whose uid is 16390.  table t1
                ** is owned by user u0 and user u0 performs the following
                ** actions:
                **
                **      grant select on t1 to g12
                **      revoke select on t1 from u1
                **
                ** There will be two entries in sysprotects for the object t1,
                ** one for the group g12 where protecttype = grant (1) and
                ** one for u1 where protecttype = revoke (2).
                **
                ** For the group g12, the following expression will
                ** evaluate to:
                **
                **      ((abs(16390-16390)*2) + ((1/2)^1)
                **      = ((0) + (0)^1) = 0 + 1 = 1
                **
                ** For the user entry u1, it will evaluate to:
                **
                **      (((+)*abs(4-16390)*2) + ((2/2)^1))
                **      = (abs(-16386)*2 + (1)^1)
                **      = 16386*2 + 0 = 32772
                **
                ** As the expression evaluates to a bigger number for the
                ** user entry u1, select max() will chose 32772 which,
                ** ANDed with 1 gives 0, i.e., sp_oledb_tables will not display
                ** this particular table to the user.
                **
                ** When the user u2 invokes sp_oledb_tables, there is only one
                ** entry for u2, which is the entry for the group g12, and
                ** so the group entry will be selected thus allowing the
                ** table t1 to be displayed.
                **
		** ((select max((abs(uid-u.gid)*2)
	        ** 		+ ((protecttype/2)^1))
         	**
                ** Notice that multiplying by 2 makes the number an
                ** even number (meaning the last digit is 0) so what
                ** matters at the end is (protecttype/2)^1.
                **
                **/
 
                or ((select max((abs(p.uid-u2.gid)*2) + ((p.protecttype/2)^1))
                        from sysprotects p, sysusers u2
                        where p.id = o.id      /* outer join to correlate
                                                ** with all rows in sysobjects
                                                */
			and u2.uid = user_id()
			/*
			** get rows for public, current users, user's groups
			*/
		      	and (p.uid = 0 or 		/* public */
			     p.uid = user_id() or	/* current user */ 
			     p.uid = u2.gid)		/* users group */ 

			/*
			** check for SELECT, EXECUTE privilege.
			*/
		 	and (p.action in (193,224)))&1

			/*
			** more magic...normalise GRANT
			** and final magic...compare
			** Grants.
			*/
			) = 1
		/*
			** If one of any user defined roles or contained roles for the
			** user has permission, the user has the permission
			*/
			or exists(select 1
				from sysprotects p1,
					master.dbo.syssrvroles srvro,
					sysroles ro
				where p1.id = o.id
				and p1.uid = ro.lrid
				and ro.id = srvro.srid
		and has_role(srvro.name, 1) > 0
				and p1.action = 193))
		
		order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
end
	select * from #oledb_results_table
	
drop table #oledb_results_table
if (@startedInTransaction = 1)
    rollback transaction oledb_keep_temptable_tx    

return (0)
go
exec sp_procxmode 'sp_oledb_views', 'anymode'
go
grant execute on sp_oledb_views to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

print ""
go
print "Installed oledb_mda Stored Procedures ..."
go
declare @retval int
declare @version_string varchar(255) 
select @version_string = '15.0.0.346/'+ 'Fri 01-16-2009 17:45:38.79' 
exec @retval = sp_version 'OLEDB MDA Scripts', NULL, @version_string, 'end'
if (@retval != 0) select syb_quit()
go
go
dump transaction sybsystemprocs with truncate_only
go
dump transaction master to diskdump with truncate_only
go
exec sp_hidetext @objname = "sp_hidetext"
go
exec sp_hidetext @objname = "sp_aux_text"
go
use master
go
dump transaction master to diskdump with truncate_only
go
update index statistics sysmessages
go
dump transaction master to diskdump with truncate_only
go
sp_configure "allow updates", 0
go
if exists (select 1
	from tempdb.dbo.sysobjects
		where name = 'ha_temp_install'
		and type = 'U')
drop table tempdb.dbo.ha_temp_install
go
use sybsystemprocs
go
if exists (select 1
	from sysobjects
		where name = 'sp_ha_check_certified'
		and type = 'P')
exec sp_procxmode 'sp_ha_check_certified', 'anymode'
go
if exists (select 1
	from sysobjects
		where name = 'sp_is_valid_user'
		and type = 'P')
exec sp_procxmode 'sp_is_valid_user', 'dynamic'
go
if exists (select 1
	from sysobjects
		where name = 'sp_encryption'
		and type = 'P')
exec sp_procxmode 'sp_encryption', 'dynamic'
go
if exists (select 1
	from sysobjects
		where name = 'sp_showtext'
		and type = 'P')
exec sp_procxmode 'sp_showtext', 'dynamic'
go
use master
go
set proc_return_status ON
go
print 'Loading of master database is complete.'
go

declare @retval int
exec @retval = sp_version 'installmaster', NULL, '15.5/EBF 17340 SMP/P/x86_64/Enterprise Linux/ase155/2391/64-bit/OPT/Mon Nov  9 14:15:35 2009', 'end'
if (@retval != 0) select syb_quit()
go

