/*
**	INSTCAT.SQL
**	Installs catalog stored procedures on the Microsoft SQL Server.
** Copyright Microsoft, Inc. 1994 - 2000
** All Rights Reserved.
*/

/*
INTERNAL NOTE:
When this file is updated, you MUST change the last row inserted into
spt_server_info to be version number of this file.	the convention is
j.nn.bbb, where j is the major version number ('7' now), nn is the minor
version number ('10' now), and bbb is the build number.
insert into spt_server_info
	values (500, 'SYS_SPROC_VERSION', '8.00.bbb')
*/

/****************************************************************************/
/* This portion sets up the ability to perform all the functions in this    */
/* script																	*/
/****************************************************************************/
go
use master
go
dump tran master with no_log
go

set quoted_identifier on
go

if (exists (select * from sysobjects
		where name = 'sp_configure' and type = 'P '))
begin
    execute sp_configure 'update',1
end
reconfigure with override
go

exec sp_MS_upd_sysobj_category 1 /*Capture datetime for use below.*/

go

/*
** If old versions of tables exist, drop them.
*/
if (exists (select * from sysobjects
		where name = 'MSdatatype_info' and type = 'U '))
    drop table MSdatatype_info
go
if (exists (select * from sysobjects
		where name = 'MSdatatype_info_ext' and type = 'U '))
    drop table MSdatatype_info_ext
go
if (exists (select * from sysobjects
		where name = 'MStable_types' and type = 'U '))
	drop table MStable_types
go
if (exists (select * from sysobjects
		where name = 'MSserver_info' and type = 'U '))
    drop table MSserver_info
go
if (exists (select * from sysobjects
		where name = 'spt_table_types' and type = 'U '))
	drop table spt_table_types
go
/*
** If tables or procs already exist, drop them.
*/

if (exists (select * from sysobjects
		where name = 'spt_datatype_info' and type = 'U '))
    drop table spt_datatype_info
go
if (exists (select * from sysobjects
		where name = 'spt_datatype_info_ext' and type = 'U '))
    drop table spt_datatype_info_ext
go
if (exists (select * from sysobjects
		where name = 'sp_add_server_sortinfo' and type = 'P '))
    drop proc sp_add_server_sortinfo
go
if (exists (select * from sysobjects
		where name = 'sp_add_server_sortinfo75' and type = 'P '))
    drop proc sp_add_server_sortinfo75
go
if (exists (select * from sysobjects
		where name = 'spt_server_info' and type = 'U '))
    drop table spt_server_info
go
if (exists (select * from sysobjects
		where name = 'sp_tables' and type = 'P '))
    drop proc sp_tables
go
if (exists (select * from sysobjects
		where name = 'sp_statistics' and type = 'P '))
    drop proc sp_statistics
go
if (exists (select * from sysobjects
		where name = 'sp_columns' and type = 'P '))
    drop proc sp_columns
go
if (exists (select * from sysobjects
		where name = 'sp_fkeys' and type = 'P '))
    drop proc sp_fkeys
go
if (exists (select * from sysobjects
		where name = 'sp_pkeys' and type = 'P '))
    drop proc sp_pkeys
dump tran master with no_log
go

go
if (exists (select * from sysobjects
		where name = 'sp_stored_procedures' and type = 'P '))
    drop proc sp_stored_procedures
go
if (exists (select * from sysobjects
		where name = 'sp_sproc_columns' and type = 'P '))
    drop proc sp_sproc_columns
go
if (exists (select * from sysobjects
		where name = 'sp_table_privileges' and type = 'P '))
    drop proc sp_table_privileges
go
if (exists (select * from sysobjects
		where name = 'sp_column_privileges' and type = 'P '))
	drop proc sp_column_privileges
go
dump tran master with no_log
go
if (exists (select * from sysobjects
		where name = 'sp_server_info' and type = 'P '))
    drop proc sp_server_info
go
if (exists (select * from sysobjects
		where name = 'sp_datatype_info' and type = 'P '))
    drop proc sp_datatype_info
go
if (exists (select * from sysobjects
		where name = 'sp_special_columns' and type = 'P '))
    drop proc sp_special_columns
go
if (exists (select * from sysobjects
		where name = 'sp_databases' and type = 'P '))
	drop proc sp_databases
go
dump tran master with no_log
go
if (exists (select * from sysobjects
		where name = 'sp_ddopen' and type = 'P '))
	drop proc sp_ddopen
go
if (exists (select * from sysobjects
		where name = 'sp_tableswc' and type = 'P '))
	drop proc sp_tableswc
go

if (exists (select * from sysobjects
		where name = 'sp_tablecollations' and type = 'P'))
	drop proc sp_tablecollations
go

if (exists (select * from sysobjects
		where name = 'sp_bcp_dbcmptlevel' and type = 'P'))
	drop proc sp_bcp_dbcmptlevel
go

dump tran master with no_log
go


if (exists (select * from sysobjects
		where name = 'spt_provider_types' and type = 'U '))
	begin
	drop table spt_provider_types
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_catalogs_rowset' and type = 'P '))
	begin
	drop procedure sp_catalogs_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_column_privileges_rowset' and type = 'P '))
	begin
	drop procedure sp_column_privileges_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_columns_rowset' and type = 'P '))
	begin
	drop procedure sp_columns_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_check_constraints_rowset' and type = 'P '))
	begin
	drop procedure sp_check_constraints_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_check_constbytable_rowset' and type = 'P '))
	begin
	drop procedure sp_check_constbytable_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_foreign_keys_rowset' and type = 'P '))
	begin
	drop procedure sp_foreign_keys_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_indexes_rowset' and type = 'P '))
	begin
	drop procedure sp_indexes_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_primary_keys_rowset' and type = 'P '))
	begin
	drop procedure sp_primary_keys_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_procedure_params_rowset' and type = 'P '))
	begin
	drop procedure sp_procedure_params_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_procedures_rowset' and type = 'P '))
	begin
	drop procedure sp_procedures_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_provider_types_rowset' and type = 'P '))
	begin
	drop procedure sp_provider_types_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_schemata_rowset' and type = 'P '))
	begin
	drop procedure sp_schemata_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_statistics_rowset' and type = 'P '))
	begin
	drop procedure sp_statistics_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_tables_rowset' and type = 'P '))
	begin
	drop procedure sp_tables_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_tables_info_rowset' and type = 'P '))
	begin
	drop procedure sp_tables_info_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_tables_info_rowset_64' and type = 'P '))
	begin
	drop procedure sp_tables_info_rowset_64
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_table_constraints_rowset' and type = 'P '))
	begin
	drop proc sp_table_constraints_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_table_privileges_rowset' and type = 'P '))
	begin
	drop proc sp_table_privileges_rowset
	dump tran master with no_log
	end
go
if (exists (select * from sysobjects
		where name = 'sp_linkedservers_rowset' and type = 'P '))
	begin
	drop proc sp_linkedservers_rowset
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_table_statistics_rowset' and type = 'P '))
	begin
	drop proc sp_table_statistics_rowset
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_column_constraints' and type = 'P '))
	begin
	drop proc sp_oledb_column_constraints
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_indexinfo' and type = 'P '))
	begin
	drop proc sp_oledb_indexinfo
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_ro_usrname' and type = 'P '))
	begin
	drop proc sp_oledb_ro_usrname
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_deflang' and type = 'P '))
	begin
	drop proc sp_oledb_deflang
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_defdb' and type = 'P '))
	begin
	drop proc sp_oledb_defdb
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_database' and type = 'P '))
	begin
	drop proc sp_oledb_database
	dump tran master with no_log
	end
go

if (exists (select * from sysobjects
		where name = 'sp_oledb_language' and type = 'P '))
	begin
	drop proc sp_oledb_language
	dump tran master with no_log
	end
go

print 'creating table spt_datatype_info_ext'
go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin	/*	Pre 6.0 server */
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following error.'
	create table spt_datatype_info_ext (
				user_type		smallint	not null,
				CREATE_PARAMS	varchar(32) null,
				AUTO_INCREMENT	smallint null,
				typename		varchar(32))
end
go
if (charindex('6.00', @@version) > 0 or
	charindex('6.50', @@version) > 0 or
	charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
begin	/* 6.0 or later server */
	create table spt_datatype_info_ext (
				user_type		smallint	not null,
				CREATE_PARAMS	varchar(32) null,
				AUTO_INCREMENT	smallint null,
				typename		sysname)	/* from systypes, to avoid xusertype hard-code */
end
go

grant select on spt_datatype_info_ext to public
go


insert into spt_datatype_info_ext
	/* CHAR 	 user_type, create_params, auto_increment */
	values			 (1,	'length' ,0, 'char')

insert into spt_datatype_info_ext
	/* VARCHAR	 user_type, create_params, auto_increment */
	values			 (2,	'max length' ,0, 'varchar')

insert into spt_datatype_info_ext
	/* BINARY	 user_type, create_params, auto_increment */
	values			 (3,	'length' ,0, 'binary')

insert into spt_datatype_info_ext
	/* VARBINARY user_type, create_params, auto_increment */
	values			 (4,	'max length' ,0, 'varbinary')

if	(charindex('6.00', @@version) > 0 or
	 charindex('6.50', @@version) > 0 or
	 charindex('7.00', @@version) > 0 or
	 charindex('8.00', @@version) > 0)
begin	/*	Add 6.0 data types */
	insert into spt_datatype_info_ext
		/* DECIMAL user_type, create_params, auto_increment */
		values			 (26,	'precision,scale' ,0, 'decimal')

	insert into spt_datatype_info_ext
		/* NUMERIC user_type, create_params, auto_increment */
		values			 (25,	'precision,scale' ,0, 'numeric')

	insert into spt_datatype_info_ext
		/* DECIMAL IDENTITY user_type, create_params, auto_increment */
		values			 (26,	'precision' ,1, 'decimal')

	insert into spt_datatype_info_ext
		/* NUMERIC IDENTITY user_type, create_params, auto_increment */
		values			 (25,	'precision' ,1, 'numeric')

end
else	/*	Pre 6.0 server, add SYSNAME create param */
	begin
		insert into spt_datatype_info_ext
			/* SYSNAME	 user_type, create_param, auto_increments */
			values			 (18,	'max length' ,0, 'sysname')

	end
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
go
if (charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
begin	/*	Update usertypes for 8.0 server */
	begin tran
	insert into spt_datatype_info_ext
		/* NCHAR	 user_type, create_params, auto_increment */
		values			 (0,	'length' ,0, 'nchar')

	insert into spt_datatype_info_ext
		/* NVARCHAR	 user_type, create_params, auto_increment */
		values			 (0,	'max length' ,0, 'nvarchar')

	/* SET user_type TO SPHINX VALUES */
	update spt_datatype_info_ext set user_type = xusertype
		from spt_datatype_info_ext e, systypes t where t.name = e.typename

	commit tran
end
go

create unique clustered index datatypeinfoextclust on spt_datatype_info_ext(user_type,AUTO_INCREMENT)
go

print 'creating table spt_datatype_info'
go
if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin	/*	Pre 6.0 server */
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following error.'
	create table spt_datatype_info (
		ss_dtype			tinyint 	not null,
		fixlen				int 		null,		/* datatype len for variable, else null */
		ODBCVer 			tinyint 	null,		/* version if needed, else null */
		TYPE_NAME			varchar(32)	not null,
		DATA_TYPE			smallint	not null,
		data_precision		int 		null,
		numeric_scale		smallint	null,	/* min scale if 6.0 */
		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(32)	null,
		charbin 			tinyint 	null, /* 0 for char/binary types, NULL for all others */
		SQL_DATA_TYPE		smallint	not null,
		SQL_DATETIME_SUB	smallint	null)
end
go
if (charindex('6.00', @@version) > 0 or
	charindex('6.50', @@version) > 0 or
	charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
begin	/* 6.0 or later server */
	create table spt_datatype_info (
		ss_dtype			tinyint 	not null,
		fixlen				int 		null,		/* datatype len for variable, else null */
		ODBCVer 			tinyint 	null,		/* version if needed, else null */
		TYPE_NAME			sysname 	not null,
		DATA_TYPE			smallint	not null,
		data_precision		int 		null,
		numeric_scale		smallint	null,	/* min scale if 6.0 */
		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 	sysname 	null,
		charbin 			tinyint 	null, /* 0 for char/binary types, NULL for all others */
		SQL_DATA_TYPE		smallint	not null,
		SQL_DATETIME_SUB	smallint	null)
end
go

grant select on spt_datatype_info to public
go

/* Get case sensitivity */
if 'A' = 'A' /* create dummy begin block */
begin
	declare @case smallint

	begin tran
	select @case = 0
	select @case = 1 where 'a' <> 'A'

	/* Local Binary */
	insert into spt_datatype_info values
	(45,null,null,'binary',-2,null,null,null,null,'0x',null,'length',1,0,2,null,0,null,'binary',0,-2,null)

	/* Local Bit */
	insert into spt_datatype_info values
	(50,null,null,'bit',-7,1,0,null,1,null,null,null,0,0,2,null,0,null,'bit',null,-7,null)

	/* Local Char */
	insert into spt_datatype_info values
	(47,null,null,'char',1,null,null,null,null,'''','''','length',1,@case,3,null,0,null,'char',0,1,null)

	/* Local Datetime */
	insert into spt_datatype_info values
	(61,8,2,'datetime',11,23,3,NULL,16,'''','''',null,1,0,3,null,0,null,'datetime',null,9,3)
	insert into spt_datatype_info values
	(61,8,3,'datetime',93,23,3,NULL,16,'''','''',null,1,0,3,null,0,null,'datetime',null,9,3)

	/* Local Smalldatetime */
	insert into spt_datatype_info values
	(58,4,2,'smalldatetime',11,16,0,NULL,16,'''','''',null,1,0,3,null,0,null,'smalldatetime',null,9,3)
	insert into spt_datatype_info values
	(58,4,3,'smalldatetime',93,16,0,NULL,16,'''','''',null,1,0,3,null,0,null,'smalldatetime',null,9,3)

	/* Local Float */
	insert into spt_datatype_info values
	(62,8,2,'float',6,15,null,10,8,null,null,null,1,0,2,0,0,0,'float',null,6,null)
	insert into spt_datatype_info values
	(62,8,3,'float',6,53,null, 2,8,null,null,null,1,0,2,0,0,0,'float',null,6,null)

	/* Local Real */
	insert into spt_datatype_info values
	(59,4,2,'real',7, 7,null,10,4,null,null,null,1,0,2,0,0,0,'real',null,7,null)
	insert into spt_datatype_info values
	(59,4,3,'real',7,24,null, 2,4,null,null,null,1,0,2,0,0,0,'real',null,7,null)

	/* Local Smallmoney */
	insert into spt_datatype_info values
	(122,4,null,'smallmoney',3,10,4,10,12,'$',null,null,1,0,2,0,1,0,'smallmoney',null,3,null)

	/* Local Money */
	insert into spt_datatype_info values
	(60,8,null,'money',3,19,4,10,21,'$',null,null,1,0,2,0,1,0,'money',null,3,null)

	/* Local Int */
	insert into spt_datatype_info values
	(56,4,null,'int',4,10,0,10,4,null,null,null,1,0,2,0,0,0,'int',null,4,null)

	commit tran
end
go

if 'A' = 'A' /* create dummy begin block */
begin
	declare @case smallint

	begin tran
	select @case = 0
	select @case = 1 where 'a' <> 'A'


	/* Local Smallint */
	insert into spt_datatype_info values
	(52,2,null,'smallint',5,5,0,10,2,null,null,null,1,0,2,0,0,0,'smallint',null,5,null)
	insert into spt_datatype_info values
	(52,2,1,'smallint',5,5,0,10,2,null,null,null,1,0,2,0,0,0,'smallint',null,5,null)

	/* Local Tinyint */
	insert into spt_datatype_info values
	(48,1,null,'tinyint',-6,3,0,10,1,null,null,null,1,0,2,1,0,0,'tinyint',null,-6,null)

	/* Local Text */
	insert into spt_datatype_info values
	(35,null,null,'text',-1,2147483647,null,null,2147483647,'''','''',null,1,@case,1,null,0,null,'text',0,-1,null)

	/* Local Varbinary */
	insert into spt_datatype_info values
	(37,null,null,'varbinary',-3,null,null,null,null,'0x',null,'max length',1,0,2,null,0,null,'varbinary',0,-3,null)

	/* Local Varchar */
	insert into spt_datatype_info values
	(39,null,null,'varchar',12,null,null,null,null,'''','''','max length',1,@case,3,null,0,null,'varchar',0,12,null)

	/* Local Image */
	insert into spt_datatype_info values
	(34,null,null,'image',-4,2147483647,null,null,2147483647,'0x',null,null,1,0,0,null,0,null,'image',0,-4,null)

	if (charindex('6.00', @@version) > 0 or
		charindex('6.50', @@version) > 0 or
		charindex('7.00', @@version) > 0 or
		charindex('8.00', @@version) > 0)
	begin	/*	Add 6.0 data types */
		/* Local Decimal */
		insert into spt_datatype_info values	/* sql server type is 'decimaln' */
		(55,null,null,'decimal',3,38,0,10,null,null,null,'precision,scale',1,0,2,0,0,0,'decimal',null,3,null)

		/* Local Numeric */
		insert into spt_datatype_info values	/* sql server type is 'numericn' */
		(63,null,null,'numeric',2	,38,0,10,null,null,null,'precision,scale',1,0,2,0,0,0,'numeric',null,2,null)

		/* Identity attribute data types */

		/* Identity Int */
		insert into spt_datatype_info values
		(56,null,null,'int identity',4,10,0,10,null,null,null,null,0,0,2,0,0,1,'int identity',null,4,null)

		/* Identity Smallint */
		insert into spt_datatype_info values
		(52,null,null,'smallint identity',5,5,0,10,null,null,null,null,0,0,2,0,0,1,'smallint identity',null,5,null)

		/* Identity Tinyint */
		insert into spt_datatype_info values
		(48,null,null,'tinyint identity',-6,3,0,10,null,null,null,null,0,0,2,1,0,1,'tinyint identity',null,-6,null)

		/* Identity Numeric */
		insert into spt_datatype_info values	/* sql server type is 'decmaln' */
		(55,null,null,'decimal() identity',3,38,0,10,null,null,null,'precision,scale',0,0,2,0,0,1,'decimal() identity',null,3,null)

		/* Identity Numeric */
		insert into spt_datatype_info values	/* sql server type is 'decmaln' */
		(63,null,null,'numeric() identity',2,38,0,10,null,null,null,'precision,scale',0,0,2,0,0,1,'numeric() identity',null,2,null)

	end

	if (charindex('7.00', @@version) = 0 and
		charindex('8.00', @@version) = 0)
	begin	/*	Add nullable type for non-8.0 server */
		/* Local Datetimn */
		insert into spt_datatype_info values
		(111,4,2,'smalldatetime',11,16,0,10,16,'''','''',null,1,0,3,null,0,null,'smalldatetime',null,9,3)
		insert into spt_datatype_info values
		(111,4,3,'smalldatetime',93,16,0,10,16,'''','''',null,1,0,3,null,0,null,'smalldatetime',null,9,3)
		insert into spt_datatype_info values /* sql server type is 'datetimn' */
		(111,8,2,'datetime',11,23,3,10,16,'''','''',null,1,0,3,null,0,null,'datetime',null,9,3)
		insert into spt_datatype_info values
		(111,8,3,'datetime',93,23,3,10,16,'''','''',null,1,0,3,null,0,null,'datetime',null,9,3)

		/* Local Floatn */
		insert into spt_datatype_info values /* sql server type is 'floatn' */
		(109,4,2,'real',7, 7,null,10,4,null,null,null,1,0,2,0,0,0,'real',null,7,null)
		insert into spt_datatype_info values
		(109,4,3,'real',7,24,null, 2,4,null,null,null,1,0,2,0,0,0,'real',null,7,null)
		insert into spt_datatype_info values /* sql server type is 'floatn' */
		(109,8,2,'float',6,15,null,10,8,null,null,null,1,0,2,0,0,0,'float',null,6,null)
		insert into spt_datatype_info values
		(109,8,3,'float',6,53,null, 2,8,null,null,null,1,0,2,0,0,0,'float',null,6,null)

		/* Local Moneyn */
		insert into spt_datatype_info values	/* sql server type is 'moneyn' */
		(110,4,null,'smallmoney',3,10,4,10,12,'$',null,null,1,0,2,0,1,0,'smallmoney',null,3,null)
		insert into spt_datatype_info values	/* sql server type is 'moneyn' */
		(110,8,null,'money',3,19,4,10,21,'$',null,null,1,0,2,0,1,0,'money',null,3,null)

		/* Local Intn */
		insert into spt_datatype_info values /* sql server type is 'intn' */
		(38,4,null,'int',4,10,0,10,4,null,null,null,1,0,2,0,0,0,'int',null,4,null)
		insert into spt_datatype_info values /* sql server type is 'intn' */
		(38,2,null,'smallint',5,5,0,10,2,null,null,null,1,0,2,0,0,0,'smallint',null,5,null)
		insert into spt_datatype_info values
		(38,1,null,'tinyint',-6,3,0,10,1,null,null,null,1,0,2,1,0,0,'tinyint',null,-6,null)

		if (charindex('6.00', @@version) > 0 or
			charindex('6.50', @@version) > 0 or
			charindex('7.00', @@version) > 0 or
			charindex('8.00', @@version) > 0)
		begin	/*	Add 6.0 data types */
			/* Local Decimaln */
			insert into spt_datatype_info values	/* sql server type is 'decimaln' */
			(106,null,null,'decimal',3,38,0,10,null,null,null,'precision,scale',1,0,2,0,0,0,'decimal',null,3,null)
			insert into spt_datatype_info values	/* sql server type is 'decmaln' */
			(106,null,null,'decimal() identity',3,38,0,10,null,null,null,'precision,scale',0,0,2,0,0,1,'decimal() identity',null,3,null)

			/* Local Numericn */
			insert into spt_datatype_info values	/* sql server type is 'numericn' */
			(108,null,null,'numeric',2,38,0,10,null,null,null,'precision,scale',1,0,2,0,0,0,'numeric',null,2,null)
			insert into spt_datatype_info values	/* sql server type is 'decmaln' */
			(108,null,null,'numeric() identity',2,38,0,10,null,null,null,'precision,scale',0,0,2,0,0,1,'numeric() identity',null,2,null)
		end
	end

	commit tran
end
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
go
if (charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
	begin
		declare @ncase smallint

		select @ncase = 0
		select @ncase = 1 where N'a' <> N'A'

		/* Local Timestamp */
		insert into spt_datatype_info values
		(0,null,null,'timestamp',-2,8,null,null,null,'0x',null,null,1,0,2,null,0,null,'timestamp',0,-2,null)

		/* Local GUID */
		insert into spt_datatype_info values
		(0,null,null,'uniqueidentifier',-11,36,null,null,null,'''','''',null,1,0,2,null,0,null,'uniqueidentifier',NULL,-11,null)

		/* Local NChar */
		insert into spt_datatype_info values
		(0,null,null,'nchar',-8,null,null,null,null,'N''','''','length',1,@ncase,3,null,0,null,'nchar',0,-8,null)

		/* Local NVarchar */
		insert into spt_datatype_info values
		(0,null,null,'nvarchar',-9,null,null,null,null,'N''','''','max length',1,@ncase,3,null,0,null,'nvarchar',0,-9,null)

		/* Local NText */
		insert into spt_datatype_info values
		(0,null,null,'ntext',-10,2147483646,null,null,2147483646,'N''','''',null,1,@ncase,1,null,0,null,'ntext',0,-10,null)

		if (charindex('8.00', @@version) > 0)
		begin
--			/* Local BIGINT */
			insert into spt_datatype_info values
			(127,8,null,'bigint',-5,19,0,10,null,null,null,null,1,0,2,0,0,0,'bigint',null,-5,null)
--			/* Identity BIGINT */
			insert into spt_datatype_info values
			(127,8,null,'bigint identity',-5,19,0,10,null,null,null,null,0,0,2,0,0,1,'bigint identity',null,-5,null)


--			/* sql_variant */
			insert into spt_datatype_info values
			(
			98,					--ss_dtype		
			null,				--fixlen
			null,				--ODBCVer
			'sql_variant',		--TYPE_NAME
			-150,				--SQL DATA TYPE
			8000,				--data_precision
			0,				    --numeric_scale
			10,					--RADIX
			8000,				--length
			null,				--PREFIX
			null,				--SUFFIX
			null,				--Create Params
			1,					--Nullable
			0,				--Case sensitive
			2,					--Searchable
			null,				--UNSIGNED_ATTRIBUTE
			0,				--MONEY
			null,				--AUTO_INCREMENT
			'sql_variant',		--LOCAL TYPE NAME
			0,					--CHARBIN
			-150,				--SQL_DATA_TYPE
			null				--SQL_DATETIME_SUB
			)
		
		end



		update spt_datatype_info set NULLABLE = 1
			where TYPE_NAME = 'bit'

		update spt_datatype_info set ss_dtype = isnull((select distinct xtype from systypes
			where TYPE_NAME like name+'%'),0)
	end
go

create unique clustered index datatypeinfoclust on spt_datatype_info(ss_dtype,fixlen,ODBCVer,AUTO_INCREMENT)
go

dump tran master with no_log
go

print 'creating table spt_server_info'
go
create table spt_server_info (
			  attribute_id		int NOT NULL,
			  attribute_name	varchar(60) NOT NULL,
			  attribute_value	varchar(255) NOT NULL)
go

create unique clustered index serverinfoclust on spt_server_info(attribute_id)
go

if (charindex('7.00', @@version) = 0 and charindex('8.00', @@version) = 0)
	begin
		drop procedure sp_add_server_sortinfo	/* not used by other servers */
		drop procedure sp_add_server_sortinfo75	/* not used by older servers */
		dump tran master with no_log
	end
go


insert into spt_server_info
	values (1,'DBMS_NAME','Microsoft SQL Server')
insert into spt_server_info
	values (2,'DBMS_VER',@@version)
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 (13,'TABLE_LENGTH','30')
insert into spt_server_info
	values (14,'MAX_QUAL_LENGTH','30')
insert into spt_server_info
	values (15,'COLUMN_LENGTH','30')
if 'A' = 'a' /* If not case sensitive server */
begin
	insert into spt_server_info
		values (16,'IDENTIFIER_CASE','MIXED')
end
else
begin
	insert into spt_server_info
		values (16,'IDENTIFIER_CASE','SENSITIVE')
end
insert into spt_server_info
	values (17,'TX_ISOLATION','2')
if (charindex('6.00', @@version) > 0 or
	charindex('6.50', @@version) > 0 or
	charindex('7.00', @@version) > 0) 
begin	/*	Add 6.0 collation sequence */
	insert into spt_server_info
		select 18,'COLLATION_SEQ',
			'charset='+t2.name+' sort_order='+t1.name
			+' charset_num='+rtrim(convert(char(4),t1.csid))+
			' sort_order_num='+rtrim(convert(char(4),t1.id))
		from syscharsets t1, syscharsets t2, sysconfigures t3
		where t1.csid=t2.id and t1.id=t3.value and t3.config=1123
end
else 
begin	/*	Add 4.2x collation sequence */
	insert into spt_server_info
		select 18,'COLLATION_SEQ',
			'charset='+t2.name+' sort_order='+t1.name
			+' charset_num='+rtrim(convert(char(4),t1.csid))+
			' sort_order_num='+rtrim(convert(char(4),t1.id))
		from syscharsets t1, syscharsets t2, sysconfigures t3
		where t1.csid=t2.id and t1.id=t3.value and t3.config=123
end
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 (22,'ACCESSIBLE_TABLES','Y')
go

insert into spt_server_info
	values (100,'USERID_LENGTH','30')
insert into spt_server_info
	values (101,'QUALIFIER_TERM','database')
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 (104,'ACCESSIBLE_SPROC','Y')
insert into spt_server_info
	values (105,'MAX_INDEX_COLS','16')
insert into spt_server_info
	values (106,'RENAME_TABLE','Y')
insert into spt_server_info
	values (107,'RENAME_COLUMN','Y')

if (charindex('8.00', @@version) > 0)
begin
	/* Columns may be dropped on 8.0 or later */
	insert into spt_server_info
		values (108,'DROP_COLUMN','Y')
end
else
begin
	insert into spt_server_info
		values (108,'DROP_COLUMN','N')
end

if (charindex('8.00', @@version) > 0)
begin
	/* Columns size may be changed on 8.0 or later */
	insert into spt_server_info
		values (109,'INCREASE_COLUMN_LENGTH','Y')
end
else
begin
	insert into spt_server_info
		values (109,'INCREASE_COLUMN_LENGTH','N')
end

if (charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	insert into spt_server_info
		values (110,'DDL_IN_TRANSACTION','N')
end
else
begin
	insert into spt_server_info
		values (110,'DDL_IN_TRANSACTION','Y')
end


if (charindex('8.00', @@version) > 0)
begin
	/* Descending indexes allowed on 8.0 or later */
	insert into spt_server_info
		values (111,'DESCENDING_INDEXES','Y')
end
else
begin
	insert into spt_server_info
		values (111,'DESCENDING_INDEXES','N')
end

insert into spt_server_info
	values (112,'SP_RENAME','Y')
insert into spt_server_info
	values (113,'REMOTE_SPROC','Y')
insert into spt_server_info
	values (500,'SYS_SPROC_VERSION','8.00.707')
go

if (charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
begin	/*	Update values for 8.0 server */
	update spt_server_info set attribute_value = '128'
		where attribute_id in (12,13,14,15,100)
end
go

grant select on spt_server_info to public
go

print 'creating sp_column_privileges'
go

/*	Procedure for pre 6.50 server */
CREATE PROCEDURE sp_column_privileges (
			@table_name 		varchar(32),
			@table_owner		varchar(32) = null,
			@table_qualifier	varchar(32) = null,
			@column_name		varchar(96) = null)	/* 3*32 */
as

	set nocount on
	declare @table_id	 int
	DECLARE @full_table_name	varchar(65)	/* 2*32 + 1 */
	declare @low smallint					 /* range of userids to check */
	declare @high smallint
	declare @owner_uid smallint

    select @low = 0, @high = 32767

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_5~~'
			return
		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 (@@trancount <> 0)
	begin	/* If inside a transaction */
		raiserror 20003 '~~Rush_6~~'
		return
    end

    /*
    ** We need to create a table which will contain a row for every row to
    ** be returned to the client.
    */

	create table #column_priv1(
		COLUMN_NAME 			varchar(32) NOT NULL,
		grantor 				smallint NOT NULL,
		grantee 				smallint NOT NULL,
		select_privilege		bit,
		select_grantable		bit,
		insert_privilege		bit,
		insert_grantable		bit,
		update_privilege		bit,
		update_grantable		bit,
		references_privilege	bit,
		references_grantable	bit,
		uid 					smallint NOT NULL,
		gid 					smallint NOT NULL)

/*
** insert a row for the table owner (who has all permissions)
*/
	select @owner_uid = (
		select uid
		from sysobjects
		where id = @table_id)

	if (charindex('6.00', @@version) > 0)
	begin
		insert into #column_priv1
			select
				c.name,
				u.uid,
				@owner_uid,
				0,
				1,
				0,
				1,
				0,
				1,
				0,
				1,
				@owner_uid,
				0
			from syscolumns c, sysusers u
			where id = @table_id
				and c.number = 0
				and u.uid = 1		/* grantor is dbo of database */
	end
	else
	begin
		insert into #column_priv1
			select
				c.name,
				u.uid,
				@owner_uid,
				0,
				1,
				0,
				1,
				0,
				1,
				0,
				0,
				@owner_uid,
				0
			from syscolumns c, sysusers u
			where id = @table_id
				and c.number = 0
				and u.uid = 1		/* grantor is dbo of database */
	end
/*
** now stick in a row for every column for every user in the database
** we will need to weed out those who have no permissions later
** (and yes this is a cartesion product: the uid field in sysprotects
** can also have a group id, in which case we need to extend those
** privileges to all group members).
*/

    insert into #column_priv1
		select distinct
			c.name,
			o.uid,
			u.uid,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			u.uid,
			u.gid
		from sysusers u, syscolumns c, sysobjects o
		where o.id = @table_id
			and c.id = o.id
			and c.number = 0
			and u.gid <> u.uid
			and u.uid <> @owner_uid

    /*
    ** we need to create another temporary table to contain all the various
    ** protection information for the table in question
    */
	create table #protects (
				uid 		smallint NOT NULL,
				grantor		smallint NOT NULL,
				action		tinyint NOT NULL,
				protecttype tinyint NOT NULL,
				name		varchar(32) NOT NULL)

    insert into #protects
		select
			p.uid,
			p.uid,
			p.action,
			p.protecttype,
			isnull(col_name(id, c.number), '~All')
			from
				sysprotects p,
				master.dbo.spt_values c,
				master.dbo.spt_values a,
				master.dbo.spt_values b
			where
				convert(tinyint, substring(isnull(p.columns, 0x1), c.low, 1))
					& c.high <> 0
					and c.number <= (
						select count(*)
						from syscolumns
						where id = @table_id)
				and c.type = 'P'
				and a.type = 'T'
				and a.number = p.action
				and p.action in (193,195,197,26)
				and b.type = 'T'
				and b.number = p.protecttype
				and p.id = @table_id
				and p.uid between @low and @high


    update #column_priv1
	set select_privilege = 1
		from #protects p
	where
		p.protecttype = 205
		and p.action = 193
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
			where
				protecttype = 206
				and action = 193
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and ( uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set insert_privilege = 1
		from #protects p
	where
		p.protecttype = 205
		and p.action = 195
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
			where
				protecttype = 206
				and action = 195
				and (name = #column_priv1.COLUMN_NAME
       				or name = '~All')
				and (uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set update_privilege = 1
		from #protects p
	where
		p.protecttype = 205
		and p.action = 197
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
				where protecttype = 206
				and action = 197
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and (uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set references_privilege = 1
		from #protects p
	where
		p.protecttype = 205
		and p.action = 26
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
				where protecttype = 206
				and action = 26
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and (uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set select_grantable = 1
		from #protects p
	where
		p.protecttype = 204
		and p.action = 193
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
			where
				protecttype = 206
				and action = 193
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and ( uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set insert_grantable = 1
		from #protects p
	where
		p.protecttype = 204
		and p.action = 195
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
			where
				protecttype = 206
				and action = 195
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and ( uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set update_grantable = 1
		from #protects p
	where
		p.protecttype = 204
		and p.action = 197
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
			where
				protecttype = 206
				and action = 197
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and ( uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

    update #column_priv1
	set references_grantable = 1
		from #protects p
	where
		p.protecttype = 204
		and p.action = 26
		and (p.name = #column_priv1.COLUMN_NAME
			or name = '~All')
		and (p.uid = 0
			or p.uid = #column_priv1.gid
			or p.uid = #column_priv1.uid)
		and not exists (
			select * from #protects
			where
				protecttype = 206
				and action = 26
				and (name = #column_priv1.COLUMN_NAME
					or name = '~All')
				and ( uid = 0
					or uid = #column_priv1.gid
					or uid = #column_priv1.uid))

	create table #column_priv2(
		COLUMN_NAME 	varchar(32) NOT NULL,
		grantor 		smallint NULL,
		grantee 		smallint NOT NULL,
		PRIVILEGE		varchar(32) NOT NULL,
		IS_GRANTABLE	varchar(3) NULL)

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'SELECT',
			'NO'
		from #column_priv1
		where select_privilege = 1 and select_grantable	= 0

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'INSERT',
			'NO'
		from #column_priv1
		where insert_privilege = 1 and insert_grantable = 0

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'UPDATE',
			'NO'
		from #column_priv1
		where update_privilege = 1 and update_grantable = 0

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'REFERENCES',
			'NO'
		from #column_priv1
		where references_privilege = 1 and references_grantable = 0

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'SELECT',
			'YES'
		from #column_priv1
		where select_grantable = 1

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'INSERT',
			'YES'
		from #column_priv1
		where insert_grantable = 1

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'UPDATE',
			'YES'
		from #column_priv1
		where update_grantable = 1

	insert into #column_priv2
		select
			COLUMN_NAME,
			grantor,
			grantee,
			'REFERENCES',
			'YES'
		from #column_priv1
		where references_grantable = 1

	select
		convert(varchar(32),db_name()) TABLE_QUALIFIER,
		convert(varchar(32),user_name(@owner_uid)) TABLE_OWNER,
		@table_name TABLE_NAME,
		COLUMN_NAME,
		convert(varchar(32),user_name(grantor)) GRANTOR,
		convert(varchar(32),user_name(grantee)) GRANTEE,
		PRIVILEGE,
		IS_GRANTABLE
	from #column_priv2
	where COLUMN_NAME like @column_name
	order by 4, 7
go

if (charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.50 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_column_privileges
go

/*	Procedure for 6.50 server */
CREATE PROCEDURE sp_column_privileges (
			@table_name 		varchar(32),
			@table_owner		varchar(32) = null,
			@table_qualifier	varchar(32) = null,
			@column_name		varchar(96) = null)	/* 3*32 */
as

	declare @table_id	 int

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @table_owner is null
	begin	/* If unqualified table name */
		select @table_id = object_id(@table_name)
    end
    else
	begin	/* Qualified table name */
		select @table_id = object_id(@table_owner + '.' + @table_name)
    end

	select
		convert(varchar(32),db_name()) TABLE_QUALIFIER,
		convert(varchar(32),user_name(o.uid)) TABLE_OWNER,
		@table_name TABLE_NAME,
		convert(varchar(32),c.name) COLUMN_NAME,
		convert(varchar(32),user_name(p.grantor)) GRANTOR,
		convert(varchar(32),user_name(u.uid)) GRANTEE,
		convert (varchar(32),case p.action
			 when 193 then 'SELECT'
			 when 195 then 'INSERT'
			 when 197 then 'UPDATE'
			 else 'REFERENCES'
		end) PRIVILEGE,
		convert (varchar(3),case when p.protecttype = 205 then 'NO'
			else 'YES'
		end) IS_GRANTABLE
	from sysprotects p, sysobjects o, sysusers u, master.dbo.spt_values v, syscolumns c
	where
		c.id = @table_id
		and c.name like @column_name
		and c.id = p.id
		and c.id = o.id
		and case substring(p.columns, 1, 1) & 1
				when NULL then 255	/* all columns have permission */
				when 0 then convert(tinyint, substring(p.columns, v.low, 1))
				else (~convert(tinyint, isnull(substring(p.columns, v.low, 1),0)))
			end
			& v.high <> 0			/* permission applies to this column */
		and v.number <= (select count(*) from syscolumns
			where id = @table_id)	/* ranges from 1 to # of columns in table */
		and v.type = 'P'
		and v.number = c.colid
			/* expand groups */
		and ((p.uid = u.uid and u.uid <> u.gid) or
			 (p.uid = u.gid and u.uid <> u.gid))
		and p.protecttype <> 206	/* only grant rows */
		and p.action in (26,193,195,197)
		and o.uid <> u.uid			/* no rows for owner */
		and not exists (			/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = p.action
				and p1.id = p.id
				and p1.uid = u.uid
				and case substring(p1.columns, 1, 1) & 1
						when NULL then 255	/* all columns have permission */
						when 0 then convert(tinyint, substring(p1.columns, v.low, 1))
                                        	else (~convert(tinyint,isnull(substring(p.columns, v.low, 1),0)))
					end
					& v.high <> 0)			/* permission applies to this column */
	union
	select	/*	Add rows for table owner */
		convert(varchar(32),db_name()) TABLE_QUALIFIER,
		convert(varchar(32),user_name(o.uid)) TABLE_OWNER,
		@table_name TABLE_NAME,
		convert(varchar(32),col_name(@table_id, c.colid)) COLUMN_NAME,
		convert(varchar(32),user_name(u.uid)) grantor,
		convert(varchar(32),user_name(o.uid)) grantee,
		convert (varchar(32),case v.number
			when 193 then 'SELECT'
			when 195 then 'INSERT'
			when 197 then 'UPDATE'
			else 'REFERENCES'
		end) PRIVILEGE,
		convert(varchar(3),'YES') IS_GRANTABLE
	from sysobjects o, master.dbo.spt_values v, sysusers u, syscolumns c
	where
		c.id = @table_id
		and c.name like @column_name
		and c.id = o.id
		and u.uid = 1		/* grantor is dbo of database */
		and v.type = 'P'	/* cross product to get all exposed privileges */
		and v.number in (26,193,195,197)
		and not exists (	/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = v.number
				and p1.id = o.id
				and p1.uid = o.uid)
	order by 4, 7
go



if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_column_privileges
go

/*	Procedure for 8.0 server */
CREATE PROCEDURE sp_column_privileges (
			@table_name 		sysname,
			@table_owner		sysname = null,
			@table_qualifier	sysname = null,
			@column_name		nvarchar(384) = null)	/* 3*128 */
as

	declare @table_id	 int

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @table_owner is null
	begin	/* If unqualified table name */
		select @table_id = object_id(quotename(@table_name))
    end
    else
	begin	/* Qualified table name */
		if @table_owner = N''
		begin	/* If empty owner name */
			select @table_id = 0
		end
		else
		begin
			select @table_id = object_id(quotename(@table_owner) +
				'.' + quotename(@table_name))
		end
    end

	select
		convert(sysname,db_name()) TABLE_QUALIFIER,
		convert(sysname,user_name(o.uid)) TABLE_OWNER,
		@table_name TABLE_NAME,
		convert(sysname,c.name) COLUMN_NAME,
		convert(sysname,user_name(p.grantor)) GRANTOR,
		convert(sysname,user_name(u.uid)) GRANTEE,
		convert (varchar(32),case p.action
			 when 193 then 'SELECT'
			 when 195 then 'INSERT'
			 when 197 then 'UPDATE'
			 else 'REFERENCES'
		end) PRIVILEGE,
		convert (varchar(3),case when p.protecttype = 205 then 'NO'
			else 'YES'
		end) IS_GRANTABLE
	from sysprotects p, sysobjects o, sysusers u, master.dbo.spt_values v, syscolumns c, sysmembers m
	where
		c.id = @table_id
		and c.name like @column_name
		and c.id = p.id
		and c.id = o.id
		and case substring(p.columns, 1, 1) & 1
				when NULL then 255	/* all columns have permission */
				when 0 then convert(tinyint, substring(p.columns, v.low, 1))
				else (~convert(tinyint, isnull(substring(p.columns, v.low, 1),0)))
			end
			& v.high <> 0			/* permission applies to this column */
		and v.number <= (select count(*) from syscolumns
			where id = @table_id)	/* ranges from 1 to # of columns in table */
		and v.type = N'P'
		and v.number = c.colid
			/* expand groups - AKUNDONE: only 1 level of group unrolling here. Need more?? */
		and (u.uid > 0 and u.uid < 16384)
		and ((p.uid = u.uid) or 
			 (p.uid = m.groupuid and u.uid = m.memberuid))
		and p.protecttype <> 206	/* only grant rows */
		and p.action in (26,193,195,197)
		and o.uid <> u.uid			/* no rows for owner */
		and not exists (			/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = p.action
				and p1.id = p.id
				and p1.uid = u.uid
				and case substring(p1.columns, 1, 1) & 1
						when NULL then 255	/* all columns have permission */
						when 0 then convert(tinyint, substring(p1.columns, v.low, 1))
                                        	else (~convert(tinyint,isnull(substring(p.columns, v.low, 1),0)))
					end
					& v.high <> 0)			/* permission applies to this column */
	union
	select	/*	Add rows for table owner */
		convert(sysname,db_name()) TABLE_QUALIFIER,
		convert(sysname,user_name(o.uid)) TABLE_OWNER,
		@table_name TABLE_NAME,
		convert(sysname,col_name(@table_id, c.colid)) COLUMN_NAME,
		convert(sysname,user_name(u.uid)) grantor,
		convert(sysname,user_name(o.uid)) grantee,
		convert (varchar(32),case v.number
			when 193 then 'SELECT'
			when 195 then 'INSERT'
			when 197 then 'UPDATE'
			else 'REFERENCES'
		end) PRIVILEGE,
		convert(varchar(3),'YES') IS_GRANTABLE
	from sysobjects o, master.dbo.spt_values v, sysusers u, syscolumns c
	where
		c.id = @table_id
		and c.name like @column_name
		and c.id = o.id
		and u.uid = 1		/* grantor is 'dbo' of database */
		and v.type = N'P'	/* cross product to get all exposed privileges */
		and v.number in (26,193,195,197)
		and not exists (	/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = v.number
				and p1.id = o.id
				and p1.uid = o.uid)
	order by 4, 7
go


grant execute on sp_column_privileges to public
go

dump tran master with no_log
go

print 'creating sp_columns'
go

/*	Procedure for pre-6.0 server */
CREATE PROCEDURE sp_columns (
				 @table_name		varchar(96),
				 @table_owner		varchar(96) = null,
				 @table_qualifier	varchar(32) = null,
				 @column_name		varchar(96) = null,
				 @ODBCVer			int = 2)
AS
	DECLARE @full_table_name varchar(193)
	DECLARE @table_id        int

	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_5~~'
			return
		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 ((charindex('%',@full_table_name) = 0) and
		(charindex('_',@full_table_name) = 0) and
		@table_id <> 0)
	begin
		/* this block is for the case where there is no pattern
			 matching required for the table name */

		SELECT
			TABLE_QUALIFIER = convert(varchar(32),DB_NAME()),
			TABLE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			TABLE_NAME = convert(varchar(32),o.name),
			COLUMN_NAME = convert(varchar(32),c.name),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			"PRECISION" = isnull(d.data_precision, convert(int,c.length)),
			LENGTH = isnull(d.length, convert(int,c.length)),
			SCALE = d.numeric_scale,
			d.RADIX,
			NULLABLE =	/* set nullability from status flag */
				convert(smallint, convert(bit, c.status&8)),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.data_precision, convert(int,c.length))+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO      YES',(c.status&8)+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			syscomments m,
			master.dbo.spt_datatype_info d,
			systypes t
		WHERE
			o.id = @table_id
			AND c.id = o.id
			AND t.type = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND o.type <> 'P'
			AND c.usertype = t.usertype
			AND c.name like @column_name
			AND c.cdefault *= m.id
			AND m.colid = 1
		ORDER BY 17
	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
			TABLE_QUALIFIER = convert(varchar(32),DB_NAME()),
			TABLE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			TABLE_NAME = convert(varchar(32),o.name),
			COLUMN_NAME = convert(varchar(32),c.name),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			"PRECISION" = isnull(d.data_precision, convert(int,c.length)),
			LENGTH = isnull(d.length, convert(int,c.length)),
			SCALE = d.numeric_scale,
			d.RADIX,
			NULLABLE =	/* set nullability from status flag */
				convert(smallint, convert(bit, c.status&8)),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.data_precision, convert(int,c.length))+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO      YES',(c.status&8)+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			syscomments m,
			master.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
			AND t.type = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND o.type <> 'P'
			AND c.usertype = t.usertype
			AND c.name like @column_name
			AND c.cdefault *= m.id
			AND m.colid = 1
		ORDER BY 2, 3, 17
	end
go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following error.'
end
else
	drop proc sp_columns
go

/*	Procedure for 6.0 and 6.50 server */
CREATE PROCEDURE sp_columns (
				 @table_name		varchar(96),
				 @table_owner		varchar(96) = null,
				 @table_qualifier	varchar(32) = null,
				 @column_name		varchar(96) = null,
				 @ODBCVer			int = 2)
AS
	DECLARE @full_table_name	varchar(193)
	DECLARE @table_id int

	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		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 ((charindex('%',@full_table_name) = 0) and
		(charindex('[',@full_table_name) = 0) and
		(charindex('_',@full_table_name) = 0) and
		@table_id <> 0)
	begin
		/* this block is for the case where there is no pattern
			matching required for the table name */

		SELECT
			TABLE_QUALIFIER = convert(varchar(32),DB_NAME()),
			TABLE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			TABLE_NAME = convert(varchar(32),o.name),
			COLUMN_NAME = convert(varchar(32),c.name),
			DATA_TYPE = d.DATA_TYPE,
			TYPE_NAME = convert(varchar(32),
					case
						when t.usertype > 100 or t.usertype in (18,80) then t.name
						else d.TYPE_NAME
					end),
			"PRECISION" = convert(int,
					case
						when d.DATA_TYPE in (6,7) then d.data_precision	/* FLOAT/REAL */
						else isnull(convert(int,c.prec), 2147483647)
					end),
			LENGTH = convert(int,
					case
						when d.ss_dtype IN (106, 108, 55, 63) then	/* decimal/numeric types */
						c.prec+2
						else
							isnull(d.length, c.length)
					end),
			SCALE = convert(smallint, c.scale),
			RADIX = d.RADIX,
			NULLABLE =	/* set nullability from status flag */
				convert(smallint, convert(bit, c.status&8)),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			SQL_DATA_TYPE = d.SQL_DATA_TYPE,
			SQL_DATETIME_SUB = d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(convert(int,c.prec), 2147483647)+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO      YES',(c.status&8)+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			syscomments m,
			master.dbo.spt_datatype_info d,
			systypes t
		WHERE
			o.id = @table_id
			AND c.id = o.id
			AND t.type = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND o.type <> 'P'
			AND isnull(d.AUTO_INCREMENT,0) = (c.status&128)/128
			AND c.usertype = t.usertype
			AND c.name like @column_name
			AND c.cdefault *= m.id
			AND m.colid = 1
		ORDER BY 17
	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
			TABLE_QUALIFIER = convert(varchar(32),DB_NAME()),
			TABLE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			TABLE_NAME = convert(varchar(32),o.name),
			COLUMN_NAME = convert(varchar(32),c.name),
			DATA_TYPE = d.DATA_TYPE,
			TYPE_NAME = convert(varchar(32), 
				case 
					when t.usertype > 100 or t.usertype in (18,80) then t.name
					else d.TYPE_NAME
				end),
			"PRECISION" = convert(int,
					case
						when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
						else isnull(convert(int,c.prec), 2147483647)
					end),
			LENGTH = convert(int,
					case
						when d.ss_dtype IN (106, 108, 55, 63) then	/* decimal/numeric types */
							c.prec+2
						else
							isnull(d.length, c.length)
					end),
			SCALE = convert(smallint, c.scale),
			RADIX = d.RADIX,
			NULLABLE =	/* set nullability from status flag */
				convert(smallint, convert(bit, c.status&8)),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			SQL_DATA_TYPE = d.SQL_DATA_TYPE,
			SQL_DATETIME_SUB = d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(convert(int,c.prec), 2147483647) + d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO      YES',(c.status&8)+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			syscomments m,
			master.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
			AND t.type = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND o.type <> 'P'
			AND isnull(d.AUTO_INCREMENT,0) = (c.status&128)/128
			AND c.usertype = t.usertype
			AND c.name like @column_name
			AND c.cdefault *= m.id
			AND m.colid = 1
		ORDER BY 2, 3, 17
	end
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_columns
go

/*	Procedure for 7.0 server */
CREATE PROCEDURE sp_columns (
				 @table_name		nvarchar(384),
				 @table_owner		nvarchar(384) = null,
				 @table_qualifier	sysname = null,
				 @column_name		nvarchar(384) = null,
				 @ODBCVer			int = 2)
AS
	DECLARE @full_table_name	nvarchar(769)
	DECLARE @table_id int

	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		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 = quotename(@table_name)
	end
	else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
	end

	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)
	if ((isnull(charindex('%', @full_table_name),0) = 0) and
		(isnull(charindex('[', @table_name),0) = 0) and
		(isnull(charindex('[', @table_owner),0) = 0) and
		(isnull(charindex('_', @full_table_name),0) = 0) and
		@table_id <> 0)
	begin
		/* this block is for the case where there is no pattern
			matching required for the table name */
		
		SELECT
			TABLE_QUALIFIER = convert(sysname,DB_NAME()),
			TABLE_OWNER = convert(sysname,USER_NAME(o.uid)),
			TABLE_NAME = convert(sysname,o.name),
			COLUMN_NAME = convert(sysname,c.name),
			d.DATA_TYPE,
			convert (sysname,case
				when t.xusertype > 255 then t.name
				else d.TYPE_NAME
			end) TYPE_NAME,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			NULLABLE = convert(smallint, ColumnProperty (c.id, c.name, 'AllowsNull')),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),
				substring('NO YES',(ColumnProperty (c.id, c.name, 'AllowsNull')*3)+1,3)),
			SS_DATA_TYPE = c.type
		FROM
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t,
			syscolumns c
			LEFT OUTER JOIN syscomments m on c.cdefault = m.id
				AND m.colid = 1
		WHERE
			o.id = @table_id
			AND c.id = o.id
			AND t.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND (o.type not in ('P', 'FN', 'TF', 'IF') OR (o.type in ('TF', 'IF') and c.number = 0))
			AND isnull(d.AUTO_INCREMENT,0) = isnull(ColumnProperty (c.id, c.name, 'IsIdentity'),0)
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
		ORDER BY 17
	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
			TABLE_QUALIFIER = convert(sysname,DB_NAME()),
			TABLE_OWNER = convert(sysname,USER_NAME(o.uid)),
			TABLE_NAME = convert(sysname,o.name),
			COLUMN_NAME = convert(sysname,c.name),
			d.DATA_TYPE,
			convert (sysname,case
				when t.xusertype > 255 then t.name
				else d.TYPE_NAME
			end) TYPE_NAME,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			NULLABLE = convert(smallint, ColumnProperty (c.id, c.name, 'AllowsNull')),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),
				rtrim(substring('NO YES',(ColumnProperty (c.id, c.name, 'AllowsNull')*3)+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t,
			syscolumns c
			LEFT OUTER JOIN syscomments m on c.cdefault = m.id
				AND m.colid = 1
		WHERE
			o.name like @table_name
			AND user_name(o.uid) like @table_owner
			AND o.id = c.id
			AND t.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND (o.type not in ('P', 'FN', 'TF', 'IF') OR (o.type in ('TF', 'IF') and c.number = 0))
			AND isnull(d.AUTO_INCREMENT,0) = isnull(ColumnProperty (c.id, c.name, 'IsIdentity'),0)
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
		ORDER BY 2, 3, 17
	end
go

if (charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_columns
go

/*	Procedure for 8.0 server */
CREATE PROCEDURE sp_columns (
				 @table_name		nvarchar(384),
				 @table_owner		nvarchar(384) = null,
				 @table_qualifier	sysname = null,
				 @column_name		nvarchar(384) = null,
				 @ODBCVer			int = 2)
AS
	DECLARE @full_table_name	nvarchar(769)
	DECLARE @table_id int

	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		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 = quotename(@table_name)
	end
	else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
	end

	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)
	if ((isnull(charindex('%', @full_table_name),0) = 0) and
		(isnull(charindex('[', @table_name),0) = 0) and
		(isnull(charindex('[', @table_owner),0) = 0) and
		(isnull(charindex('_', @full_table_name),0) = 0) and
		@table_id <> 0)
	begin
		/* this block is for the case where there is no pattern
			matching required for the table name */
		
		SELECT
			TABLE_QUALIFIER = convert(sysname,DB_NAME()),
			TABLE_OWNER = convert(sysname,USER_NAME(o.uid)),
			TABLE_NAME = convert(sysname,o.name),
			COLUMN_NAME = convert(sysname,c.name),
			d.DATA_TYPE,
			convert (sysname,case
				when t.xusertype > 255 then t.name
				else d.TYPE_NAME collate database_default
			end) TYPE_NAME,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			NULLABLE = convert(smallint, ColumnProperty (c.id, c.name, 'AllowsNull')),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),
				substring('NO YES',(ColumnProperty (c.id, c.name, 'AllowsNull')*3)+1,3)),
			SS_DATA_TYPE = c.type
		FROM
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t,
			syscolumns c
			LEFT OUTER JOIN syscomments m on c.cdefault = m.id
				AND m.colid = 1
		WHERE
			o.id = @table_id
			AND c.id = o.id
			AND t.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND (o.type not in ('P', 'FN', 'TF', 'IF') OR (o.type in ('TF', 'IF') and c.number = 0))
			AND isnull(d.AUTO_INCREMENT,0) = isnull(ColumnProperty (c.id, c.name, 'IsIdentity'),0)
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
		ORDER BY 17
	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
			TABLE_QUALIFIER = convert(sysname,DB_NAME()),
			TABLE_OWNER = convert(sysname,USER_NAME(o.uid)),
			TABLE_NAME = convert(sysname,o.name),
			COLUMN_NAME = convert(sysname,c.name),
			d.DATA_TYPE,
			convert (sysname,case
				when t.xusertype > 255 then t.name
				else d.TYPE_NAME collate database_default
			end) TYPE_NAME,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			NULLABLE = convert(smallint, ColumnProperty (c.id, c.name, 'AllowsNull')),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = text,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int,
					   (
						select count(*)
						from syscolumns sc
						where sc.id     =  c.id
						  AND sc.number =  c.number
						  AND sc.colid  <= c.colid
					    )),
			IS_NULLABLE = convert(varchar(254),
				rtrim(substring('NO YES',(ColumnProperty (c.id, c.name, 'AllowsNull')*3)+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t,
			syscolumns c
			LEFT OUTER JOIN syscomments m on c.cdefault = m.id
				AND m.colid = 1
		WHERE
			o.name like @table_name
			AND user_name(o.uid) like @table_owner
			AND o.id = c.id
			AND t.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND (o.type not in ('P', 'FN', 'TF', 'IF') OR (o.type in ('TF', 'IF') and c.number = 0))
			AND isnull(d.AUTO_INCREMENT,0) = isnull(ColumnProperty (c.id, c.name, 'IsIdentity'),0)
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
		ORDER BY 2, 3, 17
	end
go

grant execute on sp_columns to public
go

dump tran master with no_log
go

print 'creating sp_databases'
go

/*	Procedure for pre-7.0 server */
create proc sp_databases
as
	set nocount on
	/* Use temporary table to sum up database size w/o using group by */
	create table #databases (
				  DATABASE_NAME varchar(32) NOT NULL,
				  size int NOT NULL)

	/* 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,
		 DATABASE_SIZE = size*2,	/* Convert from 2048 byte pages to K */
		 REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
	from #databases
	order by 1
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_databases
go

/*	Procedure for 8.0 server */
create proc sp_databases
as
	set nocount on
	declare @name sysname
	declare @SQL  nvarchar(600)

	/* Use temporary table to sum up database size w/o using group by */
	create table #databases (
				  DATABASE_NAME sysname NOT NULL,
				  size int NOT NULL)

	declare c1 cursor for 
		select name from master.dbo.sysdatabases
			where has_dbaccess(name) = 1 -- Only look at databases to which we have access

	open c1
	fetch c1 into @name

	while @@fetch_status >= 0
	begin
		select @SQL = 'insert into #databases
				select N'''+ @name + ''', sum(size) from '
				+ QuoteName(@name) + '.dbo.sysfiles'
		/* Insert row for each database */
		execute (@SQL)
		fetch c1 into @name
	end
	deallocate c1

	select	
		DATABASE_NAME,
		DATABASE_SIZE = size*8,/* Convert from 8192 byte pages to K */
		REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
	from #databases
	order by 1
go

grant execute on sp_databases to public
go

dump tran master with no_log
go

print 'creating sp_datatype_info'
go

/*	Procedure for pre-6.0 server */
create proc sp_datatype_info
	(@data_type int = 0, @ODBCVer tinyint = 2)
as
	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @data_type = 0
		select
			TYPE_NAME = t.name,
			d.DATA_TYPE,
			"PRECISION" = 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,
			LOCAL_TYPE_NAME = t.name,
			MINIMUM_SCALE = d.numeric_scale,
			MAXIMUM_SCALE = d.numeric_scale,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			NUM_PREC_RADIX = convert(int,d.RADIX),
			INTERVAL_PRECISION = convert(smallint,NULL),
			USERTYPE = t.usertype
		from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
		where
			d.ss_dtype = t.type
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			and t.usertype *= e.user_type
			and (t.type not in (111,109,38,110) or /* get rid of nullable types */
				t.usertype > 100)
		order by 2, 12, 11, t.usertype

	else
		select
			TYPE_NAME = t.name,
			d.DATA_TYPE,
			"PRECISION" = 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,
			LOCAL_TYPE_NAME = t.name,
			MINIMUM_SCALE = d.numeric_scale,
			MAXIMUM_SCALE = d.numeric_scale,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			NUM_PREC_RADIX = convert(int,d.RADIX),
			INTERVAL_PRECISION = convert(smallint,NULL),
			USERTYPE = t.usertype
		from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
		where
			DATA_TYPE = @data_type
			and d.ss_dtype = t.type
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			and t.usertype *= e.user_type
			and (t.type not in (111,109,38,110) or /* get rid of nullable types */
				t.usertype > 100)
		order by 12, 11, t.usertype

go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_datatype_info
go

/*	Procedure for 6.0 and 6.50 servers */
create proc sp_datatype_info
	(@data_type int = 0, @ODBCVer tinyint = 2)
as
	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @data_type = 0
		select
			convert(varchar(32),case
				when t.usertype > 100 or t.usertype in (18,80) then t.name
				else d.TYPE_NAME
			end) TYPE_NAME,
			d.DATA_TYPE,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				when d.ss_dtype in (35,34) then 2147483647				/* TEXT/IMAGE */
				when d.ss_dtype in (55,63,106,108) and t.usertype <= 100 then @@max_precision /* DECIMAL/NUMERIC */
				else t.prec
			end) "PRECISION",
			d.LITERAL_PREFIX,
			d.LITERAL_SUFFIX,
			e.CREATE_PARAMS,
			convert(smallint,case
				when d.AUTO_INCREMENT = 1 then 0 /* IDENTITY*/
				else t.allownulls
			end) NULLABLE,
			d.CASE_SENSITIVE,
			d.SEARCHABLE,
			d.UNSIGNED_ATTRIBUTE,
			d.MONEY,
			d.AUTO_INCREMENT,
			convert(varchar(32),case
				when t.usertype > 100 or t.usertype in (18,80) then t.name
				else d.TYPE_NAME
			end) LOCAL_TYPE_NAME,
			convert(smallint,case
				when d.ss_dtype in (55,63,106,108) and t.usertype > 100 then t.scale
				else d.numeric_scale
			end) MINIMUM_SCALE,
			convert(smallint,case
				when d.ss_dtype in (106,108) and d.AUTO_INCREMENT = 0 then @@max_precision /* DECIMAL/NUMERIC */
				when d.ss_dtype in (106,108) and d.AUTO_INCREMENT = 1 then 0 /* DECIMAL/NUMERIC IDENTITY*/
				else t.scale
			end) MAXIMUM_SCALE,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			NUM_PREC_RADIX = convert(int,d.RADIX),
			INTERVAL_PRECISION = convert(smallint,NULL),
			USERTYPE = t.usertype
		from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
		where
			d.ss_dtype = t.type
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			and t.usertype *= e.user_type
			and isnull(d.AUTO_INCREMENT,0) *= e.AUTO_INCREMENT
			and (t.type not in (111,109,38,110,55,63) or /* get rid of nullable types */
				t.usertype > 100)
			and (t.usertype <= 100 or
				isnull(d.AUTO_INCREMENT,0) = 0)
		order by 2, 12, 11, t.usertype

	else
		select
			convert(varchar(32),case
				when t.usertype > 100 or t.usertype in (18,80) then t.name
				else d.TYPE_NAME
			end) TYPE_NAME,
			d.DATA_TYPE,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				when d.ss_dtype in (35,34) then 2147483647				/* TEXT/IMAGE */
				when d.ss_dtype in (55,63,106,108) and t.usertype <= 100 then @@max_precision /* DECIMAL/NUMERIC */
				else t.prec
			end) "PRECISION",
			d.LITERAL_PREFIX,
			d.LITERAL_SUFFIX,
			e.CREATE_PARAMS,
			convert(smallint,case
				when d.AUTO_INCREMENT = 1 then 0 /* IDENTITY*/
				else t.allownulls
			end) NULLABLE,
			d.CASE_SENSITIVE,
			d.SEARCHABLE,
			d.UNSIGNED_ATTRIBUTE,
			d.MONEY,
			d.AUTO_INCREMENT,
			convert(varchar(32),case
				when t.usertype > 100 or t.usertype in (18,80) then t.name
				else d.TYPE_NAME
			end) LOCAL_TYPE_NAME,
			convert(smallint,case
				when d.ss_dtype in (55,63,106,108) and t.usertype > 100 then t.scale
				else d.numeric_scale
			end) MINIMUM_SCALE,
			convert(smallint,case
				when d.ss_dtype in (106,108) and d.AUTO_INCREMENT = 0 then @@max_precision /* DECIMAL/NUMERIC */
				when d.ss_dtype in (106,108) and d.AUTO_INCREMENT = 1 then 0 /* DECIMAL/NUMERIC IDENTITY*/
				else t.scale
			end) MAXIMUM_SCALE,
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			NUM_PREC_RADIX = convert(int,d.RADIX),
			INTERVAL_PRECISION = convert(smallint,NULL),
			USERTYPE = t.usertype
		from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
		where
			d.DATA_TYPE = @data_type
			and d.ss_dtype = t.type
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			and t.usertype *= e.user_type
			and isnull(d.AUTO_INCREMENT,0) *= e.AUTO_INCREMENT
			and (t.type not in (111,109,38,110,55,63) or /* get rid of nullable types */
				t.usertype > 100)
			and (t.usertype <= 100 or
				isnull(d.AUTO_INCREMENT,0) = 0)
		order by 12, 11, t.usertype
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_datatype_info
go

/*	Procedure for 7.0 server */
create proc sp_datatype_info
	(@data_type int = 0, @ODBCVer tinyint = 2)
as
	declare @mintype int
	declare @maxtype int

	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @data_type = 0
	begin
		select @mintype = -32768
		select @maxtype = 32767
	end
	else
	begin
		select @mintype = @data_type
		select @maxtype = @data_type
	end

	select
		convert(sysname,case
			when t.xusertype > 255 then t.name
			else d.TYPE_NAME
		end) TYPE_NAME,
		d.DATA_TYPE,
		convert(int,case
			when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
			when type_name(d.ss_dtype) IN ('numeric','decimal') and
				t.xusertype <= 255 then @@max_precision /* DECIMAL/NUMERIC */
			else OdbcPrec(t.xtype, t.length, t.xprec)
		end) "PRECISION",
		d.LITERAL_PREFIX,
		d.LITERAL_SUFFIX,
		e.CREATE_PARAMS,
		convert(smallint,case
			when d.AUTO_INCREMENT = 1 then 0 /* IDENTITY*/
			else TypeProperty (t.name, 'AllowsNull')
		end) NULLABLE,
		d.CASE_SENSITIVE,
		d.SEARCHABLE,
		d.UNSIGNED_ATTRIBUTE,
		d.MONEY,
		d.AUTO_INCREMENT,
		convert(sysname,case
			when t.xusertype > 255 then t.name
			else d.LOCAL_TYPE_NAME
		end) LOCAL_TYPE_NAME,
		MINIMUM_SCALE = d.numeric_scale,
		convert(smallint,case
			when type_name(d.ss_dtype) IN ('numeric','decimal') and d.AUTO_INCREMENT = 0 and t.xusertype <= 255 then @@max_precision /* DECIMAL/NUMERIC */
			when type_name(d.ss_dtype) IN ('numeric','decimal') and d.AUTO_INCREMENT = 1 then 0 /* DECIMAL/NUMERIC IDENTITY*/
			else TypeProperty (t.name, 'Scale')
		end) MAXIMUM_SCALE,
		d.SQL_DATA_TYPE,
		d.SQL_DATETIME_SUB,
		NUM_PREC_RADIX = convert(int,d.RADIX),
		INTERVAL_PRECISION = convert(smallint,NULL),
		USERTYPE = t.usertype
	from master.dbo.spt_datatype_info d
		INNER JOIN systypes t on d.ss_dtype = t.xtype
		LEFT OUTER JOIN master.dbo.spt_datatype_info_ext e on
			t.xusertype = e.user_type
			and isnull(d.AUTO_INCREMENT,0) = e.AUTO_INCREMENT
	where
		d.DATA_TYPE between @mintype and @maxtype
		and (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
		and (t.xusertype <= 255 or
			isnull(d.AUTO_INCREMENT,0) = 0)
	order by 2, 12, 11,
	case
		when t.usertype=18 then 255
		else t.usertype
	end

go

if (charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_datatype_info
go

/*	Procedure for 8.0 server */
create proc sp_datatype_info
	(@data_type int = 0, @ODBCVer tinyint = 2)
as
	declare @mintype int
	declare @maxtype int

	if @ODBCVer <> 3
		select @ODBCVer = 2
	if @data_type = 0
	begin
		select @mintype = -32768
		select @maxtype = 32767
	end
	else
	begin
		select @mintype = @data_type
		select @maxtype = @data_type
	end

	select
		convert(sysname,case
			when t.xusertype > 255 then t.name
			else d.TYPE_NAME collate database_default
		end) TYPE_NAME,
		d.DATA_TYPE,
		convert(int,case
			when d.DATA_TYPE in (6,7,-150) then d.data_precision 		/* FLOAT/REAL/sql_variant*/
			when d.ss_dtype in (55,63,106,108) and
				t.xusertype <= 255 then @@max_precision /* DECIMAL/NUMERIC */
			else OdbcPrec(t.xtype, t.length, t.xprec)
		end) "PRECISION",
		d.LITERAL_PREFIX,
		d.LITERAL_SUFFIX,
		e.CREATE_PARAMS,
		convert(smallint,case
			when d.AUTO_INCREMENT = 1 then 0 /* IDENTITY*/
			else TypeProperty (t.name, 'AllowsNull')
		end) NULLABLE,
		d.CASE_SENSITIVE,
		d.SEARCHABLE,
		d.UNSIGNED_ATTRIBUTE,
		d.MONEY,
		d.AUTO_INCREMENT,
		convert(sysname,case
			when t.xusertype > 255 then t.name
			else d.LOCAL_TYPE_NAME collate database_default
		end) LOCAL_TYPE_NAME,
		convert(smallint,case
			when d.ss_dtype in (55,63,106,108) and t.xusertype > 255 then TypeProperty (t.name, 'Scale')
			else d.numeric_scale
		end) MINIMUM_SCALE,
		convert(smallint,case
			when d.ss_dtype in (55,63,106,108) and d.AUTO_INCREMENT = 0 and t.xusertype <= 255 then @@max_precision /* DECIMAL/NUMERIC */
			when d.ss_dtype in (55,63,106,108) and d.AUTO_INCREMENT = 1 then 0 /* DECIMAL/NUMERIC IDENTITY*/
			else TypeProperty (t.name, 'Scale')
		end) MAXIMUM_SCALE,
		d.SQL_DATA_TYPE,
		d.SQL_DATETIME_SUB,
		NUM_PREC_RADIX = convert(int,d.RADIX),
		INTERVAL_PRECISION = convert(smallint,NULL),
		USERTYPE = t.usertype
	from master.dbo.spt_datatype_info d
		INNER JOIN systypes t on d.ss_dtype = t.xtype
		LEFT OUTER JOIN master.dbo.spt_datatype_info_ext e on
			t.xusertype = e.user_type
			and isnull(d.AUTO_INCREMENT,0) = e.AUTO_INCREMENT
	where
		d.DATA_TYPE between @mintype and @maxtype
		and (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
		and (t.xusertype <= 255 or
			isnull(d.AUTO_INCREMENT,0) = 0)
	order by 2, 12, 11,
	case
		when t.usertype=18 then 255
		else t.usertype
	end

go

grant execute on sp_datatype_info to public
go

dump tran master with no_log
go

print 'creating sp_fkeys'
go

/*	Procedure for pre-6.0 server */
CREATE PROCEDURE sp_fkeys(
			   @pktable_name		varchar(32) = null,
			   @pktable_owner		varchar(32) = null,
			   @pktable_qualifier	varchar(32) = null,
			   @fktable_name		varchar(32) = null,
			   @fktable_owner		varchar(32) = null,
			   @fktable_qualifier	varchar(32) = null )
as
	set nocount on
    declare	@order_by_pk int

    select  @order_by_pk = 0

	if (@pktable_name is null) and (@fktable_name is null)
	begin	/* If neither primary key nor foreign key table names given */
		raiserror 20004 '~~Rush_25~~'
		return
    end
	if @fktable_qualifier is not null
    begin
		if db_name() <> @fktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_26~~'
			return
		end
    end
	if @pktable_qualifier is not null
    begin
		if db_name() <> @pktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_27~~'
			return
		end
    end

	if @pktable_name is null
	begin /*  If table name not supplied, match all */
		select @pktable_name = '%'
		select @order_by_pk = 1
    end
	if @pktable_owner is null	/*	If PK owner not supplied, match all */
		select @pktable_owner = '%'
	if @fktable_name is null	/*	If table name not supplied, match all */
		select @fktable_name = '%'
	if @fktable_owner is null	/*	If FK owner not supplied, match all */
		select @fktable_owner = '%'

	if @@trancount <> 0
	begin	/* If inside a transaction */
		raiserror 20003 '~~Rush_28~~'
		return
    end
	create table #fkeys(
			 PKTABLE_QUALIFIER	varchar(32) NULL,
			 PKTABLE_OWNER		varchar(32) NULL,
			 PKTABLE_NAME		varchar(32) NOT NULL,
			 PKCOLUMN_NAME		varchar(32) NOT NULL,
			 FKTABLE_QUALIFIER	varchar(32) NULL,
			 FKTABLE_OWNER		varchar(32) NULL,
			 FKTABLE_NAME		varchar(32) NOT NULL,
			 FKCOLUMN_NAME		varchar(32) NOT NULL,
			 KEY_SEQ			smallint NOT NULL)

	/*	SQL Server supports upto 8 PK/FK relationships between 2 tables */
	/*	Process syskeys for each relationship */
	/*	The inserts below adds a row to the temp table for each of the
		8 possible relationships */
    insert into #fkeys
		select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			1
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key1
			and c2.id = k.depid
			and c2.colid = k.depkey1
			and o1.id = k.depid
			and o2.id = k.id
	union all
	    select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			2
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key2
			and c2.id = k.depid
			and c2.colid = k.depkey2
			and o1.id = k.depid
			and o2.id = k.id
	union all
		select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			3
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key3
			and c2.id = k.depid
			and c2.colid = k.depkey3
			and o1.id = k.depid
			and o2.id = k.id
	union all
		select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			4
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key4
			and c2.id = k.depid
			and c2.colid = k.depkey4
			and o1.id = k.depid
			and o2.id = k.id
	union all
		select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			5
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key5
			and c2.id = k.depid
			and c2.colid = k.depkey5
			and o1.id = k.depid
			and o2.id = k.id
	union all
		select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			6
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key6
			and c2.id = k.depid
			and c2.colid = k.depkey6
			and o1.id = k.depid
			and o2.id = k.id
	union all
	    select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			7
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key7
			and c2.id = k.depid
			and c2.colid = k.depkey7
			and o1.id = k.depid
			and o2.id = k.id
	union all
	    select
			db_name(),
			user_name(o1.uid),
			object_name(k.depid),
			c2.name,
			db_name(),
			user_name(o2.uid),
			object_name(k.id),
			c1.name,
			8
		from
			syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
		where
			c1.id = k.id
			and k.type = 2	/* Foreign type key */
			and c1.colid = k.key8
			and c2.id = k.depid
			and c2.colid = k.depkey8
			and o1.id = k.depid
			and o2.id = k.id

	if @order_by_pk = 1 /*	If order by PK fields */
		select
			PKTABLE_QUALIFIER,
			PKTABLE_OWNER,
			PKTABLE_NAME,
			PKCOLUMN_NAME,
			FKTABLE_QUALIFIER,
			FKTABLE_OWNER,
			FKTABLE_NAME,
			FKCOLUMN_NAME,
			KEY_SEQ,
			UPDATE_RULE = convert(smallint, null),
			DELETE_RULE = convert(smallint,null),
			FK_NAME = convert(varchar(32),null),
			PK_NAME = convert(varchar(32),null),
			DEFERRABILITY = convert(smallint,7)
		from #fkeys
		where FKTABLE_NAME like @fktable_name
			and FKTABLE_OWNER like @fktable_owner
			and PKTABLE_NAME  like @pktable_name
			and PKTABLE_OWNER like @pktable_owner
		order by 1, 2, 3, 9, 4
	else		/*	Order by FK fields */
		select
			PKTABLE_QUALIFIER,
			PKTABLE_OWNER,
			PKTABLE_NAME,
			PKCOLUMN_NAME,
			FKTABLE_QUALIFIER,
			FKTABLE_OWNER,
			FKTABLE_NAME,
			FKCOLUMN_NAME,
			KEY_SEQ,
			UPDATE_RULE = convert(smallint,null),
			DELETE_RULE = convert(smallint,null),
			FK_NAME = convert(varchar(32),null),
			PK_NAME = convert(varchar(32),null),
			DEFERRABILITY = convert(smallint,7)
		from #fkeys
		where FKTABLE_NAME like @fktable_name
			and FKTABLE_OWNER like @fktable_owner
			and PKTABLE_NAME  like @pktable_name
			and PKTABLE_OWNER like @pktable_owner
		order by 5, 6, 7, 9, 8
go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_fkeys
go

/*	Procedure for 6.0 and 6.50 servers */
CREATE PROCEDURE sp_fkeys(
			   @pktable_name		varchar(32) = null,
			   @pktable_owner		varchar(32) = null,
			   @pktable_qualifier	varchar(32) = null,
			   @fktable_name		varchar(32) = null,
			   @fktable_owner		varchar(32) = null,
			   @fktable_qualifier	varchar(32) = null )
as
	set nocount on
	DECLARE @pktable_id			int
	DECLARE @pkfull_table_name	varchar(65) /* 2*32 +1 */
	DECLARE @fktable_id			int
	DECLARE @fkfull_table_name	varchar(65) /* 2*32 +1 */
	declare	@order_by_pk		int

    select  @order_by_pk = 0

	if (@pktable_name is null) and (@fktable_name is null)
	begin	/* If neither primary key nor foreign key table names given */
		raiserror (15252,-1,-1)
		return
    end
	if @fktable_qualifier is not null
    begin
		if db_name() <> @fktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @pktable_qualifier is not null
    begin
		if db_name() <> @pktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end

	if @pktable_owner is null
	begin	/* If unqualified primary key table name */
		SELECT @pkfull_table_name = @pktable_name
    end
    else
	begin	/* Qualified primary key table name */
		SELECT @pkfull_table_name = @pktable_owner + '.' + @pktable_name
    end
	/*	Get Object ID */
	SELECT @pktable_id = object_id(@pkfull_table_name)

	if @fktable_owner is null
	begin	/* If unqualified foreign key table name */
		SELECT @fkfull_table_name = @fktable_name
    end
    else
	begin	/* Qualified foreign key table name */
		SELECT @fkfull_table_name = @fktable_owner + '.' + @fktable_name
    end
	/*	Get Object ID */
	SELECT @fktable_id = object_id(@fkfull_table_name)

	if @fktable_name is not null
	begin
		if @fktable_id is null
			SELECT @fktable_id = 0	/* fk table not found, empty result */
    end

	if @pktable_name is null
	begin /*  If table name not supplied, match all */
		select @order_by_pk = 1
	end
	else
	begin
		if @pktable_id is null
		begin
			SELECT @pktable_id = 0	/* pk table not found, empty result */
		end
	end

	if (@@trancount <> 0 and
		charindex('6.50', @@version) = 0)
	begin	/* If inside a transaction */
		raiserror (15002,-1,-1,'sp_fkeys')
		return
	end

	create table #fkeys(
			 pkdb_id		int NOT NULL,
			 pktable_id 	int NOT NULL,
			 pkcolid		int NOT NULL,
			 fkdb_id		int NOT NULL,
			 fktable_id		int NOT NULL,
			 fkcolid		int NOT NULL,
			 KEY_SEQ		smallint NOT NULL,
			 fk_id			int NOT NULL,
			 pk_id			int NOT NULL)

	/*	SQL Server supports upto 16 PK/FK relationships between 2 tables */
	/*	Process syskeys for each relationship */
	/*	The inserts below adds a row to the temp table for each of the
		16 possible relationships */
    insert into #fkeys
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey1,
			r.fkeydbid,
			r.fkeyid,
			r.fkey1,
			1,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey2,
			r.fkeydbid,
			r.fkeyid,
			r.fkey2,
			2,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey3,
			r.fkeydbid,
			r.fkeyid,
			r.fkey3,
			3,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey4,
			r.fkeydbid,
			r.fkeyid,
			r.fkey4,
			4,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey5,
			r.fkeydbid,
			r.fkeyid,
			r.fkey5,
			5,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey6,
			r.fkeydbid,
			r.fkeyid,
			r.fkey6,
			6,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey7,
			r.fkeydbid,
			r.fkeyid,
			r.fkey7,
			7,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey8,
			r.fkeydbid,
			r.fkeyid,
			r.fkey8,
			8,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey9,
			r.fkeydbid,
			r.fkeyid,
			r.fkey9,
			9,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey10,
			r.fkeydbid,
			r.fkeyid,
			r.fkey10,
			10,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey11,
			r.fkeydbid,
			r.fkeyid,
			r.fkey11,
			11,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey12,
			r.fkeydbid,
			r.fkeyid,
			r.fkey12,
			12,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey13,
			r.fkeydbid,
			r.fkeyid,
			r.fkey13,
			13,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey14,
			r.fkeydbid,
			r.fkeyid,
			r.fkey14,
			14,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey15,
			r.fkeydbid,
			r.fkeyid,
			r.fkey15,
			15,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)
	  union all
		select
			r.rkeydbid,
			r.rkeyid,
			r.rkey16,
			r.fkeydbid,
			r.fkeyid,
			r.fkey16,
			16,
			r.constid,
			s.constid
		from
			sysreferences r, sysconstraints s
		where	r.rkeyid = s.id
			AND (s.status & 0xf) = 1
			AND r.rkeyid between isnull(@pktable_id, 0) and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0) and isnull(@fktable_id, 0x7fffffff)

	if @order_by_pk = 1 /*	If order by PK fields */
		select
			PKTABLE_QUALIFIER = convert(varchar(32),DB_NAME(f.pkdb_id)),
			PKTABLE_OWNER = convert(varchar(32),USER_NAME(o1.uid)),
			PKTABLE_NAME = convert(varchar(32),o1.name),
			PKCOLUMN_NAME = convert(varchar(32),c1.name),
			FKTABLE_QUALIFIER = convert(varchar(32),DB_NAME(f.fkdb_id)),
			FKTABLE_OWNER = convert(varchar(32),USER_NAME(o2.uid)),
			FKTABLE_NAME = convert(varchar(32),o2.name),
			FKCOLUMN_NAME = convert(varchar(32),c2.name),
			KEY_SEQ,
			UPDATE_RULE = convert(smallint,1),
			DELETE_RULE = convert(smallint,1),
			FK_NAME = convert(varchar(32),OBJECT_NAME(fk_id)),
			PK_NAME = convert(varchar(32),OBJECT_NAME(pk_id)),
			DEFERRABILITY = convert(smallint,7)
		from #fkeys f,
			sysobjects o1, sysobjects o2,
			syscolumns c1, syscolumns c2
		where	o1.id = f.pktable_id
			AND o2.id = f.fktable_id
			AND c1.id = f.pktable_id
			AND c2.id = f.fktable_id
			AND c1.colid = f.pkcolid
			AND c2.colid = f.fkcolid
		order by 1,2,3,9,4
	else		/*	Order by FK fields */
		select
			PKTABLE_QUALIFIER = convert(varchar(32),DB_NAME(f.pkdb_id)),
			PKTABLE_OWNER = convert(varchar(32),USER_NAME(o1.uid)),
			PKTABLE_NAME = convert(varchar(32),o1.name),
			PKCOLUMN_NAME = convert(varchar(32),c1.name),
			FKTABLE_QUALIFIER = convert(varchar(32),DB_NAME(f.fkdb_id)),
			FKTABLE_OWNER = convert(varchar(32),USER_NAME(o2.uid)),
			FKTABLE_NAME = convert(varchar(32),o2.name),
			FKCOLUMN_NAME = convert(varchar(32),c2.name),
			KEY_SEQ,
			UPDATE_RULE = convert(smallint,1),
			DELETE_RULE = convert(smallint,1),
			FK_NAME = convert(varchar(32),OBJECT_NAME(fk_id)),
			PK_NAME = convert(varchar(32),OBJECT_NAME(pk_id)),
			DEFERRABILITY = convert(smallint,7)
		from #fkeys f,
			sysobjects o1, sysobjects o2,
			syscolumns c1, syscolumns c2
		where	o1.id = f.pktable_id
			AND o2.id = f.fktable_id
			AND c1.id = f.pktable_id
			AND c2.id = f.fktable_id
			AND c1.colid = f.pkcolid
			AND c2.colid = f.fkcolid
		order by 5,6,7,9,8
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_fkeys
go

/*	Procedure for 7.0 server */
CREATE PROCEDURE sp_fkeys(
			   @pktable_name		sysname = null,
			   @pktable_owner		sysname = null,
			   @pktable_qualifier	sysname = null,
			   @fktable_name		sysname = null,
			   @fktable_owner		sysname = null,
			   @fktable_qualifier	sysname = null )
as
	set nocount on
	DECLARE @pktable_id			int
	DECLARE @pkfull_table_name	nvarchar(257) /* 2*128 + 1 */
	DECLARE @fktable_id			int
	DECLARE @fkfull_table_name	nvarchar(257) /* 2*128 + 1 */
	declare	@order_by_pk		int

	/* select 'XXX starting table creation' */

	create table #fkeysall(
			rkeyid int NOT NULL,
			rkey1 int NOT NULL,
				rkey2 int NOT NULL,
				rkey3 int NOT NULL,
				rkey4 int NOT NULL,
				rkey5 int NOT NULL,
				rkey6 int NOT NULL,
				rkey7 int NOT NULL,
				rkey8 int NOT NULL,
				rkey9 int NOT NULL,
				rkey10 int NOT NULL,
				rkey11 int NOT NULL,
				rkey12 int NOT NULL,
				rkey13 int NOT NULL,
				rkey14 int NOT NULL,
				rkey15 int NOT NULL,
				rkey16 int NOT NULL,
			fkeyid int NOT NULL,
			fkey1 int NOT NULL,
				fkey2 int NOT NULL,
				fkey3 int NOT NULL,
				fkey4 int NOT NULL,
				fkey5 int NOT NULL,
				fkey6 int NOT NULL,
				fkey7 int NOT NULL,
				fkey8 int NOT NULL,
				fkey9 int NOT NULL,
				fkey10 int NOT NULL,
				fkey11 int NOT NULL,
				fkey12 int NOT NULL,
				fkey13 int NOT NULL,
				fkey14 int NOT NULL,
				fkey15 int NOT NULL,
				fkey16 int NOT NULL,
			constid int NOT NULL,
			name sysname NOT NULL)

	create table #fkeys(
			pktable_id		int NOT NULL,
			pkcolid 		int NOT NULL,
			fktable_id		int NOT NULL,
			fkcolid 		int NOT NULL,
			KEY_SEQ 		smallint NOT NULL,
			fk_id			int NOT NULL,
			PK_NAME			sysname NOT NULL)

	create table #fkeysout(
			PKTABLE_QUALIFIER sysname NULL,
			PKTABLE_OWNER sysname NULL,
			PKTABLE_NAME sysname NOT NULL,
			PKCOLUMN_NAME sysname NOT NULL,
			FKTABLE_QUALIFIER sysname NULL,
			FKTABLE_OWNER sysname NULL,
			FKTABLE_NAME sysname NOT NULL,
			FKCOLUMN_NAME sysname NOT NULL,
			KEY_SEQ smallint NOT NULL,
			UPDATE_RULE smallint NULL,
			DELETE_RULE smallint NULL,
			FK_NAME sysname NULL,
			PK_NAME sysname NULL,
			DEFERRABILITY smallint null)

	/* select 'XXX starting parameter analysis' */

    select  @order_by_pk = 0

	if (@pktable_name is null) and (@fktable_name is null)
	begin	/* If neither primary key nor foreign key table names given */
		raiserror (15252,-1,-1)
		return
    end
	if @fktable_qualifier is not null
    begin
		if db_name() <> @fktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @pktable_qualifier is not null
    begin
		if db_name() <> @pktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end

	if @pktable_owner is null
	begin	/* If unqualified primary key table name */
		SELECT @pkfull_table_name = quotename(@pktable_name)
    end
    else
	begin	/* Qualified primary key table name */
		if @pktable_owner = ''
		begin	/* If empty owner name */
			SELECT @pkfull_table_name = quotename(@pktable_owner)
		end
		else
		begin
			SELECT @pkfull_table_name = quotename(@pktable_owner) +
				'.' + quotename(@pktable_name)
		end
    end
	/*	Get Object ID */
	SELECT @pktable_id = object_id(@pkfull_table_name)

	if @fktable_owner is null
	begin	/* If unqualified foreign key table name */
		SELECT @fkfull_table_name = quotename(@fktable_name)
    end
    else
	begin	/* Qualified foreign key table name */
		if @fktable_owner = ''
		begin	/* If empty owner name */
			SELECT @fkfull_table_name = quotename(@fktable_owner)
		end
		else
		begin
			SELECT @fkfull_table_name = quotename(@fktable_owner) +
				'.' + quotename(@fktable_name)
		end
    end
	/*	Get Object ID */
	SELECT @fktable_id = object_id(@fkfull_table_name)

	if @fktable_name is not null
	begin
		if @fktable_id is null
			SELECT @fktable_id = 0	/* fk table not found, empty result */
    end

	if @pktable_name is null
	begin /*  If table name not supplied, match all */
		select @order_by_pk = 1
	end
	else
	begin
		if @pktable_id is null
		begin
			SELECT @pktable_id = 0	/* pk table not found, empty result */
		end
	end

	/*	SQL Server supports upto 16 PK/FK relationships between 2 tables */
	/*	Process syskeys for each relationship */
	/*  First, attempt to get all 16 keys for each rel'ship, then sort
		them out with a 16-way "insert select ... union select ..." */

	/* select 'XXX starting data analysis' */

	insert into #fkeysall
		select
			r.rkeyid,
			r.rkey1, r.rkey2, r.rkey3, r.rkey4,
				r.rkey5, r.rkey6, r.rkey7, r.rkey8,
				r.rkey9, r.rkey10, r.rkey11, r.rkey12,
				r.rkey13, r.rkey14, r.rkey15, r.rkey16,
			r.fkeyid,
			r.fkey1, r.fkey2, r.fkey3, r.fkey4,
				r.fkey5, r.fkey6, r.fkey7, r.fkey8,
				r.fkey9, r.fkey10, r.fkey11, r.fkey12,
				r.fkey13, r.fkey14, r.fkey15, r.fkey16,
			r.constid,
			i.name
		from
			sysreferences r, sysobjects o, sysindexes i
		where	r.constid = o.id
			AND o.xtype = 'F'
			AND r.rkeyindid = i.indid
			AND r.rkeyid = i.id
			AND r.rkeyid between isnull(@pktable_id, 0)
							and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0)
							and isnull(@fktable_id, 0x7fffffff)

	/* select count (*) as 'XXX countall' from #fkeysall */

    insert into #fkeys
			select rkeyid, rkey1, fkeyid, fkey1, 1, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey2, fkeyid, fkey2, 2, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey3, fkeyid, fkey3, 3, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey4, fkeyid, fkey4, 4, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey5, fkeyid, fkey5, 5, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey6, fkeyid, fkey6, 6, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey7, fkeyid, fkey7, 7, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey8, fkeyid, fkey8, 8, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey9, fkeyid, fkey9, 9, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey10, fkeyid, fkey10, 10, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey11, fkeyid, fkey11, 11, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey12, fkeyid, fkey12, 12, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey13, fkeyid, fkey13, 13, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey14, fkeyid, fkey14, 14, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey15, fkeyid, fkey15, 15, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey16, fkeyid, fkey16, 16, constid, name
			from #fkeysall

	/* select count (*) as 'XXX count' from #fkeys */

	insert into #fkeysout
		select
			PKTABLE_QUALIFIER = convert(sysname,db_name()),
			PKTABLE_OWNER = convert(sysname,USER_NAME(o1.uid)),
			PKTABLE_NAME = convert(sysname,o1.name),
			PKCOLUMN_NAME = convert(sysname,c1.name),
			FKTABLE_QUALIFIER = convert(sysname,db_name()),
			FKTABLE_OWNER = convert(sysname,USER_NAME(o2.uid)),
			FKTABLE_NAME = convert(sysname,o2.name),
			FKCOLUMN_NAME = convert(sysname,c2.name),
			KEY_SEQ,
			UPDATE_RULE = CASE WHEN (ObjectProperty(fk_id, 'CnstIsUpdateCascade')=1) THEN 
				convert(smallint,0) ELSE convert(smallint,1) END,
			DELETE_RULE = CASE WHEN (ObjectProperty(fk_id, 'CnstIsDeleteCascade')=1) THEN 
				convert(smallint,0) ELSE convert(smallint,1) END,
			FK_NAME = convert(sysname,OBJECT_NAME(fk_id)),
			PK_NAME,
			DEFERRABILITY = 7	/* SQL_NOT_DEFERRABLE */
		from #fkeys f,
			sysobjects o1, sysobjects o2,
			syscolumns c1, syscolumns c2
		where	o1.id = f.pktable_id
			AND o2.id = f.fktable_id
			AND c1.id = f.pktable_id
			AND c2.id = f.fktable_id
			AND c1.colid = f.pkcolid
			AND c2.colid = f.fkcolid
	/* select count (*) as 'XXX countout' from #fkeysout */

	if @order_by_pk = 1 /*	If order by PK fields */
		select
			PKTABLE_QUALIFIER, PKTABLE_OWNER, PKTABLE_NAME, PKCOLUMN_NAME,
			FKTABLE_QUALIFIER, FKTABLE_OWNER, FKTABLE_NAME, FKCOLUMN_NAME,
			KEY_SEQ, UPDATE_RULE, DELETE_RULE, FK_NAME, PK_NAME, DEFERRABILITY
		from #fkeysout
		order by 1,2,3,9,4
	else		/*	Order by FK fields */
		select
			PKTABLE_QUALIFIER, PKTABLE_OWNER, PKTABLE_NAME, PKCOLUMN_NAME,
			FKTABLE_QUALIFIER, FKTABLE_OWNER, FKTABLE_NAME, FKCOLUMN_NAME,
			KEY_SEQ, UPDATE_RULE, DELETE_RULE, FK_NAME, PK_NAME, DEFERRABILITY
		from #fkeysout
		order by 5,6,7,9,8
go

if (charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_fkeys
go

/*	Procedure for 8.0 server */
CREATE PROCEDURE sp_fkeys(
			   @pktable_name		sysname = null,
			   @pktable_owner		sysname = null,
			   @pktable_qualifier	sysname = null,
			   @fktable_name		sysname = null,
			   @fktable_owner		sysname = null,
			   @fktable_qualifier	sysname = null )
as
	set nocount on
	DECLARE @pktable_id			int
	DECLARE @pkfull_table_name	nvarchar(257) /* 2*128 + 1 */
	DECLARE @fktable_id			int
	DECLARE @fkfull_table_name	nvarchar(257) /* 2*128 + 1 */
	declare	@order_by_pk		int

	/* select 'XXX starting table creation' */

	create table #fkeysall(
			rkeyid int NOT NULL,
			rkey1 int NOT NULL,
				rkey2 int NOT NULL,
				rkey3 int NOT NULL,
				rkey4 int NOT NULL,
				rkey5 int NOT NULL,
				rkey6 int NOT NULL,
				rkey7 int NOT NULL,
				rkey8 int NOT NULL,
				rkey9 int NOT NULL,
				rkey10 int NOT NULL,
				rkey11 int NOT NULL,
				rkey12 int NOT NULL,
				rkey13 int NOT NULL,
				rkey14 int NOT NULL,
				rkey15 int NOT NULL,
				rkey16 int NOT NULL,
			fkeyid int NOT NULL,
			fkey1 int NOT NULL,
				fkey2 int NOT NULL,
				fkey3 int NOT NULL,
				fkey4 int NOT NULL,
				fkey5 int NOT NULL,
				fkey6 int NOT NULL,
				fkey7 int NOT NULL,
				fkey8 int NOT NULL,
				fkey9 int NOT NULL,
				fkey10 int NOT NULL,
				fkey11 int NOT NULL,
				fkey12 int NOT NULL,
				fkey13 int NOT NULL,
				fkey14 int NOT NULL,
				fkey15 int NOT NULL,
				fkey16 int NOT NULL,
			constid int NOT NULL,
			name sysname collate database_default NOT NULL)

	create table #fkeys(
			pktable_id		int NOT NULL,
			pkcolid 		int NOT NULL,
			fktable_id		int NOT NULL,
			fkcolid 		int NOT NULL,
			KEY_SEQ 		smallint NOT NULL,
			fk_id			int NOT NULL,
			PK_NAME			sysname collate database_default NOT NULL)

	create table #fkeysout(
			PKTABLE_QUALIFIER sysname collate database_default NULL,
			PKTABLE_OWNER sysname collate database_default NULL,
			PKTABLE_NAME sysname collate database_default NOT NULL,
			PKCOLUMN_NAME sysname collate database_default NOT NULL,
			FKTABLE_QUALIFIER sysname collate database_default NULL,
			FKTABLE_OWNER sysname collate database_default NULL,
			FKTABLE_NAME sysname collate database_default NOT NULL,
			FKCOLUMN_NAME sysname collate database_default NOT NULL,
			KEY_SEQ smallint NOT NULL,
			UPDATE_RULE smallint NULL,
			DELETE_RULE smallint NULL,
			FK_NAME sysname collate database_default NULL,
			PK_NAME sysname collate database_default NULL,
			DEFERRABILITY smallint null)

	/* select 'XXX starting parameter analysis' */

    select  @order_by_pk = 0

	if (@pktable_name is null) and (@fktable_name is null)
	begin	/* If neither primary key nor foreign key table names given */
		raiserror (15252,-1,-1)
		return
    end
	if @fktable_qualifier is not null
    begin
		if db_name() <> @fktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @pktable_qualifier is not null
    begin
		if db_name() <> @pktable_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end

	if @pktable_owner is null
	begin	/* If unqualified primary key table name */
		SELECT @pkfull_table_name = quotename(@pktable_name)
    end
    else
	begin	/* Qualified primary key table name */
		if @pktable_owner = ''
		begin	/* If empty owner name */
			SELECT @pkfull_table_name = quotename(@pktable_owner)
		end
		else
		begin
			SELECT @pkfull_table_name = quotename(@pktable_owner) +
				'.' + quotename(@pktable_name)
		end
    end
	/*	Get Object ID */
	SELECT @pktable_id = object_id(@pkfull_table_name)

	if @fktable_owner is null
	begin	/* If unqualified foreign key table name */
		SELECT @fkfull_table_name = quotename(@fktable_name)
    end
    else
	begin	/* Qualified foreign key table name */
		if @fktable_owner = ''
		begin	/* If empty owner name */
			SELECT @fkfull_table_name = quotename(@fktable_owner)
		end
		else
		begin
			SELECT @fkfull_table_name = quotename(@fktable_owner) +
				'.' + quotename(@fktable_name)
		end
    end
	/*	Get Object ID */
	SELECT @fktable_id = object_id(@fkfull_table_name)

	if @fktable_name is not null
	begin
		if @fktable_id is null
			SELECT @fktable_id = 0	/* fk table not found, empty result */
    end

	if @pktable_name is null
	begin /*  If table name not supplied, match all */
		select @order_by_pk = 1
	end
	else
	begin
		if @pktable_id is null
		begin
			SELECT @pktable_id = 0	/* pk table not found, empty result */
		end
	end

	/*	SQL Server supports upto 16 PK/FK relationships between 2 tables */
	/*	Process syskeys for each relationship */
	/*  First, attempt to get all 16 keys for each rel'ship, then sort
		them out with a 16-way "insert select ... union select ..." */

	/* select 'XXX starting data analysis' */

	insert into #fkeysall
		select
			r.rkeyid,
			r.rkey1, r.rkey2, r.rkey3, r.rkey4,
				r.rkey5, r.rkey6, r.rkey7, r.rkey8,
				r.rkey9, r.rkey10, r.rkey11, r.rkey12,
				r.rkey13, r.rkey14, r.rkey15, r.rkey16,
			r.fkeyid,
			r.fkey1, r.fkey2, r.fkey3, r.fkey4,
				r.fkey5, r.fkey6, r.fkey7, r.fkey8,
				r.fkey9, r.fkey10, r.fkey11, r.fkey12,
				r.fkey13, r.fkey14, r.fkey15, r.fkey16,
			r.constid,
			i.name
		from
			sysreferences r, sysobjects o, sysindexes i
		where	r.constid = o.id
			AND o.xtype = 'F'
			AND r.rkeyindid = i.indid
			AND r.rkeyid = i.id
			AND r.rkeyid between isnull(@pktable_id, 0)
							and isnull(@pktable_id, 0x7fffffff)
			AND r.fkeyid between isnull(@fktable_id, 0)
							and isnull(@fktable_id, 0x7fffffff)

	/* select count (*) as 'XXX countall' from #fkeysall */

    insert into #fkeys
			select rkeyid, rkey1, fkeyid, fkey1, 1, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey2, fkeyid, fkey2, 2, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey3, fkeyid, fkey3, 3, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey4, fkeyid, fkey4, 4, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey5, fkeyid, fkey5, 5, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey6, fkeyid, fkey6, 6, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey7, fkeyid, fkey7, 7, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey8, fkeyid, fkey8, 8, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey9, fkeyid, fkey9, 9, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey10, fkeyid, fkey10, 10, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey11, fkeyid, fkey11, 11, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey12, fkeyid, fkey12, 12, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey13, fkeyid, fkey13, 13, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey14, fkeyid, fkey14, 14, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey15, fkeyid, fkey15, 15, constid, name
			from #fkeysall
		union all
			select rkeyid, rkey16, fkeyid, fkey16, 16, constid, name
			from #fkeysall

	/* select count (*) as 'XXX count' from #fkeys */

	insert into #fkeysout
		select
			PKTABLE_QUALIFIER = convert(sysname,db_name()),
			PKTABLE_OWNER = convert(sysname,USER_NAME(o1.uid)),
			PKTABLE_NAME = convert(sysname,o1.name),
			PKCOLUMN_NAME = convert(sysname,c1.name),
			FKTABLE_QUALIFIER = convert(sysname,db_name()),
			FKTABLE_OWNER = convert(sysname,USER_NAME(o2.uid)),
			FKTABLE_NAME = convert(sysname,o2.name),
			FKCOLUMN_NAME = convert(sysname,c2.name),
			KEY_SEQ,
			UPDATE_RULE = CASE WHEN (ObjectProperty(fk_id, 'CnstIsUpdateCascade')=1) THEN 
				convert(smallint,0) ELSE convert(smallint,1) END,
			DELETE_RULE = CASE WHEN (ObjectProperty(fk_id, 'CnstIsDeleteCascade')=1) THEN 
				convert(smallint,0) ELSE convert(smallint,1) END,
			FK_NAME = convert(sysname,OBJECT_NAME(fk_id)),
			PK_NAME,
			DEFERRABILITY = 7	/* SQL_NOT_DEFERRABLE */
		from #fkeys f,
			sysobjects o1, sysobjects o2,
			syscolumns c1, syscolumns c2
		where	o1.id = f.pktable_id
			AND o2.id = f.fktable_id
			AND c1.id = f.pktable_id
			AND c2.id = f.fktable_id
			AND c1.colid = f.pkcolid
			AND c2.colid = f.fkcolid
	/* select count (*) as 'XXX countout' from #fkeysout */

	if @order_by_pk = 1 /*	If order by PK fields */
		select
			PKTABLE_QUALIFIER, PKTABLE_OWNER, PKTABLE_NAME, PKCOLUMN_NAME,
			FKTABLE_QUALIFIER, FKTABLE_OWNER, FKTABLE_NAME, FKCOLUMN_NAME,
			KEY_SEQ, UPDATE_RULE, DELETE_RULE, FK_NAME, PK_NAME, DEFERRABILITY
		from #fkeysout
		order by 1,2,3,9,4
	else		/*	Order by FK fields */
		select
			PKTABLE_QUALIFIER, PKTABLE_OWNER, PKTABLE_NAME, PKCOLUMN_NAME,
			FKTABLE_QUALIFIER, FKTABLE_OWNER, FKTABLE_NAME, FKCOLUMN_NAME,
			KEY_SEQ, UPDATE_RULE, DELETE_RULE, FK_NAME, PK_NAME, DEFERRABILITY
		from #fkeysout
		order by 5,6,7,9,8
go
grant execute on sp_fkeys to public
go

dump tran master with no_log
go

print 'creating sp_pkeys'
go

/*	Procedure for pre-6.0 server */
CREATE PROCEDURE sp_pkeys(
			   @table_name		varchar(32),
			   @table_owner 	varchar(32) = null,
			   @table_qualifier varchar(32) = null )
as
	set nocount on
	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_5~~'
			return
		end
    end
	if @table_owner is null /*	If owner not supplied, match all */
		select @table_owner = '%'
	if @@trancount <> 0
	begin	/* If inside a transaction */
		raiserror 20003 '~~Rush_35~~'
		return
    end

	create table #pkeys(
			 TABLE_QUALIFIER varchar(32) NULL,
			 TABLE_OWNER	 varchar(32) NULL,
			 TABLE_NAME 	 varchar(32) NOT NULL,
			 COLUMN_NAME	 varchar(32) NOT NULL,
			 KEY_SEQ		 smallint NOT NULL)

	/*	SQL Server supports upto 8 PK/FK relationships between 2 tables */
	/*	Process syskeys for each relationship */
	/*	The inserts below adds a row to the temp table for each of the
		8 possible relationships */
    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			1
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = k.key1
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			2
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = key2
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			3
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = key3
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			4
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = key4
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			5
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = key5
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			6
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = key6
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		select
			db_name(),
			(select user_name(uid) from sysobjects o where o.id = k.id),
			object_name(k.id),
			c.name,
			7
		from
			syskeys k, syscolumns c
		where
			c.id = k.id
			and k.type = 1	/* Primary type key */
			and c.colid = key7
    if (@@rowcount = 0)
		goto done

    insert into #pkeys
		 select
			 db_name(),
			 (select user_name(uid) from sysobjects o where o.id = k.id),
			 object_name(k.id),
			 c.name,
			 8
		 from
			 syskeys k, syscolumns c
		 where
			 c.id = k.id
			 and k.type = 1 /* Primary type key */
			 and c.colid = key8

    done:
    select
		TABLE_QUALIFIER,
		TABLE_OWNER,
		TABLE_NAME,
		COLUMN_NAME,
		KEY_SEQ,
		PK_NAME = convert(varchar(32),null)
	from #pkeys
	where TABLE_NAME = @table_name
		and TABLE_OWNER like @table_owner
	order by 1, 2, 3, 5
go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following error.'
end
else
	drop proc sp_pkeys
go

/*	Procedure for 6.0 and 6.50 servers */
CREATE PROCEDURE sp_pkeys(
			   @table_name		sysname,
			   @table_owner 	sysname = null,
			   @table_qualifier sysname = null )
as
	DECLARE @table_id			int
	DECLARE @full_table_name	varchar(255) /* 2*128 + 1 */

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @table_owner is null
	begin	/* If unqualified table name */
		SELECT @full_table_name = @table_name
    end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = @table_owner
		end
		else
		begin
			SELECT @full_table_name = @table_owner + '.' + @table_name
		end
    end
	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)

    select
		TABLE_QUALIFIER = convert(sysname,db_name()),
		TABLE_OWNER = convert(sysname,user_name(o.uid)),
		TABLE_NAME = convert(sysname,o.name),
		COLUMN_NAME = convert(sysname,c.name),
		KEY_SEQ = convert(smallint,c1.colid),
		PK_NAME = convert(sysname,i.name)
	from
		sysindexes i, syscolumns c, sysobjects o, syscolumns c1
	where
		o.id = @table_id
		and o.id = c.id
		and o.id = i.id
		and (i.status & 0x800) = 0x800
		and c.name = index_col (@full_table_name, i.indid, c1.colid)
		and c1.colid <= i.keycnt	/* create rows from 1 to keycnt */
		and c1.id = @table_id
	order by 1, 2, 3, 5
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_pkeys
go

/*	Procedure for 8.0 server */
CREATE PROCEDURE sp_pkeys(
			   @table_name		sysname,
			   @table_owner 	sysname = null,
			   @table_qualifier sysname = null )
as
	DECLARE @table_id		int
	DECLARE @full_table_name	nvarchar(255)

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @table_owner is null
	begin	/* If unqualified table name */
		SELECT @full_table_name = quotename(@table_name)
    end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
    end
	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)

    select
		TABLE_QUALIFIER = convert(sysname,db_name()),
		TABLE_OWNER = convert(sysname,user_name(o.uid)),
		TABLE_NAME = convert(sysname,o.name),
		COLUMN_NAME = convert(sysname,c.name),
		--KEY_SEQ = convert(smallint,c.colid),
		KEY_SEQ =
			case
				when c.name = index_col(@full_table_name, i.indid,  1) then convert (smallint,1)
				when c.name = index_col(@full_table_name, i.indid,  2) then convert (smallint,2)
				when c.name = index_col(@full_table_name, i.indid,  3) then convert (smallint,3)
				when c.name = index_col(@full_table_name, i.indid,  4) then convert (smallint,4)
				when c.name = index_col(@full_table_name, i.indid,  5) then convert (smallint,5)
				when c.name = index_col(@full_table_name, i.indid,  6) then convert (smallint,6)
				when c.name = index_col(@full_table_name, i.indid,  7) then convert (smallint,7)
				when c.name = index_col(@full_table_name, i.indid,  8) then convert (smallint,8)
				when c.name = index_col(@full_table_name, i.indid,  9) then convert (smallint,9)
				when c.name = index_col(@full_table_name, i.indid, 10) then convert (smallint,10)
				when c.name = index_col(@full_table_name, i.indid, 11) then convert (smallint,11)
				when c.name = index_col(@full_table_name, i.indid, 12) then convert (smallint,12)
				when c.name = index_col(@full_table_name, i.indid, 13) then convert (smallint,13)
				when c.name = index_col(@full_table_name, i.indid, 14) then convert (smallint,14)
				when c.name = index_col(@full_table_name, i.indid, 15) then convert (smallint,15)
				when c.name = index_col(@full_table_name, i.indid, 16) then convert (smallint,16)
			end,
		PK_NAME = convert(sysname,i.name)
	from
		sysindexes i, syscolumns c, sysobjects o --, syscolumns c1
	where
		o.id = @table_id
		and o.id = c.id
		and o.id = i.id
		and (i.status & 0x800) = 0x800
		--and c.name = index_col (@full_table_name, i.indid, c1.colid)
		and (c.name = index_col (@full_table_name, i.indid,  1) or
		     c.name = index_col (@full_table_name, i.indid,  2) or
		     c.name = index_col (@full_table_name, i.indid,  3) or
		     c.name = index_col (@full_table_name, i.indid,  4) or
		     c.name = index_col (@full_table_name, i.indid,  5) or
		     c.name = index_col (@full_table_name, i.indid,  6) or
		     c.name = index_col (@full_table_name, i.indid,  7) or
		     c.name = index_col (@full_table_name, i.indid,  8) or
		     c.name = index_col (@full_table_name, i.indid,  9) or
		     c.name = index_col (@full_table_name, i.indid, 10) or
		     c.name = index_col (@full_table_name, i.indid, 11) or
		     c.name = index_col (@full_table_name, i.indid, 12) or
		     c.name = index_col (@full_table_name, i.indid, 13) or
		     c.name = index_col (@full_table_name, i.indid, 14) or
		     c.name = index_col (@full_table_name, i.indid, 15) or
		     c.name = index_col (@full_table_name, i.indid, 16)
		    )
		--and c1.colid <= i.keycnt	/* create rows from 1 to keycnt */
		--and c1.id = @table_id
	order by 1, 2, 3, 5
go


grant execute on sp_pkeys to public
go

dump tran master with no_log
go

print 'creating sp_server_info'
go

create proc sp_server_info (
			@attribute_id  int = null)
as
    if @attribute_id is not null
		select *
		from master.dbo.spt_server_info
		where attribute_id = @attribute_id
    else
		select *
		from master.dbo.spt_server_info
		order by attribute_id
go

grant execute on sp_server_info to public
go

dump tran master with no_log
go

print 'creating sp_special_columns'
go

/*	Procedure for pre-6.0 server */
CREATE PROCEDURE sp_special_columns (
				 @table_name		varchar(32),
				 @table_owner		varchar(32) = null,
				 @table_qualifier	varchar(32) = null,
				 @col_type			char(1) = 'R',
				 @scope				char(1) = 'T',
				 @nullable			char(1) = 'U',
				 @ODBCVer			int = 2)
AS
	DECLARE @indid				int
	DECLARE @table_id			int
	DECLARE @full_table_name	varchar(65) /* 2*32+1 */
	DECLARE @scopeout			smallint

	if @col_type not in ('R','V') or @col_type is null
	begin
		raiserror 20002 '~~Rush_42~~'
		return
	end

	if @scope = 'C'
		select @scopeout = 0
	else if @scope = 'T'
		select @scopeout = 1
	else
	begin
		raiserror 20002 '~~Rush_43~~'
		return
	end

	if @nullable not in ('U','O') or @nullable is null
	begin
		raiserror 20002 '~~Rush_44~~'
		return
	end

	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin /* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_5~~'
			return
		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,NULL),
			COLUMN_NAME = convert(varchar(32),c.name),
			DATA_TYPE = convert(smallint, -3),
			TYPE_NAME = t.name,
			"PRECISION" = convert(int,8),
			LENGTH = convert(int,8),
			SCALE = convert(smallint, NULL),
			PSEUDO_COLUMN = convert(smallint,1)
		FROM
			systypes t, syscolumns c
		WHERE
			c.id = @table_id
			AND c.usertype = 80 /*	TIMESTAMP */
			AND t.usertype = 80 /*	TIMESTAMP */
		RETURN
	END

	/* ROWID, now find the id of the 'best' index for this table */

	IF @nullable = 'O'	/* Don't include any indexes that contain
						   nullable columns. */

			SELECT @indid = MIN(indid)
				FROM sysindexes i,syscolumns c,syscolumns c2
				WHERE
					i.status&2 = 2		/*	If Unique Index */
		 			AND c.id = i.id
		 			AND c2.id = c.id
		 			AND c2.colid < i.keycnt + (i.status&16)/16
					AND i.id = @table_id
					AND indid > 0		/*	Eliminate Table Row */
					AND c.name = index_col(@table_name,i.indid,c2.colid)
					GROUP BY indid HAVING SUM(c.status&8) = 0

	ELSE	/* Include indexes that are partially nullable. */

		SELECT @indid = MIN(indid)
			FROM sysindexes i
			WHERE
				status&2 = 2		/*	If Unique Index */
				AND id = @table_id
				AND indid > 0		/*	Eliminate Table Row */

	SELECT
		SCOPE = @scopeout,
		COLUMN_NAME = convert(varchar(32),INDEX_COL(@full_table_name,indid,c2.colid)),
		d.DATA_TYPE,
		TYPE_NAME = t.name,
		"PRECISION" = isnull(d.data_precision, convert(int,c.length)),
		LENGTH = isnull(d.length, convert(int,c.length)),
		SCALE = d.numeric_scale,
		PSEUDO_COLUMN = convert(smallint,1)
	FROM
		sysindexes x,
		syscolumns c,
		master.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 c.name = INDEX_COL(@full_table_name,@indid,c2.colid)
		AND c.id = x.id
		AND c2.id = x.id
		AND c2.colid < keycnt+(x.status&16)/16
		AND x.indid = @indid
		AND t.type = d.ss_dtype
		AND c.length = d.fixlen
		AND c.usertype = t.usertype

go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_special_columns
go

/*	Procedure for 6.0 and 6.50 servers */
CREATE PROCEDURE sp_special_columns (
				 @table_name		varchar(32),
				 @table_owner		varchar(32) = null,
				 @table_qualifier	varchar(32) = null,
				 @col_type			char(1) = 'R',
				 @scope				char(1) = 'T',
				 @nullable			char(1) = 'U',
				 @ODBCVer			int = 2)
AS
	DECLARE @indid				int
	DECLARE @table_id			int
	DECLARE @full_table_name	varchar(65) /* 2*32+1 */
	DECLARE @scopeout			smallint

	if @col_type not in ('R','V') or @col_type is null
	begin
		raiserror (15251,-1,-1,'col_type','''R'' or ''V''')
		return
	end

	if @scope = 'C'
		select @scopeout = 0
	else if @scope = 'T'
		select @scopeout = 1
	else
	begin
		raiserror (15251,-1,-1,'scope','''C'' or ''T''')
		return
	end

	if @nullable not in ('U','O') or @nullable is null
	begin
		raiserror (15251,-1,-1,'nullable','''U'' or ''O''')
		return
	end

	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin /* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		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,NULL),
			COLUMN_NAME = convert(varchar(32),c.name),
			DATA_TYPE = convert(smallint, -2),
			TYPE_NAME = t.name,
			"PRECISION" = convert(int,8),
			LENGTH = convert(int,8),
			SCALE = convert(smallint, NULL),
			PSEUDO_COLUMN = convert(smallint,1)
		FROM
			systypes t, syscolumns c
		WHERE
			c.id = @table_id
			AND c.usertype = 80 /*	TIMESTAMP */
			AND t.usertype = 80 /*	TIMESTAMP */
		RETURN
	END

	/* ROWID, now find the id of the 'best' index for this table */

	IF @nullable = 'O'	/* Don't include any indexes that contain
						   nullable columns. */

		SELECT @indid = MIN(indid)
			FROM sysindexes i,syscolumns c,syscolumns c2
			WHERE
				i.status&2 = 2		/*	If Unique Index */
				AND c.id = i.id
				AND c2.id = c.id
				AND c2.colid < i.keycnt + (i.status&16)/16
				AND i.id = @table_id
				AND indid > 0		/*	Eliminate Table Row */
				AND c.name = index_col(@table_name,i.indid,c2.colid)
				GROUP BY indid HAVING SUM(c.status&8) = 0

	ELSE	/* Include indexes that are partially nullable. */

		SELECT @indid = MIN(indid)
			FROM sysindexes i
			WHERE
				status&2 = 2		/*	If Unique Index */
				AND id = @table_id
				AND indid > 0		/*	Eliminate Table Row */

	SELECT
		SCOPE = @scopeout,
		COLUMN_NAME = convert(varchar(32),INDEX_COL(@full_table_name,indid,c2.colid)),
		d.DATA_TYPE,
		convert(varchar(32),case
			when (t.usertype > 100 or t.usertype in (18,80))
				then t.name
			else d.TYPE_NAME
		end) TYPE_NAME,
		convert(int,case
			when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
			else isnull(convert(int,c.prec), 2147483647)
		end) "PRECISION",
		convert(int,case
			when d.ss_dtype IN (106, 108, 55, 63) then	/* decimal/numeric types */
				convert(int,c.prec+2)
			else
				isnull(d.length, c.length)
		end) LENGTH,
		SCALE = convert(smallint, c.scale),
		PSEUDO_COLUMN = convert(smallint,1)
	FROM
		sysindexes x,
		syscolumns c,
		master.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 c.name = INDEX_COL(@full_table_name,@indid,c2.colid)
		AND c.id = x.id
		AND c2.id = x.id
		AND c2.colid < x.keycnt+(x.status&16)/16
		AND x.indid = @indid
		AND t.type = d.ss_dtype
		AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
		AND isnull(d.AUTO_INCREMENT,0) = (c.status&128)/128
		AND c.usertype = t.usertype
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_special_columns
go

/*	Procedure for 7.0 servers */
CREATE PROCEDURE sp_special_columns (
				 @table_name		sysname,
				 @table_owner		sysname = null,
				 @table_qualifier	sysname = null,
				 @col_type			char(1) = 'R',
				 @scope				char(1) = 'T',
				 @nullable			char(1) = 'U',
				 @ODBCVer			int = 2)
AS
	DECLARE @indid				int
	DECLARE @table_id			int
	DECLARE @full_table_name	nvarchar(257)
	DECLARE @scopeout			smallint

	if @col_type not in ('R','V') or @col_type is null
	begin
		raiserror (15251,-1,-1,'col_type','''R'' or ''V''')
		return
	end

	if @scope = 'C'
		select @scopeout = 0
	else if @scope = 'T'
		select @scopeout = 1
	else
	begin
		raiserror (15251,-1,-1,'scope','''C'' or ''T''')
		return
	end

	if @nullable not in ('U','O') or @nullable is null
	begin
		raiserror (15251,-1,-1,'nullable','''U'' or ''O''')
		return
	end

	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin /* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
	end
	if @table_owner is null
	begin	 /* If unqualified table name */
		SELECT @full_table_name = quotename(@table_name)
	end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
    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,NULL),
			COLUMN_NAME = convert(sysname,c.name),
			DATA_TYPE = convert(smallint, -2),
			TYPE_NAME = t.name,
			"PRECISION" = convert(int,8),
			LENGTH = convert(int,8),
			SCALE = convert(smallint, NULL),
			PSEUDO_COLUMN = convert(smallint,1)
		FROM
			systypes t, syscolumns c
		WHERE
			not (@table_id is null)
			AND c.id = @table_id
			AND t.name = 'timestamp'	/*	TIMESTAMP  */
			AND t.xtype = c.xtype		
			AND t.xusertype = c.xusertype	
		RETURN
	END

	/* ROWID, now find the id of the 'best' index for this table */

	IF @nullable = 'O'	/* Don't include any indexes that contain
						   nullable columns. */

		SELECT @indid = MIN(indid)
			FROM sysindexes x, syscolumns c, syscolumns c2
			WHERE
				not (@table_id is null)
				AND x.status&2 = 2		/*	If Unique Index */
				AND c.id = x.id
				AND c2.id = c.id
				AND c2.colid < x.keycnt + (x.status&16)/16
				AND x.id = @table_id
				AND indid > 0		/*	Eliminate Table Row */
				AND c.name = index_col(@table_name,x.indid,c2.colid)
				GROUP BY indid HAVING SUM(c.status&8) = 0

	ELSE	/* Include indexes that are partially nullable. */

		SELECT @indid = MIN(indid)
			FROM sysindexes x
			WHERE
				not (@table_id is null)
				AND status&2 = 2		/*	If Unique Index */
				AND id = @table_id
				AND indid > 0		/*	Eliminate Table Row */

	SELECT
		SCOPE = @scopeout,
		COLUMN_NAME = convert(sysname,INDEX_COL(@full_table_name,indid,c2.colid)),
		d.DATA_TYPE,
		convert(sysname,case
			when t.xusertype > 255 then t.name
			else d.TYPE_NAME
		end) TYPE_NAME,
		convert(int,case
			when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
			else OdbcPrec(c.xtype,c.length,c.xprec)
		end) "PRECISION",
		convert(int,case
			when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
				OdbcPrec(c.xtype,c.length,c.xprec)+2
			else isnull(d.length, c.length)
		end) LENGTH,
		SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
		PSEUDO_COLUMN = convert(smallint,1)
	FROM
		sysindexes x,
		syscolumns c,
		master.dbo.spt_datatype_info d,
		systypes t,
		syscolumns c2	/* Self-join to generate list of index columns and */
						/* to extract datatype names */
	WHERE
		not (@table_id is null)
		AND x.id = @table_id
		AND c.name = INDEX_COL(@full_table_name,@indid,c2.colid)
		AND c.id = x.id
		AND c2.id = x.id
		AND c2.colid < x.keycnt + (x.status&16)/16
		AND x.indid = @indid
		AND t.xtype = d.ss_dtype
		AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
		AND isnull(d.AUTO_INCREMENT,0) = isnull(ColumnProperty (c.id, c.name, 'IsIdentity'),0)
		AND c.xusertype = t.xusertype
go

if (charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_special_columns
go

/*	Procedure for 8.0 and later servers */
CREATE PROCEDURE sp_special_columns (
				 @table_name		sysname,
				 @table_owner		sysname = null,
				 @table_qualifier	sysname = null,
				 @col_type			char(1) = 'R',
				 @scope				char(1) = 'T',
				 @nullable			char(1) = 'U',
				 @ODBCVer			int = 2)
AS
	DECLARE @indid				int
	DECLARE @table_id			int
	DECLARE @full_table_name	nvarchar(257)
	DECLARE @scopeout			smallint

	if @col_type not in ('R','V') or @col_type is null
	begin
		raiserror (15251,-1,-1,'col_type','''R'' or ''V''')
		return
	end

	if @scope = 'C'
		select @scopeout = 0
	else if @scope = 'T'
		select @scopeout = 1
	else
	begin
		raiserror (15251,-1,-1,'scope','''C'' or ''T''')
		return
	end

	if @nullable not in ('U','O') or @nullable is null
	begin
		raiserror (15251,-1,-1,'nullable','''U'' or ''O''')
		return
	end

	if @table_qualifier is not null
	begin
		if db_name() <> @table_qualifier
		begin /* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
	end
	if @table_owner is null
	begin	 /* If unqualified table name */
		SELECT @full_table_name = quotename(@table_name)
	end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
    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,NULL),
			COLUMN_NAME = convert(sysname,c.name),
			DATA_TYPE = convert(smallint, -2),
			TYPE_NAME = t.name,
			"PRECISION" = convert(int,8),
			LENGTH = convert(int,8),
			SCALE = convert(smallint, NULL),
			PSEUDO_COLUMN = convert(smallint,1)
		FROM
			systypes t, syscolumns c
		WHERE
			not (@table_id is null)
			AND c.id = @table_id
			AND t.name = 'timestamp'	/*	TIMESTAMP  */
			AND t.xtype = c.xtype		
			AND t.xusertype = c.xusertype	
		RETURN
	END

	/* ROWID, now find the id of the 'best' index for this table */

	IF @nullable = 'O'	/* Don't include any indexes that contain
						   nullable columns. */

		SELECT @indid = MIN(indid)
			FROM sysindexes x, syscolumns c, syscolumns c2
			WHERE
				not (@table_id is null)
				AND x.status&2 = 2		/*	If Unique Index */
				AND c.id = x.id
				AND c2.id = c.id
				AND c2.colid < x.keycnt + (x.status&18)/18
				AND x.id = @table_id
				AND indid > 0		/*	Eliminate Table Row */
				AND c.name = index_col(@table_name,x.indid,c2.colid)
				GROUP BY indid HAVING SUM(c.status&8) = 0

	ELSE	/* Include indexes that are partially nullable. */

		SELECT @indid = MIN(indid)
			FROM sysindexes x
			WHERE
				not (@table_id is null)
				AND status&2 = 2		/*	If Unique Index */
				AND id = @table_id
				AND indid > 0		/*	Eliminate Table Row */

	SELECT
		SCOPE = @scopeout,
		COLUMN_NAME = convert(sysname,INDEX_COL(@full_table_name,indid,c2.colid)),
		d.DATA_TYPE,
		convert(sysname,case
			when t.xusertype > 255 then t.name
			else d.TYPE_NAME collate database_default
		end) TYPE_NAME,
		convert(int,case
			when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
			else OdbcPrec(c.xtype,c.length,c.xprec)
		end) "PRECISION",
		convert(int,case
			when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
				OdbcPrec(c.xtype,c.length,c.xprec)+2
			else isnull(d.length, c.length)
		end) LENGTH,
		SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
		PSEUDO_COLUMN = convert(smallint,1)
	FROM
		sysindexes x,
		syscolumns c,
		master.dbo.spt_datatype_info d,
		systypes t,
		syscolumns c2	/* Self-join to generate list of index columns and */
						/* to extract datatype names */
	WHERE
		not (@table_id is null)
		AND x.id = @table_id
		AND c.name = INDEX_COL(@full_table_name,@indid,c2.colid)
		AND c.id = x.id
		AND c2.id = x.id
		AND c2.colid < x.keycnt + (x.status&16)/16
		AND x.indid = @indid
		AND t.xtype = d.ss_dtype
		AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
		AND isnull(d.AUTO_INCREMENT,0) = isnull(ColumnProperty (c.id, c.name, 'IsIdentity'),0)
		AND c.xusertype = t.xusertype
go

grant execute on sp_special_columns to public
go

dump tran master with no_log
go

print 'creating sp_sproc_columns'
go

/*	Procedure for pre-6.0 server */
CREATE PROCEDURE sp_sproc_columns (
				 @procedure_name		varchar(102) = '%', /* 3*32+5+1 */
				 @procedure_owner		varchar(96) = null,
				 @procedure_qualifier	varchar(32) = null,
				 @column_name			varchar(96) = null,
				 @ODBCVer				int = 2)
AS
    DECLARE @group_num_lower smallint
    DECLARE @group_num_upper smallint
    DECLARE @semi_position int
	DECLARE @full_procedure_name	varchar(205)/* 2*102+1 */
    DECLARE @procedure_id int

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	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	/* If qualifier doesn't match current database */
				raiserror 20001 '~~Rush_51~~'
				return
			end
		end
    end

	if @procedure_name is null
	begin	/*	If procedure name not supplied, match all */
		select @procedure_name = '%'
	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_lower = convert(int,substring(@procedure_name, @semi_position + 1, 2))
		select @group_num_upper = @group_num_lower
		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_lower = 1
		select @group_num_upper = 32767			
    end

	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

	/*	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 */
		SELECT
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(varchar(32),c.name),
			COLUMN_TYPE = convert(smallint, 0),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			"PRECISION" = isnull(d.data_precision, convert(int,c.length)),
			LENGTH = isnull(d.length, convert(int,c.length)),
			SCALE = d.numeric_scale,
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),null),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.data_precision, convert(int,c.length))+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND t.type = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND c.usertype = t.usertype
			AND c.name like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ isnull(ltrim(str(c.number,5)),'1')),
			COLUMN_NAME = convert(varchar(32),'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(varchar(32),'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.colid = 1
			AND o.type = 'P'						/* Just Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper		
		ORDER BY 1, 2, 3, 18
	end
	else
    begin
		/* this block is for the case where there IS pattern
			matching done on the procedure name */
		if @procedure_owner is null
			select @procedure_owner = '%'
		SELECT
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(varchar(32),c.name),
			COLUMN_TYPE = convert(smallint, 0),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			"PRECISION" = isnull(d.data_precision, convert(int,c.length)),
			LENGTH = isnull(d.length, convert(int,c.length)),
			SCALE = d.numeric_scale,
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),null),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.data_precision, convert(int,c.length))+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.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 t.type = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND c.usertype = t.usertype
			AND o.type = 'P'							/* Just Procedures */
			AND c.name like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ isnull(ltrim(str(c.number,5)),'1')),
			COLUMN_NAME = convert(varchar(32),'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(varchar(32),'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.name like @procedure_name
			AND user_name(o.uid) like @procedure_owner
			AND c.id = o.id
			AND c.colid = 1
			AND o.type = 'P'						/* Just Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		ORDER BY 1, 2, 3, 18
	end
go

if (charindex('6.00', @@version) = 0 and
	charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.0 SQL Server.'
	print 'Ignore the following error.'
end
else
	drop proc sp_sproc_columns
go

/*	Procedure for 6.0 and 6.50 servers */
CREATE PROCEDURE sp_sproc_columns (
				 @procedure_name		varchar(102) = '%', /* 3*36+5+1 */
				 @procedure_owner		varchar(96) = null,
				 @procedure_qualifier	varchar(32) = null,
				 @column_name			varchar(96) = null,
				 @ODBCVer				int = 2)
AS
    DECLARE @group_num_lower smallint
    DECLARE @group_num_upper smallint
    DECLARE @semi_position int
	DECLARE @full_procedure_name	varchar(205)
    DECLARE @procedure_id int

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	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	/* If qualifier doesn't match current database */
				raiserror (15250, -1,-1)
				return
			end
		end
    end

	if @procedure_name is null
	begin	/*	If procedure name not supplied, match all */
		select @procedure_name = '%'
	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_lower = convert(int,substring(@procedure_name, @semi_position + 1, 2))
		select @group_num_upper = @group_num_lower
		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_lower = 1
		select @group_num_upper = 32767			
    end

	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

	/*	Get Object ID */
	SELECT @procedure_id = object_id(@full_procedure_name)
	if ((charindex('%',@full_procedure_name) = 0) and
		(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 */
		SELECT
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(varchar(32),c.name),
			COLUMN_TYPE = convert(smallint, 1+((c.status/64)&1)),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else isnull(convert(int,c.prec), 2147483647)
			end) "PRECISION",
			convert(int,case
				when d.ss_dtype IN (106, 108, 55, 63) then	/* decimal/numeric types */
					c.prec+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, c.scale),
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(convert(int,c.prec), 2147483647)+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.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.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.usertype = t.usertype
			AND c.name like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ isnull(ltrim(str(c.number,5)),'1')),
			COLUMN_NAME = convert(varchar(32),'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(varchar(32),'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.colid = 1
			AND o.type = 'P'						/* Just Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		ORDER BY 1, 2, 3, 18
	end
	else
    begin
		/* this block is for the case where there IS pattern
			matching done on the procedure name */
		if @procedure_owner is null
			select @procedure_owner = '%'
		SELECT
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(varchar(32),c.name),
			COLUMN_TYPE = convert(smallint, 1+((c.status/64)&1)),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else isnull(convert(int,c.prec), 2147483647)
			end) "PRECISION",
			convert(int,case
				when d.ss_dtype IN (106, 108, 55, 63) then	/* decimal/numeric types */
					c.prec+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, c.scale),
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(convert(int,c.prec), 2147483647)+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.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.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.usertype = t.usertype
			AND o.type = 'P'							/* Just Procedures */
			AND c.name like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(varchar(32),DB_NAME()),
			PROCEDURE_OWNER = convert(varchar(32),USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(varchar(36),o.name +';'+ isnull(ltrim(str(c.number,5)),'1')),
			COLUMN_NAME = convert(varchar(32),'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(varchar(32),'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(varchar(255),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.name like @procedure_name
			AND user_name(o.uid) like @procedure_owner
			AND c.id = o.id
			AND c.colid = 1
			AND o.type = 'P'						/* Just Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		ORDER BY 1, 2, 3, 18
	end
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_sproc_columns
go

/*	Procedure for 7.0 server */
CREATE PROCEDURE sp_sproc_columns (
				 @procedure_name		nvarchar(390) = '%',
				 @procedure_owner		nvarchar(384) = null,
				 @procedure_qualifier	sysname = null,
				 @column_name			nvarchar(384) = null,
				 @ODBCVer				int = 2)
AS
    DECLARE @group_num_lower smallint
    DECLARE @group_num_upper smallint
    DECLARE @semi_position int
	DECLARE @full_procedure_name	nvarchar(774)
    DECLARE @procedure_id int

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	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	/* If qualifier doesn't match current database */
				raiserror (15250, -1,-1)
				return
			end
		end
    end

	if @procedure_name is null
	begin	/*	If procedure name not supplied, match all */
		select @procedure_name = '%'
	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_lower = convert(int,substring(@procedure_name, @semi_position + 1, 2))
		select @group_num_upper = @group_num_lower
		select @procedure_name = substring(@procedure_name, 1, @semi_position -1)
    end
    else
	begin	/* No group separator, so default to all groups */
		select @group_num_lower = 1
		select @group_num_upper = 32767			
    end

	if @procedure_owner is null
	begin	/* If unqualified procedure name */
		SELECT @full_procedure_name = quotename(@procedure_name)
    end
    else
	begin	/* Qualified procedure name */
		if @procedure_owner = ''
		begin	/* If empty owner name */
			SELECT @full_procedure_name = quotename(@procedure_owner)
		end
		else
		begin
			SELECT @full_procedure_name = quotename(@procedure_owner) +
				'.' + quotename(@procedure_name)
		end
    end

	/*	Get Object ID */
	SELECT @procedure_id = object_id(@full_procedure_name)
	if ((isnull(charindex('%', @full_procedure_name),0) = 0) and
		(isnull(charindex('[', @procedure_name),0) = 0) and
		(isnull(charindex('[', @procedure_owner),0) = 0) and
		(isnull(charindex('_', @full_procedure_name),0) = 0) and
		not (@procedure_id is null))
    begin
		/* this block is for the case where there is no pattern
			matching required for the procedure name */
		SELECT
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,c.name),
			COLUMN_TYPE = convert(smallint, 1+c.isoutparam),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(sysname,'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.colid = 1
			AND o.type = 'P'						/* Just Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper		
		ORDER BY 1, 2, 3, 18
	end
	else
    begin
		/* this block is for the case where there IS pattern
			matching done on the procedure name */
		if @procedure_owner is null
			select @procedure_owner = '%'
		SELECT
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,c.name),
			COLUMN_TYPE = convert(smallint,	1+c.isoutparam),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.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.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.xusertype = t.xusertype
			AND o.type = 'P'							/* Just Procedures */
			AND c.name like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ isnull(ltrim(str(c.number,5)),'1')),
			COLUMN_NAME = convert(sysname,'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(sysname,'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.name like @procedure_name
			AND c.id = o.id
			AND user_name(o.uid) like @procedure_owner
			AND c.colid = 1
			AND o.type = 'P'						/* Just Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		ORDER BY 1, 2, 3, 18
	end
go

if (charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_sproc_columns
go

/*	Procedure for 8.0 server */
CREATE PROCEDURE sp_sproc_columns (
				 @procedure_name		nvarchar(390) = '%',
				 @procedure_owner		nvarchar(384) = null,
				 @procedure_qualifier		sysname = null,
				 @column_name			nvarchar(384) = null,
				 @ODBCVer				int = 2)
AS
    DECLARE @group_num_lower smallint
    DECLARE @group_num_upper smallint
    DECLARE @semi_position int
    DECLARE @full_procedure_name nvarchar(774)
    DECLARE @procedure_id int

	if @column_name is null /*	If column name not supplied, match all */
		select @column_name = '%'
	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	/* If qualifier doesn't match current database */
				raiserror (15250, -1,-1)
				return
			end
		end
    end

	if @procedure_name is null
	begin	/*	If procedure name not supplied, match all */
		select @procedure_name = '%'
	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_lower = convert(int,substring(@procedure_name, @semi_position + 1, 2))
		select @group_num_upper = @group_num_lower
		select @procedure_name = substring(@procedure_name, 1, @semi_position -1)
    end
    else
	begin	/* No group separator, so default to all groups */
		select @group_num_lower = 1
		select @group_num_upper = 32767			
    end

	if @procedure_owner is null
	begin	/* If unqualified procedure name */
		SELECT @full_procedure_name = quotename(@procedure_name)
    end
    else
	begin	/* Qualified procedure name */
		if @procedure_owner = ''
		begin	/* If empty owner name */
			SELECT @full_procedure_name = quotename(@procedure_owner)
		end
		else
		begin
			SELECT @full_procedure_name = quotename(@procedure_owner) +
				'.' + quotename(@procedure_name)
		end
    end

	/*	Get Object ID */
	SELECT @procedure_id = object_id(@full_procedure_name)
	if ((isnull(charindex('%', @full_procedure_name),0) = 0) and
		(isnull(charindex('[', @procedure_name),0) = 0) and
		(isnull(charindex('[', @procedure_owner),0) = 0) and
		(isnull(charindex('_', @full_procedure_name),0) = 0) and
		not (@procedure_id is null))
    begin
		/* this block is for the case where there is no pattern
			matching required for the procedure name */
		SELECT
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,c.name),
			COLUMN_TYPE = convert(smallint, 1+c.isoutparam),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
			AND (o.type in ('P', 'TF', 'IF') OR (len(c.name) > 0 and o.type = 'FN'))
			AND ((c.number between @group_num_lower and @group_num_upper)
			     OR (c.number = 0 and o.type = 'FN'))
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(sysname,'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.colid = 1
			AND o.type = 'P'			/* Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		/* UDF return value */
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),	/* SQL_RETURN_VALUE */
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			NULLABLE = convert(smallint, c.isnullable),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.dbo.spt_datatype_info d,
			systypes t
		WHERE
			o.name like @procedure_name
			AND o.id = c.id
			AND c.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.xusertype = t.xusertype
			AND o.type = 'FN'			/* Scalar UDF */
			AND c.name like @column_name
			AND c.colid = 0
			AND c.number = 0
		UNION ALL
		SELECT		/* Table valued functions */
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';1'),
			COLUMN_NAME = convert(sysname,'@TABLE_RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 3),
			DATA_TYPE = convert(smallint, NULL),
			TYPE_NAME = convert(sysname, 'table'),
			"PRECISION" = convert(int,0),
			LENGTH = convert(int,0),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,0),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254), 'Result table returned by table valued function'),
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			SQL_DATA_TYPE = convert(smallint, NULL),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,0)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.id = @procedure_id
			AND c.id = o.id
			AND c.colid = 1
			AND o.type IN ('TF', 'IF')
			AND '@TABLE_RETURN_VALUE' like @column_name
			AND c.number = 0
		ORDER BY 1, 2, 3, 18
	end
	else
    begin
		/* this block is for the case where there IS pattern
			matching done on the procedure name */
		if @procedure_owner is null
			select @procedure_owner = '%'

		SELECT
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,c.name),
			COLUMN_TYPE = convert(smallint,	1+c.isoutparam),
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			d.NULLABLE,
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int, c.colid),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.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.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.xusertype = t.xusertype
			AND c.name like @column_name
			AND (o.type in ('P', 'TF', 'IF') OR (len(c.name) > 0 and o.type = 'FN'))
			AND ((c.number between @group_num_lower and @group_num_upper)
			     OR (c.number = 0 and o.type = 'FN'))
		UNION ALL
		SELECT		   /* return value row*/
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ isnull(ltrim(str(c.number,5)),'1')),
			COLUMN_NAME = convert(sysname,'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),	/* SQL_RETURN_VALUE */
			DATA_TYPE = convert(smallint, 4),
			TYPE_NAME = convert(sysname,'int'),
			"PRECISION" = convert(int,10),
			LENGTH = convert(int,4),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,10),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			SQL_DATA_TYPE = convert(smallint, 4),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,56)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.name like @procedure_name
			AND c.id = o.id
			AND user_name(o.uid) like @procedure_owner
			AND c.colid = 1
			AND o.type = 'P'					/* Procedures */
			AND '@RETURN_VALUE' like @column_name
			AND c.number between @group_num_lower and @group_num_upper
		UNION ALL
		SELECT		/* UDF return value */
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.number,5))),
			COLUMN_NAME = convert(sysname,'@RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 5),	/* SQL_RETURN_VALUE */
			d.DATA_TYPE,
			TYPE_NAME = t.name,
			convert(int,case
				when d.DATA_TYPE in (6,7) then d.data_precision 		/* FLOAT/REAL */
				else OdbcPrec(c.xtype,c.length,c.xprec)
			end) "PRECISION",
			convert(int,case
				when type_name(d.ss_dtype) IN ('numeric','decimal') then	/* decimal/numeric types */
					OdbcPrec(c.xtype,c.length,c.xprec)+2
				else
					isnull(d.length, c.length)
			end) LENGTH,
			SCALE = convert(smallint, OdbcScale(c.xtype,c.xscale)),
			d.RADIX,
			NULLABLE = convert(smallint, c.isnullable),
			REMARKS = convert(varchar(254),null),	/* Remarks are NULL */
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			d.SQL_DATA_TYPE,
			d.SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH = isnull(d.length, c.length)+d.charbin,
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),rtrim(substring('NO YES',d.NULLABLE*3+1,3))),
			SS_DATA_TYPE = c.type
		FROM
			syscolumns c,
			sysobjects o,
			master.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.xtype = d.ss_dtype
			AND c.length = isnull(d.fixlen, c.length)
			AND (d.ODBCVer is null or d.ODBCVer = @ODBCVer)
			AND isnull(d.AUTO_INCREMENT,0) = 0
			AND c.xusertype = t.xusertype
			AND o.type = 'FN'			/* Scalar UDF */
			AND c.name like @column_name
			AND c.colid = 0
			AND c.number = 0
		UNION ALL
		SELECT		/* Table valued functions */
			PROCEDURE_QUALIFIER = convert(sysname,DB_NAME()),
			PROCEDURE_OWNER = convert(sysname,USER_NAME(o.uid)),
			PROCEDURE_NAME = convert(nvarchar(134),o.name +';1'),
			COLUMN_NAME = convert(sysname,'@TABLE_RETURN_VALUE'),
			COLUMN_TYPE = convert(smallint, 3),
			DATA_TYPE = convert(smallint, NULL),
			TYPE_NAME = convert(sysname, 'table'),
			"PRECISION" = convert(int,0),
			LENGTH = convert(int,0),
			SCALE = convert(smallint,0),
			RADIX = convert(smallint,0),
			NULLABLE = convert(smallint,0),
			REMARKS = convert(varchar(254), 'Result table returned by table valued function'),
			COLUMN_DEF = convert(nvarchar(4000),NULL),
			SQL_DATA_TYPE = convert(smallint, NULL),
			SQL_DATETIME_SUB = convert(smallint,null),
			CHAR_OCTET_LENGTH = convert(int,null),
			ORDINAL_POSITION = convert(int,0),
			IS_NULLABLE = convert(varchar(254),'NO'),
			SS_DATA_TYPE = convert(tinyint,0)
		FROM
			syscomments c, sysobjects o
		WHERE
			o.name like @procedure_name
			AND user_name(o.uid) like @procedure_owner
			AND c.id = o.id
			AND c.colid = 1
			AND o.type IN ('TF', 'IF')
			AND '@TABLE_RETURN_VALUE' like @column_name
			AND c.number = 0
		ORDER BY 1, 2, 3, 18
	end
go

grant execute on sp_sproc_columns to public
go

dump tran master with no_log
go

print 'creating sp_statistics'
go

/*	Procedure for pre-7.0 server */
CREATE PROCEDURE sp_statistics (
				 @table_name		varchar(32),
				 @table_owner		varchar(32) = null,
				 @table_qualifier	varchar(32) = null,
				 @index_name		varchar(32) = '%',
				 @is_unique 		char(1) = 'N',
				 @accuracy			char(1) = 'Q')
AS
	set nocount on
	DECLARE @indid				int
	DECLARE @lastindid			int
	DECLARE @table_id			int
	DECLARE @full_table_name	varchar(65) /* 2*32+1 */

	create table #TmpIndex(
		TABLE_QUALIFIER varchar(32) NULL,
		TABLE_OWNER 	varchar(32) NULL,
		TABLE_NAME		varchar(32) NOT NULL,
		INDEX_QUALIFIER varchar(32) null,
		INDEX_NAME		varchar(32) null,
		NON_UNIQUE		smallint null,
		TYPE			smallint NOT NULL,
		SEQ_IN_INDEX	smallint null,
		COLUMN_NAME 	varchar(32) null,
		COLLATION		char(1) null,
		index_id		int null,
		CARDINALITY 	int null,
		PAGES			int null,
		status			smallint NOT NULL)

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 '~~Rush_5~~'
			return
		end
    end

	if @accuracy not in ('Q','E')
		begin
			raiserror 20002 '~~Rush_58~~'
			return
		end

	if (@@trancount <> 0 and
		charindex('6.50', @@version) = 0 and
		charindex('7.00', @@version) = 0 and
		charindex('8.00', @@version) = 0)
	begin	/* If inside a transaction */
		raiserror 20003 '~~Rush_59~~'
		return
    end

	if @table_owner is null
	begin	/* If unqualified table name */
		SELECT @full_table_name = @table_name
    end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = @table_owner
		end
		else
		begin
			SELECT @full_table_name = @table_owner + '.' + @table_name
		end
    end
	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)

	/*	Start at lowest index id */
	SELECT @indid = min(indid)
    FROM sysindexes
	WHERE id = @table_id
		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,indid,colid),/* COLUMN_NAME	   */
				'A',									/* COLLATION	   */
				@indid, 								/* index_id 	   */
				x.rows, 								/* CARDINALITY	   */
				x.dpages,								/* PAGES		   */
				x.status								/* status			*/
			FROM sysindexes x, syscolumns c, sysobjects o
			WHERE
				x.id = @table_id
				AND x.id = o.id
				AND x.id = c.id
				AND c.colid < keycnt+(x.status&16)/16	/* all but Unique Clust indices have an extra key */
				AND x.indid = @indid
		/*
		**	  Now move @indid to the next index.
		*/
		SELECT @lastindid = @indid
		SELECT @indid = NULL

		SELECT @indid = min(indid)
		FROM sysindexes
		WHERE id = @table_id
			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 */

	/* now add row for 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 	   */
			x.rows, 				/* CARDINALITY	   */
			x.dpages,				/* PAGES		   */
			0						/* status		   */
		FROM sysindexes x, sysobjects o
		WHERE o.id = @table_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		*/

	if @is_unique <> 'Y'	/* 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,
			FILTER_CONDITION = convert(varchar(128),null)
		FROM #TmpIndex
		WHERE
			INDEX_NAME like @index_name /* If matching name */
			or INDEX_NAME is null		/* If SQL_TABLE_STAT row */
		ORDER BY 4, 7, 6, 8
	else					/* If 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,
			FILTER_CONDITION = convert(varchar(128),null)
		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 4, 7, 6, 8

    DROP TABLE #TmpIndex
go

if (charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_statistics
go

/*	Procedure for 7.0 server */
CREATE PROCEDURE sp_statistics (
				 @table_name		sysname,
				 @table_owner		sysname = null,
				 @table_qualifier	sysname = null,
				 @index_name		sysname = '%',
				 @is_unique 		char(1) = 'N',
				 @accuracy			char(1) = 'Q')
AS
	set nocount on
	DECLARE @indid				int
	DECLARE @lastindid			int
	DECLARE @table_id			int
	DECLARE @full_table_name	nvarchar(257)

	create table #TmpIndex(
		TABLE_QUALIFIER sysname NULL,
		TABLE_OWNER 	sysname NULL,
		TABLE_NAME		sysname NOT NULL,
		INDEX_QUALIFIER sysname null,
		INDEX_NAME		sysname null,
		NON_UNIQUE		smallint null,
		TYPE			smallint NOT NULL,
		SEQ_IN_INDEX	smallint null,
		COLUMN_NAME 	sysname null,
		COLLATION		char(1) null,
		index_id		int null,
		CARDINALITY 	int null,
		PAGES			int null,
		status			int NOT NULL)

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end

	if @accuracy not in ('Q','E')
		begin
			raiserror (15251,-1,-1,'accuracy','''Q'' or ''E''')
			return
		end

	if @table_owner is null
	begin	/* If unqualified table name */
		SELECT @full_table_name = quotename(@table_name)
    end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
    end
	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)

	/*	Start at lowest index id */
	SELECT @indid = min(indid)
    FROM sysindexes
	WHERE not (@table_id is null)
		AND id = @table_id
		AND indid > 0
		AND indid < 255

	/* Create a temp table to correct the ordinal position of the columns */
	create table #TmpColumns
	(ordinal int identity(1,1),
	 colid   smallint not null)

	/* Load columns into the temp table */
	insert into #TmpColumns (colid)
	select c.colid
	from syscolumns c
	where c.id = @table_id
	order by c.colid
	
	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	   */
				case									/* NON_UNIQUE	   */
					WHEN x.status&2 <> 2 then 1			/* Nonunique index */
					else 0								/* Unique index    */
				end,
				case									/* TYPE 		   */
					when @indid > 1 then 3				/* Non-Clustered   */
					else 1								/* Clustered index */
				end,
				tc.ordinal,									/* SEQ_IN_INDEX    */
				INDEX_COL(@full_table_name, indid, tc.ordinal),/* COLUMN_NAME	   */
				'A',									/* COLLATION	   */
				@indid, 								/* index_id 	   */
				case									/* CARDINALITY	   */
					when @indid > 1 then NULL			/* Non-Clustered   */
					else x.rows 						/* Clustered index */
				end,
				case									/* PAGES		   */
					when @indid > 1 then NULL			/* Non-Clustered   */
					else x.dpages						/* Clustered index */
				end,
				x.status								/* status			*/
			FROM sysindexes x, syscolumns c, sysobjects o, #TmpColumns tc
			WHERE
				not (@table_id is null)
				AND x.id = @table_id
				AND x.id = o.id
				AND x.id = c.id
				AND tc.colid = c.colid
				AND tc.ordinal < keycnt+(x.status&18)/18	/* all but Unique Clust indices have an extra key */
				AND INDEX_COL(@full_table_name, indid, tc.ordinal) IS NOT NULL
				AND indid = @indid
				AND (x.status&2 = 2
					OR @is_unique <> 'Y')
				AND (x.status&32) = 0
		/*
		**	  Now move @indid to the next index.
		*/
		SELECT @lastindid = @indid
		SELECT @indid = NULL

		SELECT @indid = min(indid)
		FROM sysindexes
		WHERE not (@table_id is null)
			AND id = @table_id
			AND indid > @lastindid
			AND indid < 255
    END

	/* now add row for 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 	   */
			x.rows, 				/* CARDINALITY	   */
			x.dpages,				/* PAGES		   */
			0						/* status		   */
		FROM sysindexes x, sysobjects o
		WHERE not (@table_id is null)
			AND o.id = @table_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		*/

	SELECT
		TABLE_QUALIFIER,
		TABLE_OWNER,
		TABLE_NAME,
		NON_UNIQUE,
		INDEX_QUALIFIER,
		INDEX_NAME,
		TYPE,
		SEQ_IN_INDEX,
		COLUMN_NAME,
		COLLATION,
		CARDINALITY,
		PAGES,
		FILTER_CONDITION = convert(varchar(128),null)
	FROM #TmpIndex
	WHERE
		INDEX_NAME like @index_name /* If matching name */
		or INDEX_NAME is null		/* If SQL_TABLE_STAT row */
	ORDER BY 4, 7, 6, 8

    DROP TABLE #TmpIndex, #TmpColumns
go

if (charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_statistics
go

/*	Procedure for 8.0 server */
CREATE PROCEDURE sp_statistics (
				 @table_name		sysname,
				 @table_owner		sysname = null,
				 @table_qualifier	sysname = null,
				 @index_name		sysname = '%',
				 @is_unique 		char(1) = 'N',
				 @accuracy			char(1) = 'Q')
AS
	set nocount on
	DECLARE @indid				int
	DECLARE @lastindid			int
	DECLARE @table_id			int
	DECLARE @full_table_name	nvarchar(257)

	create table #TmpIndex(
		TABLE_QUALIFIER sysname collate database_default NULL,
		TABLE_OWNER 	sysname collate database_default NULL,
		TABLE_NAME		sysname collate database_default NOT NULL,
		INDEX_QUALIFIER sysname collate database_default null,
		INDEX_NAME		sysname collate database_default null,
		NON_UNIQUE		smallint null,
		TYPE			smallint NOT NULL,
		SEQ_IN_INDEX	smallint null,
		COLUMN_NAME 	sysname collate database_default null,
		COLLATION		char(1) collate database_default null,
		index_id		int null,
		CARDINALITY 	int null,
		PAGES			int null,
		status			int NOT NULL)

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end

	if @accuracy not in ('Q','E')
		begin
			raiserror (15251,-1,-1,'accuracy','''Q'' or ''E''')
			return
		end

	if @table_owner is null
	begin	/* If unqualified table name */
		SELECT @full_table_name = quotename(@table_name)
    end
    else
	begin	/* Qualified table name */
		if @table_owner = ''
		begin	/* If empty owner name */
			SELECT @full_table_name = quotename(@table_owner)
		end
		else
		begin
			SELECT @full_table_name = quotename(@table_owner) +
				'.' + quotename(@table_name)
		end
    end
	/*	Get Object ID */
	SELECT @table_id = object_id(@full_table_name)

	/*	Start at lowest index id */
	SELECT @indid = min(indid)
    FROM sysindexes
	WHERE not (@table_id is null)
		AND id = @table_id
		AND indid > 0
		AND indid < 255

	/* Create a temp table to correct the ordinal position of the columns */
	create table #TmpColumns
	(ordinal int identity(1,1),
	 colid   smallint not null)

	/* Load columns into the temp table */
	insert into #TmpColumns (colid)
	select c.colid
	from syscolumns c
	where c.id = @table_id
	order by c.colid
	
	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	   */
				case									/* NON_UNIQUE	   */
					WHEN x.status&2 <> 2 then 1			/* Nonunique index */
					else 0								/* Unique index    */
				end,
				case									/* TYPE 		   */
					when @indid > 1 then 3				/* Non-Clustered   */
					else 1								/* Clustered index */
				end,
				tc.ordinal,									/* SEQ_IN_INDEX    */
				INDEX_COL(@full_table_name, indid, tc.ordinal),/* COLUMN_NAME	   */
				'A',									/* COLLATION	   */
				@indid, 								/* index_id 	   */
				case									/* CARDINALITY	   */
					when @indid > 1 then NULL			/* Non-Clustered   */
					else x.rows 						/* Clustered index */
				end,
				case									/* PAGES		   */
					when @indid > 1 then NULL			/* Non-Clustered   */
					else x.dpages						/* Clustered index */
				end,
				x.status								/* status			*/
			FROM sysindexes x, syscolumns c, sysobjects o, #TmpColumns tc
			WHERE
				not (@table_id is null)
				AND x.id = @table_id
				AND x.id = o.id
				AND x.id = c.id
				AND tc.colid = c.colid
				AND tc.ordinal < keycnt+(x.status&18)/18	/* all but Unique Clust indices have an extra key */
				AND INDEX_COL(@full_table_name, indid, tc.ordinal) IS NOT NULL
				AND indid = @indid
				AND (x.status&2 = 2
					OR @is_unique <> 'Y')
				AND (x.status&32) = 0
		/*
		**	  Now move @indid to the next index.
		*/
		SELECT @lastindid = @indid
		SELECT @indid = NULL

		SELECT @indid = min(indid)
		FROM sysindexes
		WHERE not (@table_id is null)
			AND id = @table_id
			AND indid > @lastindid
			AND indid < 255
    END

	/* now add row for 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 	   */
			x.rows, 				/* CARDINALITY	   */
			x.dpages,				/* PAGES		   */
			0						/* status		   */
		FROM sysindexes x, sysobjects o
		WHERE not (@table_id is null)
			AND o.id = @table_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		*/

	SELECT
		TABLE_QUALIFIER,
		TABLE_OWNER,
		TABLE_NAME,
		NON_UNIQUE,
		INDEX_QUALIFIER,
		INDEX_NAME,
		TYPE,
		SEQ_IN_INDEX,
		COLUMN_NAME,
		COLLATION,
		CARDINALITY,
		PAGES,
		FILTER_CONDITION = convert(varchar(128),null)
	FROM #TmpIndex
	WHERE
		INDEX_NAME like @index_name /* If matching name */
		or INDEX_NAME is null		/* If SQL_TABLE_STAT row */
	ORDER BY 4, 7, 6, 8

    DROP TABLE #TmpIndex, #TmpColumns
go

grant execute on sp_statistics to public
go

dump tran master with no_log
go

print 'creating sp_stored_procedures'
go


/* pre 8.0 version */
create procedure sp_stored_procedures(
						@sp_name		varchar(102) = null,
						@sp_owner		varchar(96) = null,
						@sp_qualifier	varchar(32) = null)
as
	declare @proc_type smallint

    if @sp_qualifier is not null
    begin
		if db_name() <> @sp_qualifier
		begin
			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 else
			begin	/* If qualifier doesn't match current database */
				raiserror 20001 '~~Rush_51~~'
				return
			end
		end
    end

    if @sp_name is null
	begin  /*  If procedure name not supplied, match all */
		select @sp_name = '%'
    end
	else begin
		if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
		begin
			if exists (select * from sysobjects
				where uid = user_id()
					and name = @sp_name
					and type = 'P') /* Object type of Procedure */
			begin
				select @sp_owner = user_name()
			end
		end
    end
	if @sp_owner is null	/*	If procedure owner not supplied, match all */
		select @sp_owner = '%'

	select @proc_type=2		/* Return 2 for 4.2 and later servers. */

    select
		PROCEDURE_QUALIFIER = convert(varchar(32),db_name()),
		PROCEDURE_OWNER = convert(varchar(32),user_name(o.uid)),
		PROCEDURE_NAME = convert(varchar(36),o.name +';'+ ltrim(str(c.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 = @proc_type
	from
		sysobjects o,syscomments c,sysusers u
	where
	    o.name like @sp_name
		and c.colid = 1
	    and user_name(o.uid) like @sp_owner
		and o.type = 'P'		/* Object type of Procedure */
		and c.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)  */
		    or ((select max(((sign(uid)*abs(uid-16383))*2)+(protecttype&1))
			 from sysprotects p
			 /* outer join to correlate with all rows in sysobjects */
			 where p.id =* o.id
			     /*  get rows for public,current user,user's group */
				 and (p.uid = 0 or p.uid = user_id() or p.uid =* u.gid)
			     /* check for SELECT,EXECUTE privilege */
			     and (action in (193,224)))&1    /* more magic...normalize GRANT */
			) = 1	 /* final magic...compare Grants	*/
		)
	order by 1, 2, 3
go

grant execute on sp_stored_procedures to public
go


if (charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
	drop procedure sp_stored_procedures
else
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
go


/* 7.0 version */
create procedure sp_stored_procedures(
						@sp_name		nvarchar(390) = null,
						@sp_owner		nvarchar(384) = null,
						@sp_qualifier	sysname = null)
as
	declare @proc_type smallint

    if @sp_qualifier is not null
    begin
		if db_name() <> @sp_qualifier
		begin
			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 else
			begin	/* If qualifier doesn't match current database */
				raiserror (15250, -1,-1)
				return
			end
		end
    end

    if @sp_name is null
	begin  /*  If procedure name not supplied, match all */
		select @sp_name = '%'
    end
	else begin
		if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
		begin
			if exists (select * from sysobjects
				where uid = user_id()
					and name = @sp_name
					and type = 'P') /* Object type of Procedure */
			begin
				select @sp_owner = user_name()
			end
		end
    end
	if @sp_owner is null	/*	If procedure owner not supplied, match all */
		select @sp_owner = '%'

	select @proc_type=2		/* Return 2 for 4.2 and later servers. */

    select
		PROCEDURE_QUALIFIER = convert(sysname,db_name()),
		PROCEDURE_OWNER = convert(sysname,user_name(o.uid)),
		PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.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 = @proc_type
	from
		sysobjects o,syscomments c
	where
	    o.name like @sp_name
		and c.colid = 1
	    and user_name(o.uid) like @sp_owner
		and o.type = 'P'		/* Object type of Procedure */
		and c.id = o.id
		and permissions (o.id)&32 <> 0
	order by 1, 2, 3
go

grant execute on sp_stored_procedures to public
go

if (charindex('8.00', @@version) > 0)
	drop procedure sp_stored_procedures
else
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
go


/* 8.0 version */
create procedure sp_stored_procedures(
						@sp_name	nvarchar(390) = null,
						@sp_owner	nvarchar(384) = null,
						@sp_qualifier	sysname = null)
as
    declare @proc_type smallint

    if @sp_qualifier is not null
    begin
		if db_name() <> @sp_qualifier
		begin
			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 else
			begin	/* If qualifier doesn't match current database */
				raiserror (15250, -1,-1)
				return
			end
		end
    end

    if @sp_name is null
	begin  /*  If procedure name not supplied, match all */
		select @sp_name = '%'
	end
    else
    begin
	if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
	begin
		if exists (select * from sysobjects
			where uid = user_id()
				and name = @sp_name
				and type in ('P', 'FN', 'TF', 'IF'))		/* Procedures, scalar UDF, table UDF */
		begin
			select @sp_owner = user_name()
		end
	end
    end
	
    if @sp_owner is null		/* If procedure owner not supplied, match all */
	select @sp_owner = '%'

    select @proc_type=2			/* Return 2 for 4.2 and later servers. */

    select
		PROCEDURE_QUALIFIER = convert(sysname,db_name()),
		PROCEDURE_OWNER = convert(sysname,user_name(o.uid)),
		PROCEDURE_NAME = convert(nvarchar(134),o.name +';'+ ltrim(str(c.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 = @proc_type
	from
		sysobjects o,syscomments c
	where
	    o.name like @sp_name
		and c.colid = 1
	    and user_name(o.uid) like @sp_owner
		and o.type in ('P', 'FN', 'TF', 'IF')		/* Object type of Procedure, scalar UDF, table UDF */
		and c.id = o.id
		and permissions (o.id)&32 <> 0
	order by 1, 2, 3
go

grant execute on sp_stored_procedures to public
go

dump tran master with no_log
go


print 'creating sp_table_privileges'
go

/*	Procedure for pre 6.50 server */
CREATE PROCEDURE sp_table_privileges (
			@table_name 		varchar(90),
			@table_owner		varchar(90) = null,
			@table_qualifier	varchar(32) = null)
as
	set nocount on

    declare @table_id    int,
			@owner_id	 int,
			@full_table_name char(181)
	declare @refconst int

	select @refconst = 1
	if	(charindex('6.00', @@version) = 0)
		select @refconst = NULL

    if @table_qualifier is not null
    begin
		if db_name() != @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror 20001 'Table qualifier must be name of current database'
			return
		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 @@trancount != 0
	begin	/* If inside a transaction */
		raiserror 20003 'The procedure ''sp_table_privileges'' cannot be executed from within a transaction.'
		return
    end
	create table #table_priv1(
		table_qualifier			varchar(32) NOT NULL,
		table_owner 			varchar(32) NOT NULL,
		table_name				varchar(32) NOT NULL,
		grantor 				varchar(32) NOT NULL,
		grantee 				varchar(32) NOT NULL,
		select_privilege		int NOT NULL,
		insert_privilege		int NOT NULL,
		update_privilege		int NOT NULL,
		delete_privilege		int NOT NULL,
		references_privilege	int NULL,
		is_grantable			varchar(3) NOT NULL,
		uid 					int NOT NULL,
		gid 					int NOT NULL)

    insert into #table_priv1
		select distinct
			db_name(),
			user_name(o.uid),
			o.name,
			user_name(o.uid),
			u.name,
			0,
			0,
			0,
			0,
			@refconst,
			'no',
			u.uid,
			u.gid
		from sysusers u, sysobjects o
		where o.id = @table_id and u.uid != u.gid
		   and sysstat & 0xf in (1,2,3)	/* only valid for system tables,
		   								** user tables, and views. */

    /*
    ** now add row for table owner
    */
    if exists (
		select *
			from #table_priv1
			where grantor = grantee)
    begin
		update #table_priv1
		set
			select_privilege = 1,
			update_privilege = 1,
			insert_privilege = 1,
			delete_privilege = 1,
			references_privilege = 1,
			is_grantable = 'yes'
		where grantor = grantee
    end
    else
    begin
		insert into #table_priv1
			select	db_name(),
				user_name(o.uid),
				o.name,
				user_name(o.uid),
				user_name(o.uid),
				1,
				1,
				1,
				1,
				@refconst,
				'yes',
				o.uid,
				u.gid
			from sysobjects o, sysusers u
			where o.id = @table_id and u.uid = o.uid
			and sysstat & 0xf in (1,2,3)	/* only valid for system tables,
		   								** user tables, and views. */

    end

    update #table_priv1
	set select_privilege = 1
	where
		exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 205
				and action = 193)
		and not exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 206
				and action = 193)

    update #table_priv1
	set insert_privilege = 1
	where
		exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 205
				and action = 195)
		and not exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 206
				and action = 195)

    update #table_priv1
	set delete_privilege = 1
	where
		exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 205
				and action = 196)
		and not exists (select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 206
				and action = 196)

    update #table_priv1
	set update_privilege = 1
	where
		exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 205
				and action = 197)
		and not exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 206
				and action = 197)

    update #table_priv1
	set references_privilege = 1
	where
		exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 205
				and action = 26)
		and not exists (
			select * from sysprotects
			where
				id = @table_id
				and (#table_priv1.uid = uid
					or #table_priv1.gid = uid
					or uid = 0)
				and protecttype = 206
				and action = 26)

	create table #table_priv2(
		table_qualifier varchar(32) NULL,
		table_owner 	varchar(32) NULL,
		table_name		varchar(32) NOT NULL,
		grantor 		varchar(32) NULL,
		grantee 		varchar(32) NOT NULL,
		privilege		varchar(32) NOT NULL,
		is_grantable	varchar(3) NULL)

	insert into #table_priv2
		select
			table_qualifier,
			table_owner,
			table_name,
			grantor,
			grantee,
			'SELECT',
			is_grantable
		from #table_priv1
		where select_privilege = 1


	insert into #table_priv2
		select
			table_qualifier,
			table_owner,
			table_name,
			grantor,
			grantee,
			'INSERT',
			is_grantable
		from #table_priv1
		where insert_privilege = 1


	insert into #table_priv2
		select
			table_qualifier,
			table_owner,
			table_name,
			grantor,
			grantee,
			'DELETE',
			is_grantable
		from #table_priv1
		where delete_privilege = 1


	insert into #table_priv2
		select
			table_qualifier,
			table_owner,
			table_name,
			grantor,
			grantee,
			'UPDATE',
			is_grantable
		from #table_priv1
		where update_privilege = 1

	insert into #table_priv2
		select
			table_qualifier,
			table_owner,
			table_name,
			grantor,
			grantee,
			'REFERENCES',
			is_grantable
		from #table_priv1
		where references_privilege = 1


    select * from #table_priv2
	order by table_owner,table_name,privilege,grantee
/*	order by 2,3,6,5 Can't use since fails on 4.21a server */
go

if (charindex('6.50', @@version) = 0 and
	charindex('7.00', @@version) = 0 and
	charindex('8.00', @@version) = 0)
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 6.50 SQL Server.'
	print 'Ignore the following errors.'
end
else
	drop proc sp_table_privileges
go


/*	Procedure for 6.50 server */
CREATE PROCEDURE sp_table_privileges (
			@table_name 		varchar(96),
			@table_owner		varchar(96) = null,
			@table_qualifier	varchar(32) = null)
as

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @table_name is null
		select @table_name = '%'
	if @table_owner is null /* If no owner supplied, force wildcard */
		select @table_owner = '%'

	select
		convert(varchar(32),db_name()) TABLE_QUALIFIER,
		convert(varchar(32),user_name(o.uid)) TABLE_OWNER,
		convert(varchar(32),object_name(o.id)) TABLE_NAME,
		convert(varchar(32),user_name(p.grantor)) GRANTOR,
		convert(varchar(32),user_name(u.uid)) GRANTEE,
		convert(varchar(32),case p.action
			 when 193 then 'SELECT'
			 when 195 then 'INSERT'
			 when 196 then 'DELETE'
			 when 197 then 'UPDATE'
			 else 'REFERENCES'
		end) PRIVILEGE,
		convert(varchar(3),case when p.protecttype = 205 then 'NO'
			else 'YES'
		end) IS_GRANTABLE
	from sysprotects p, sysobjects o, sysusers u
	where
		p.id = o.id
		and o.type in ('U','V','S')
		and object_name(o.id) like @table_name
		and user_name(o.uid) like @table_owner
			/* expand groups */
		and ((p.uid = u.uid and u.uid <> u.gid) or
			 (p.uid = u.gid and u.uid <> u.gid))
		and p.protecttype <> 206	/* only grant rows */
		and p.action in (26,193,195,196,197)
		and o.uid <> u.uid			/* no rows for owner */
		and not exists (			/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = p.action
				and p1.id = p.id
				and p1.uid = u.uid)
	union
	select	/*	Add rows for table owner */
		convert(varchar(32),db_name()) TABLE_QUALIFIER,
		convert(varchar(32),user_name(o.uid)) TABLE_OWNER,
		convert(varchar(32),object_name(o.id)) TABLE_NAME,
		convert(varchar(32),user_name(u.uid)) GRANTOR,
		convert(varchar(32),user_name(o.uid)) GRANTEE,
		convert(varchar(32),case v.number
			when 193 then 'SELECT'
			when 195 then 'INSERT'
			when 196 then 'DELETE'
			when 197 then 'UPDATE'
			else 'REFERENCES'
		end) PRIVILEGE,
		convert(varchar(3),'YES') IS_GRANTABLE
	from sysobjects o, master.dbo.spt_values v, sysusers u
	where
		object_name(o.id) like @table_name
		and o.type in ('U','V','S')
		and user_name(o.uid) like @table_owner
		and u.uid = 1		/* grantor is dbo of database */
		and v.type = 'P'	/* cross product to get all exposed privileges */
		and v.number in (26,193,195,196,197)
		and not exists (	/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = v.number
				and p1.id = o.id
				and p1.uid = o.uid)
	order by 2,3,6,5
go


if (charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
	drop proc sp_table_privileges
else
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 7.0 SQL Server.'
	print 'Ignore the following errors.'
end
go

/*	Procedure for 7.0 and later servers */
CREATE PROCEDURE sp_table_privileges (
			@table_name 		nvarchar(384),
			@table_owner		nvarchar(384) = null,
			@table_qualifier	sysname = null)
as

	if @table_qualifier is not null
    begin
		if db_name() <> @table_qualifier
		begin	/* If qualifier doesn't match current database */
			raiserror (15250, -1,-1)
			return
		end
    end
	if @table_name is null
		select @table_name = '%'
	if @table_owner is null /* If no owner supplied, force wildcard */
		select @table_owner = '%'

	select
		convert(sysname,db_name()) TABLE_QUALIFIER,
		convert(sysname,user_name(o.uid)) TABLE_OWNER,
		convert(sysname,object_name(o.id)) TABLE_NAME,
		convert(sysname,user_name(p.grantor)) GRANTOR,
		convert(sysname,user_name(u.uid)) GRANTEE,
		convert(varchar(32),case p.action
			 when 193 then 'SELECT'
			 when 195 then 'INSERT'
			 when 196 then 'DELETE'
			 when 197 then 'UPDATE'
			 else 'REFERENCES'
		end) PRIVILEGE,
		convert(varchar(3),case when p.protecttype = 205 then 'NO'
			else 'YES'
		end) IS_GRANTABLE
	from sysprotects p, sysobjects o, sysusers u, sysmembers m
	where
		p.id = o.id
		and o.type in ('U','V','S')
		and object_name(o.id) like @table_name
		and user_name(o.uid) like @table_owner
			/* expand groups - AKUNDONE: only 1 level of grp unrolling. */
		and (u.uid > 0 and u.uid < 16384)
		and ((p.uid = u.uid) or
			 (p.uid = m.groupuid and u.uid = m.memberuid))
		and p.protecttype <> 206	/* only grant rows */
		and p.action in (26,193,195,196,197)
		and o.uid <> u.uid			/* no rows for owner */
		and not exists (			/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = p.action
				and p1.id = p.id
				and p1.uid = u.uid)
	union
	select	/*	Add rows for table owner */
		convert(sysname,db_name()) TABLE_QUALIFIER,
		convert(sysname,user_name(o.uid)) TABLE_OWNER,
		convert(sysname,object_name(o.id)) TABLE_NAME,
		convert(sysname,user_name(u.uid)) GRANTOR,
		convert(sysname,user_name(o.uid)) GRANTEE,
		convert(varchar(32),case v.number
			when 193 then 'SELECT'
			when 195 then 'INSERT'
			when 196 then 'DELETE'
			when 197 then 'UPDATE'
			else 'REFERENCES'
		end) PRIVILEGE,
		convert(varchar(3),'YES') IS_GRANTABLE
	from sysobjects o, master.dbo.spt_values v, sysusers u
	where
		object_name(o.id) like @table_name
		and o.type in ('U','V','S')
		and user_name(o.uid) like @table_owner
		and u.uid = 1		/* grantor is 'dbo' of database */
		and v.type = N'P'	/* cross product to get all exposed privileges */
		and v.number in (26,193,195,196,197)
		and not exists (	/* exclude revoke'd privileges */
			select *
			from sysprotects p1
			where
				p1.protecttype = 206
				and p1.action = v.number
				and p1.id = o.id
				and p1.uid = o.uid)
	order by 2,3,6,5
go

grant execute on sp_table_privileges to public
go

dump tran master with no_log
go

print 'creating sp_tables'
go

/*	Procedure for 6.50 and earlier servers */
create procedure sp_tables(
			   @table_name		varchar(96)	= null,
			   @table_owner 	varchar(96)	= null,
			   @table_qualifier varchar(32)	= null,
			   @table_type		varchar(100) = null)
as
	declare @type1 varchar(3)
	declare @tableindex int


	/* 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 = convert(varchar(32),d.name),
			TABLE_OWNER = convert(varchar(32),null),
			TABLE_NAME = convert(varchar(32),null),
			TABLE_TYPE = convert(varchar(32),null),
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from master.dbo.sysdatabases d
		where d.name <> 'model'	/* eliminate MODEL database */
		order by 1
	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 = convert(varchar(32),null),
			TABLE_OWNER = convert(varchar(32),user_name(uid)),
			TABLE_NAME = convert(varchar(32),null),
			TABLE_TYPE = convert(varchar(32),null),
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from sysobjects
		order by 2
	end

	/* Special feature #3:	enumerate table types when qualifier, owner and
		 name are blank but table type is explicitly '%'.	*/
	else if @table_qualifier = '' and
		@table_owner = '' and
		@table_name = '' and
		@table_type = '%'
	begin	/* If enumerating table types */
		select
			TABLE_QUALIFIER = convert(varchar(32),null),
			TABLE_OWNER = convert(varchar(32),null),
			TABLE_NAME = convert(varchar(32),null),
			TABLE_TYPE = convert(varchar(32),rtrim(substring('SYSTEM TABLETABLE       VIEW',(colid-1)*12+1,12))),
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from sysobjects o, syscolumns c
		where o.id=c.id and o.name='sysusers' and colid<=3
	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 20001 '~~Rush_5~~'
					return
				end
			end
		end
		if @table_type is null
		begin	/* Select all ODBC supported table types */
			select @type1 = 'SUV'
		end
		else
		begin
			/*	TableType is case sensitive if CS server */
			select @type1 = null
			if (charindex('''SYSTEM TABLE''',@table_type) <> 0)
				select @type1 = @type1 + 'S'	/* Add System Tables */
			if (charindex('''TABLE''',@table_type) <> 0)
				select @type1 = @type1 + 'U'	/* Add User Tables */
			if (charindex('''VIEW''',@table_type) <> 0)
				select @type1 = @type1 + 'V'	/* Add Views */
		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 name = @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 @table_owner is null /* If no owner supplied, force wildcard */
			select @table_owner = '%'
		select
			TABLE_QUALIFIER = convert(varchar(32),db_name()),
			TABLE_OWNER = convert(varchar(32),user_name(o.uid)),
			TABLE_NAME = convert(varchar(32),o.name),	/* make nullable */
			TABLE_TYPE = convert(varchar(32),rtrim(
				substring('SYSTEM TABLE            TABLE       VIEW       ',
					(ascii(o.type)-83)*12+1,12))),	/* 'S'=0,'U'=2,'V'=3 */
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from sysusers u, sysobjects o
		where
			o.name like @table_name
			and user_name(o.uid) like @table_owner
			and charindex(substring(o.type,1,1),@type1) <> 0 /* Only desired types */
			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)  */
				or ((select max(((sign(uid)*abs(uid-16383))*2)+(protecttype&1))
					from sysprotects p
					/* outer join to correlate with all rows in sysobjects */
					where p.id =* o.id
						/* get rows for public,current user,user's group */
						and (p.uid = 0 or p.uid = user_id() or p.uid =* u.gid)
						/* check for SELECT,EXECUTE privilege */
						and (action in (193,224)))&1	 /* more magic...normalize GRANT */
					) = 1	/* final magic...compare Grants	  */
			)
		order by 4, 1, 2, 3
	end
go

if (charindex('7.00', @@version) > 0 or
	charindex('8.00', @@version) > 0)
	drop procedure sp_tables
else
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
go

/*	Procedure for 8.0 server */
create procedure sp_tables(
			   @table_name		nvarchar(384)	= null,
			   @table_owner 	nvarchar(384)	= null,
			   @table_qualifier sysname	= null,
			   @table_type		varchar(100) = null)
as
	declare @type1 varchar(3)
	declare @tableindex int


	/* 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 = convert(sysname,d.name),
			TABLE_OWNER = convert(sysname,null),
			TABLE_NAME = convert(sysname,null),
			TABLE_TYPE = convert(varchar(32),null),
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from master.dbo.sysdatabases d
		where d.name <> 'model'	/* eliminate MODEL database */
		order by 1
	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 = convert(sysname,null),
			TABLE_OWNER = convert(sysname,user_name(uid)),
			TABLE_NAME = convert(sysname,null),
			TABLE_TYPE = convert(varchar(32),null),
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from sysobjects
		order by 2
	end

	/* Special feature #3:	enumerate table types when qualifier, owner and
		 name are blank but table type is explicitly '%'.	*/
	else if @table_qualifier = '' and
		@table_owner = '' and
		@table_name = '' and
		@table_type = '%'
	begin	/* If enumerating table types */
		select
			TABLE_QUALIFIER = convert(sysname,null),
			TABLE_OWNER = convert(sysname,null),
			TABLE_NAME = convert(sysname,null),
			TABLE_TYPE = convert(varchar(32),rtrim(substring('SYSTEM TABLETABLE       VIEW',(colid-1)*12+1,12))),
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from sysobjects o, syscolumns c
		where o.id=c.id and o.name='sysusers' and colid<=3
	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 (15250, -1,-1)
					return
				end
			end
		end
		if @table_type is null
		begin	/* Select all ODBC supported table types */
			select @type1 = 'SUV'
		end
		else
		begin
			/*	TableType is case sensitive if CS server */
			select @type1 = ''
			if (charindex('''SYSTEM TABLE''',@table_type) <> 0)
				select @type1 = @type1 + 'S'	/* Add System Tables */
			if (charindex('''TABLE''',@table_type) <> 0)
				select @type1 = @type1 + 'U'	/* Add User Tables */
			if (charindex('''VIEW''',@table_type) <> 0)
				select @type1 = @type1 + 'V'	/* Add Views */
		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 name = @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 @table_owner is null /* If no owner supplied, force wildcard */
			select @table_owner = '%'
		select
			TABLE_QUALIFIER = convert(sysname,db_name()),
			TABLE_OWNER = convert(sysname,user_name(o.uid)),
			TABLE_NAME = convert(sysname,o.name),	/* make nullable */
			TABLE_TYPE = convert(varchar(32),rtrim(
				substring('SYSTEM TABLE            TABLE       VIEW       ',
					(ascii(o.type)-83)*12+1,12))),	/* 'S'=0,'U'=2,'V'=3 */
			REMARKS = convert(varchar(254),null)	/* Remarks are NULL */
		from sysobjects o
		where
			o.name like @table_name
			and user_name(o.uid) like @table_owner
			and o.type in ('U','V','S')
			and charindex(substring(o.type,1,1),@type1) <> 0 /* Only desired types */
			and permissions (o.id)&4096 <> 0
		order by 4, 1, 2, 3
	end
go


grant execute on sp_tables to public
go

dump tran master with no_log
go

/*-----------------------------------------------------------------------------*/
/*-------------- CATALOG STORED PROCEDURES FOR OLEDB SOURCES ------------------*/
/*-----------------------------------------------------------------------------*/

if object_id('sp_linkedservers', 'P') is not null
	drop proc sp_linkedservers
go
raiserror(15339,-1,-1,'sp_linkedservers')
go
create proc sp_linkedservers as
	IF is_srvrolemember('sysadmin') = 1
	begin
		select
			SRV_NAME = srvname,
			SRV_PROVIDERNAME = providername,
			SRV_PRODUCT = srvproduct,
			SRV_DATASOURCE = datasource,
			SRV_PROVIDERSTRING = providerstring,
			SRV_LOCATION = location,
			SRV_CAT = catalog
		from master.dbo.sysservers
		order by 1
	end
	ELSE
	begin
		select
			SRV_NAME = srvname,
			SRV_PROVIDERNAME = providername,
			SRV_PRODUCT = srvproduct,
			SRV_DATASOURCE = datasource,
			SRV_PROVIDERSTRING = NULL,
			SRV_LOCATION = location,
			SRV_CAT = catalog
		from master.dbo.sysservers
		order by 1
	end

go
grant execute on sp_linkedservers to public
go


if object_id('sp_catalogs', 'P') is not null
	drop proc sp_catalogs
go
raiserror(15339,-1,-1,'sp_catalogs')
go
create procedure sp_catalogs(
	@server_name		sysname)
as
	select
        CATALOG_NAME,
		convert (nvarchar(255),DESCRIPTION)
	from master.dbo.SYSREMOTE_CATALOGS < @server_name >
	order by CATALOG_NAME
go
grant execute on sp_catalogs to public
go


if object_id('sp_tables_ex', 'P') is not null
	drop proc sp_tables_ex
go
raiserror(15339,-1,-1,'sp_tables_ex')
go
create procedure sp_tables_ex(
	@table_server		sysname,
	@table_name			sysname = null,
	@table_schema		sysname = null,
	@table_catalog		sysname = null,
	@table_type			sysname = null)
as
	declare @table_catalog_param		sysname
	if ((isnull(charindex('%', @table_catalog),0) = 0) and
		(isnull(charindex('[', @table_catalog),0) = 0) and
		(isnull(charindex('_', @table_catalog),0) = 0))
		select @table_catalog_param = @table_catalog
	else
		select @table_catalog_param = null

	if ((isnull(charindex('%', @table_name),0) = 0) and
		(isnull(charindex('[', @table_name),0) = 0) and
		(isnull(charindex('_', @table_name),0) = 0))
	begin	/*	If no wild carding */
		select
			TABLE_CAT = TABLE_CATALOG,
			TABLE_SCHEM = TABLE_SCHEMA,
			TABLE_NAME = TABLE_NAME,
			TABLE_TYPE = TABLE_TYPE,
			REMARKS = convert(nvarchar(255),DESCRIPTION)
		from master.dbo.SYSREMOTE_TABLES <
					@table_server,
					@table_catalog_param,
					NULL,
					@table_name,
					NULL >
		where (TABLE_SCHEMA like @table_schema
			or @table_schema is NULL or (TABLE_SCHEMA is NULL and @table_schema = N'%'))
			and (TABLE_CATALOG like @table_catalog
			or	 @table_catalog is NULL or (TABLE_CATALOG is NULL and @table_catalog = N'%'))
			and (charindex ('''' + TABLE_TYPE + '''', @table_type) <> 0
			or	 @table_type is NULL)
		order by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
	end
	else
	begin	/*	If wild carding */
		select
			TABLE_CAT = TABLE_CATALOG,
			TABLE_SCHEM = TABLE_SCHEMA,
			TABLE_NAME = TABLE_NAME,
			TABLE_TYPE = TABLE_TYPE,
			REMARKS = convert(nvarchar(255),DESCRIPTION)
		from master.dbo.SYSREMOTE_TABLES <
					@table_server,
					@table_catalog_param,
					NULL,
					NULL,
					NULL >
		where (TABLE_SCHEMA like @table_schema
			or @table_schema is NULL or (TABLE_SCHEMA is NULL and @table_schema = N'%'))
			and (TABLE_CATALOG like @table_catalog
			or	 @table_catalog is NULL or (TABLE_CATALOG is NULL and @table_catalog = N'%'))
			and (charindex ('''' + TABLE_TYPE + '''', @table_type) <> 0
			or	 @table_type is NULL)
			and TABLE_NAME like @table_name
		order by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
	end
go
grant execute on sp_tables_ex to public
go


if object_id('sp_columns_ex', 'P') is not null
	drop proc sp_columns_ex
go

/* 7.0 version */
raiserror(15339,-1,-1,'sp_columns_ex')
go

create procedure sp_columns_ex(
	@table_server		sysname,
	@table_name			sysname = null,
	@table_schema		sysname = null,
	@table_catalog		sysname = null,
	@column_name		sysname = null,
	@ODBCVer			int = 2)
as

	set nocount on
	declare
	@DBCOLUMNFLAGS_ISFIXEDLENGTH binary(1),	@DBCOLUMNFLAGS_ISLONG	binary(1),
	@DBCOLUMNFLAGS_ISROWVER	binary(2)

	select
	@DBCOLUMNFLAGS_ISFIXEDLENGTH	= 0x10,	@DBCOLUMNFLAGS_ISLONG	= 0x80,
	@DBCOLUMNFLAGS_ISROWVER	= 0x0200

	declare	
	@DBTYPE_I2 smallint,			@DBTYPE_I4 smallint,
	@DBTYPE_R4 smallint,			@DBTYPE_R8 smallint,
	@DBTYPE_CY smallint,			@DBTYPE_DATE smallint,
	@DBTYPE_BSTR smallint,			@DBTYPE_BOOL smallint,
	@DBTYPE_VARNUMERIC smallint,	@DBTYPE_DECIMAL smallint,
	@DBTYPE_UI1 smallint,			@DBTYPE_BYREF smallint,
	@DBTYPE_I1 smallint,			@DBTYPE_UI2 smallint,
	@DBTYPE_UI4 smallint,			@DBTYPE_I8 smallint,
	@DBTYPE_UI8 smallint,			@DBTYPE_GUID smallint,
	@DBTYPE_BYTES smallint,			@DBTYPE_STR smallint,
	@DBTYPE_WSTR smallint,			@DBTYPE_NUMERIC smallint,
	@DBTYPE_DBDATE smallint,		@DBTYPE_DBTIME smallint,
	@DBTYPE_DBTIMESTAMP smallint

	select
	@DBTYPE_I2			= 2,	@DBTYPE_I4			= 3,
	@DBTYPE_R4			= 4,	@DBTYPE_R8			= 5,
	@DBTYPE_CY			= 6,	@DBTYPE_DATE		= 7,
	@DBTYPE_BSTR		= 8,	@DBTYPE_BOOL		= 11,
	@DBTYPE_VARNUMERIC	= 139,	@DBTYPE_DECIMAL		= 14,
	@DBTYPE_UI1			= 17,	@DBTYPE_BYREF		= 16384,
	@DBTYPE_I1			= 16,	@DBTYPE_UI2			= 18,
	@DBTYPE_UI4			= 19,	@DBTYPE_I8			= 20,
	@DBTYPE_UI8			= 21,	@DBTYPE_GUID		= 72,
	@DBTYPE_BYTES		= 128,	@DBTYPE_STR			= 129,
	@DBTYPE_WSTR		= 130,	@DBTYPE_NUMERIC		= 131,
	@DBTYPE_DBDATE		= 133,	@DBTYPE_DBTIME		= 134,	
	@DBTYPE_DBTIMESTAMP	= 135

	declare	
	@ODS_SMALLINT_NOT_NULL tinyint,	@ODS_INT_NULL tinyint,
	@ODS_INT_NOT_NULL tinyint,		@ODS_TINYINT_NOT_NULL tinyint,
	@ODS_REAL_NOT_NULL tinyint,		@ODS_FLOAT_NULL tinyint,
	@ODS_FLOAT_NOT_NULL tinyint,	@ODS_MONEY_NULL tinyint,
	@ODS_MONEY_NOT_NULL tinyint,	@ODS_DATETIME_NULL tinyint,
	@ODS_DATETIME_NOT_NULL tinyint,	@ODS_TEXT tinyint,
	@ODS_BIT tinyint,				@ODS_DECIMAL tinyint,
	@ODS_NUMERIC tinyint,			@ODS_GUID tinyint,
	@ODS_IMAGE tinyint,				@ODS_TIMESTAMP tinyint,
	@ODS_BINARY_NULL tinyint,		@ODS_BINARY_NOT_NULL tinyint,
	@ODS_VARBINARY tinyint,			@ODS_CHAR_NULL tinyint,
	@ODS_CHAR_NOT_NULL tinyint,		@ODS_VARCHAR tinyint

	select 	
	@ODS_IMAGE = 34,			@ODS_TEXT = 35,
	@ODS_GUID = 36,				@ODS_BINARY_NULL = 37,			
	@ODS_VARBINARY = 37,		@ODS_INT_NULL = 38,
	@ODS_CHAR_NULL = 39,		@ODS_VARCHAR = 39,
	@ODS_TIMESTAMP = 45,		@ODS_BINARY_NOT_NULL = 45,
	@ODS_CHAR_NOT_NULL = 47,	@ODS_TINYINT_NOT_NULL = 48,
	@ODS_BIT = 50,				@ODS_SMALLINT_NOT_NULL = 52,	
	@ODS_INT_NOT_NULL = 56,		@ODS_REAL_NOT_NULL = 59,		
	@ODS_MONEY_NOT_NULL = 60,	@ODS_DATETIME_NOT_NULL = 61,	
	@ODS_FLOAT_NOT_NULL = 62,	@ODS_DECIMAL = 106,
	@ODS_NUMERIC = 108,			@ODS_FLOAT_NULL = 109,
	@ODS_MONEY_NULL = 110,		@ODS_DATETIME_NULL = 111

	declare 
	@ODBC_GUID smallint,		@ODBC_NTEXT smallint,
	@ODBC_NVARCHAR smallint,	@ODBC_NCHAR smallint,
	@ODBC_BIT smallint,			@ODBC_TINYINT smallint,
	@ODBC_IMAGE smallint,		@ODBC_VARBINARY smallint,
	@ODBC_TIMESTAMP smallint,	@ODBC_BINARY smallint,
	@ODBC_TEXT smallint,		@ODBC_CHAR smallint,
	@ODBC_NUMERIC smallint,		@ODBC_DECIMAL smallint,
	@ODBC_MONEY smallint,		@ODBC_INT smallint,		
	@ODBC_SMALLINT smallint,	@ODBC_FLOAT smallint,	
	@ODBC_REAL smallint,		@ODBC_VARCHAR smallint,
	@ODBC_DATETIME smallint

	select
	@ODBC_GUID		= -11,	@ODBC_NTEXT		= -10,
	@ODBC_NVARCHAR	= -9,	@ODBC_NCHAR		= -8,
	@ODBC_BIT		= -7,	@ODBC_TINYINT	= -6,
	@ODBC_IMAGE		= -4,	@ODBC_VARBINARY	= -3,
	@ODBC_TIMESTAMP	= -2,	@ODBC_BINARY	= -2,
	@ODBC_TEXT		= -1,	@ODBC_CHAR		= 1,
	@ODBC_NUMERIC	= 2,	@ODBC_DECIMAL	= 3,
	@ODBC_MONEY		= 3,	@ODBC_INT		= 4,		
	@ODBC_SMALLINT	= 5,	@ODBC_FLOAT		= 6,	
	@ODBC_REAL		= 7,	@ODBC_VARCHAR	= 12,
	@ODBC_DATETIME	=	
	case @ODBCVer
		when 2 then 11
		else 93
	end

	create table #tmp_columns
	(	TABLE_CAT sysname  NULL,
		TABLE_SCHEM sysname  NULL,
		TABLE_NAME sysname NOT NULL,
		COLUMN_NAME sysname  NULL,
		DATA_TYPE smallint NOT NULL,
		TYPE_NAME sysname   NULL,
		COLUMN_SIZE int NULL,
		BUFFER_LENGTH int NULL,
		DECIMAL_DIGITS smallint NULL,
		NUM_PREC_RADIX smallint NULL,
		NULLABLE smallint NOT NULL,
		REMARKS nvarchar(255)  NULL,
        	COLUMN_DEF nvarchar(128)  NULL,
	        SQL_DATA_TYPE smallint null,
        	SQL_DATETIME_SUB smallint NULL,
		CHAR_OCTET_LENGTH int NULL,
		ORDINAL_POSITION smallint,
		IS_NULLABLE varchar(254)  NOT NULL,
		SS_DATA_TYPE tinyint null,
		COLUMN_FLAGS int NOT NULL)

	if ((isnull(charindex('%', @table_name),0) = 0) and
		(isnull(charindex('[', @table_name),0) = 0) and
		(isnull(charindex('_', @table_name),0) = 0))
	begin	/*	If no wild carding */
		insert into #tmp_columns
		select
			TABLE_CAT = c.TABLE_CATALOG,
			TABLE_SCHEM = c.TABLE_SCHEMA,
			TABLE_NAME = c.TABLE_NAME,
			COLUMN_NAME = c.COLUMN_NAME,
			DATA_TYPE =
			case c.DATA_TYPE & ~@DBTYPE_BYREF
				when @DBTYPE_I2				then @ODBC_SMALLINT
				when @DBTYPE_I4				then @ODBC_INT
				when @DBTYPE_R4				then @ODBC_REAL
				when @DBTYPE_R8				then @ODBC_FLOAT
				when @DBTYPE_CY				then @ODBC_MONEY
				when @DBTYPE_DATE			then @ODBC_DATETIME
				when @DBTYPE_DBDATE			then @ODBC_DATETIME
				when @DBTYPE_DBTIME			then @ODBC_DATETIME
				when @DBTYPE_DBTIMESTAMP	then @ODBC_DATETIME
				when @DBTYPE_BOOL			then @ODBC_BIT
				when @DBTYPE_DECIMAL		then @ODBC_DECIMAL
				when @DBTYPE_UI1			then @ODBC_TINYINT
				when @DBTYPE_I1				then @ODBC_NUMERIC
				when @DBTYPE_UI2			then @ODBC_NUMERIC
				when @DBTYPE_UI4			then @ODBC_NUMERIC
				when @DBTYPE_I8				then @ODBC_NUMERIC
				when @DBTYPE_UI8			then @ODBC_NUMERIC
				when @DBTYPE_NUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_VARNUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_GUID			then @ODBC_GUID
				when @DBTYPE_BYTES then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_IMAGE
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
								(c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
								 p.COLUMN_SIZE = 8
							then @ODBC_TIMESTAMP
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
							then @ODBC_BINARY
						else @ODBC_VARBINARY
					end
				when @DBTYPE_STR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_TEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_CHAR
						else @ODBC_VARCHAR
					end
				when @DBTYPE_WSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				when @DBTYPE_BSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				else @ODBC_NVARCHAR 	/*	Unknown OleDB datatype */
			end,
			TYPE_NAME = p.TYPE_NAME,
			COLUMN_SIZE =
				COALESCE(c.CHARACTER_MAXIMUM_LENGTH, c.NUMERIC_PRECISION, p.COLUMN_SIZE),
			BUFFER_LENGTH = c.CHARACTER_OCTET_LENGTH,
			DECIMAL_DIGITS = c.NUMERIC_SCALE,
			NUM_PREC_RADIX = NULL,
			NULLABLE = convert(smallint, c.IS_NULLABLE),
			REMARKS = convert(nvarchar(255),c.DESCRIPTION),
			COLUMN_DEF = c.COLUMN_DEFAULT,
			SQL_DATA_TYPE = NULL,
			SQL_DATETIME_SUB = convert(smallint, c.DATETIME_PRECISION),
			CHAR_OCTET_LENGTH = c.CHARACTER_OCTET_LENGTH,
			ORDINAL_POSITION = c.ORDINAL_POSITION,
			IS_NULLABLE =
			case c.IS_NULLABLE
				when 1 then 'YES'
				else 'NO'
			end,
			SS_DATA_TYPE = NULL,
			COLUMN_FLAGS = c.COLUMN_FLAGS
		from master.dbo.SYSREMOTE_COLUMNS <
					@table_server,
					@table_catalog,
					NULL,
					@table_name,
					NULL > c,
				master.dbo.SYSREMOTE_PROVIDER_TYPES <
					@table_server > p
					/* LUXOR/KAGERA don't support restricting DATA_TYPE */
			where c.DATA_TYPE = p.DATA_TYPE AND p.BEST_MATCH = 1 and
				(TABLE_SCHEMA like @table_schema
				or @table_schema is NULL or (TABLE_SCHEMA is NULL and @table_schema = N'%'))
				and (c.COLUMN_NAME like @column_name
				or	 @column_name is NULL)
	end
	else
	begin	/*	If wild carding */
		insert into #tmp_columns
		select
			TABLE_CAT = c.TABLE_CATALOG,
			TABLE_SCHEM = c.TABLE_SCHEMA,
			TABLE_NAME = c.TABLE_NAME,
			COLUMN_NAME = c.COLUMN_NAME,
			DATA_TYPE =
			case c.DATA_TYPE & ~@DBTYPE_BYREF
				when @DBTYPE_I2				then @ODBC_SMALLINT
				when @DBTYPE_I4				then @ODBC_INT
				when @DBTYPE_R4				then @ODBC_REAL
				when @DBTYPE_R8				then @ODBC_FLOAT
				when @DBTYPE_CY				then @ODBC_MONEY
				when @DBTYPE_DATE			then @ODBC_DATETIME
				when @DBTYPE_DBDATE			then @ODBC_DATETIME
				when @DBTYPE_DBTIME			then @ODBC_DATETIME
				when @DBTYPE_DBTIMESTAMP	then @ODBC_DATETIME
				when @DBTYPE_BOOL			then @ODBC_BIT
				when @DBTYPE_DECIMAL		then @ODBC_DECIMAL
				when @DBTYPE_UI1			then @ODBC_TINYINT
				when @DBTYPE_I1				then @ODBC_NUMERIC
				when @DBTYPE_UI2			then @ODBC_NUMERIC
				when @DBTYPE_UI4			then @ODBC_NUMERIC
				when @DBTYPE_I8				then @ODBC_NUMERIC
				when @DBTYPE_UI8			then @ODBC_NUMERIC
				when @DBTYPE_NUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_VARNUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_GUID			then @ODBC_GUID
				when @DBTYPE_BYTES then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_IMAGE
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
								(c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
								 p.COLUMN_SIZE = 8
							then @ODBC_TIMESTAMP
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
							then @ODBC_BINARY
						else @ODBC_VARBINARY
					end
				when @DBTYPE_STR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_TEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_CHAR
						else @ODBC_VARCHAR
					end
				when @DBTYPE_WSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				when @DBTYPE_BSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				else @ODBC_NVARCHAR 	/*	Unknown OleDB datatype */
			end,
			TYPE_NAME = p.TYPE_NAME,
			COLUMN_SIZE =
				COALESCE(c.CHARACTER_MAXIMUM_LENGTH, c.NUMERIC_PRECISION, p.COLUMN_SIZE),
			BUFFER_LENGTH = c.CHARACTER_OCTET_LENGTH,
			DECIMAL_DIGITS = c.NUMERIC_SCALE,
			NUM_PREC_RADIX = NULL,
			NULLABLE = convert(smallint, c.IS_NULLABLE),
			REMARKS = convert(nvarchar(255),c.DESCRIPTION),
			COLUMN_DEF = c.COLUMN_DEFAULT,
			SQL_DATA_TYPE = NULL,
			SQL_DATETIME_SUB = convert(smallint, c.DATETIME_PRECISION),
			CHAR_OCTET_LENGTH = c.CHARACTER_OCTET_LENGTH,
			ORDINAL_POSITION = c.ORDINAL_POSITION,
			IS_NULLABLE =
			case c.IS_NULLABLE
				when 1 then 'YES'
				else 'NO'
			end,
			SS_DATA_TYPE = NULL,
			COLUMN_FLAGS = c.COLUMN_FLAGS
		from master.dbo.SYSREMOTE_COLUMNS <
					@table_server,
					@table_catalog,
					NULL,
					NULL,
					NULL > c,
				master.dbo.SYSREMOTE_PROVIDER_TYPES <
					@table_server > p
					/* LUXOR/KAGERA don't support restricting DATA_TYPE */
			where c.DATA_TYPE = p.DATA_TYPE AND p.BEST_MATCH = 1 and
				(TABLE_SCHEMA like @table_schema
				or @table_schema is NULL or (TABLE_SCHEMA is NULL and @table_schema = N'%'))
				and (c.COLUMN_NAME like @column_name
				or	 @column_name is NULL)
				and c.TABLE_NAME like @table_name
	end

	update #tmp_columns
	set SQL_DATA_TYPE = spt_dt.SQL_DATA_TYPE,
		SQL_DATETIME_SUB =
		case
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME then 3
			else #tmp_columns.SQL_DATETIME_SUB
		end,
		TYPE_NAME = 
		case 
			when #tmp_columns.DATA_TYPE = @ODBC_BINARY and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
					(COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
					BUFFER_LENGTH = 8
				then 'timestamp'
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and
					#tmp_columns.SQL_DATETIME_SUB = 0
				then 'smalldatetime'
			when #tmp_columns.DATA_TYPE = @ODBC_MONEY and
					#tmp_columns.COLUMN_SIZE = 10
				then 'smallmoney'
			when (#tmp_columns.DATA_TYPE in (@ODBC_BINARY, @ODBC_CHAR) and
					(COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH) or
				 #tmp_columns.DATA_TYPE in (@ODBC_TEXT, @ODBC_NTEXT, @ODBC_IMAGE)
				then spt_dt.TYPE_NAME
			else isnull(#tmp_columns.TYPE_NAME, spt_dt.TYPE_NAME)
		end,
		COLUMN_SIZE =
		case
			when #tmp_columns.DATA_TYPE IN (@ODBC_REAL, @ODBC_FLOAT) then /* app. numeric types */
				spt_dt.data_precision
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and
					#tmp_columns.SQL_DATETIME_SUB = 0
				then 16
			else #tmp_columns.COLUMN_SIZE
		end,
		BUFFER_LENGTH =
		case
			when #tmp_columns.DATA_TYPE IN (@ODBC_NUMERIC, @ODBC_DECIMAL) then	/* decimal/numeric types */
				COLUMN_SIZE+2
			when isnull (#tmp_columns.BUFFER_LENGTH,0) = 0 then spt_dt.length
			else #tmp_columns.BUFFER_LENGTH
		end,
		DECIMAL_DIGITS =
		case
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME
				then #tmp_columns.SQL_DATETIME_SUB
			else COALESCE (DECIMAL_DIGITS, spt_dt.numeric_scale)
		end,
		NUM_PREC_RADIX = spt_dt.RADIX,
		SS_DATA_TYPE = 
		case
			when #tmp_columns.DATA_TYPE in ( @ODBC_TINYINT, @ODBC_SMALLINT, @ODBC_INT ) 
				and #tmp_columns.NULLABLE = 1
					then @ODS_INT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_TINYINT and #tmp_columns.NULLABLE = 0 
				then @ODS_TINYINT_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_SMALLINT	and #tmp_columns.NULLABLE = 0
				then @ODS_SMALLINT_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_INT  and #tmp_columns.NULLABLE = 0
				then @ODS_INT_NOT_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_REAL, @ODBC_FLOAT) and #tmp_columns.NULLABLE = 1
				then @ODS_FLOAT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_REAL and #tmp_columns.NULLABLE = 0
				then @ODS_REAL_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_FLOAT and #tmp_columns.NULLABLE = 0
				then @ODS_FLOAT_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_MONEY and #tmp_columns.NULLABLE = 1 
				then @ODS_MONEY_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_MONEY and #tmp_columns.NULLABLE = 0 
				then @ODS_MONEY_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and #tmp_columns.NULLABLE = 1
				then @ODS_DATETIME_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and #tmp_columns.NULLABLE = 0
				then @ODS_DATETIME_NOT_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_NTEXT, @ODBC_TEXT) then @ODS_TEXT
			when #tmp_columns.DATA_TYPE = @ODBC_BIT then @ODS_BIT
			when #tmp_columns.DATA_TYPE = @ODBC_DECIMAL then  @ODS_DECIMAL	
			when #tmp_columns.DATA_TYPE = @ODBC_NUMERIC then  @ODS_NUMERIC
			when #tmp_columns.DATA_TYPE = @ODBC_GUID then @ODS_GUID
			when #tmp_columns.DATA_TYPE = @ODBC_IMAGE then  @ODS_IMAGE
			when #tmp_columns.DATA_TYPE = @ODBC_TIMESTAMP
				and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
					(COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
					BUFFER_LENGTH = 8
				then @ODS_TIMESTAMP
			when #tmp_columns.DATA_TYPE = @ODBC_BINARY and #tmp_columns.NULLABLE =	1
				and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
				then  @ODS_BINARY_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_BINARY and #tmp_columns.NULLABLE =	0
				and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
				then @ODS_BINARY_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_VARBINARY
				then @ODS_VARBINARY	
			when #tmp_columns.DATA_TYPE in (@ODBC_CHAR, @ODBC_NCHAR) and #tmp_columns.NULLABLE = 1
				then @ODS_CHAR_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_CHAR, @ODBC_NCHAR) and #tmp_columns.NULLABLE = 0
				then @ODS_CHAR_NOT_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_VARCHAR, @ODBC_NVARCHAR) then @ODS_VARCHAR
			else null
		end
		from master.dbo.spt_datatype_info spt_dt
		where spt_dt.DATA_TYPE = #tmp_columns.DATA_TYPE
			AND (spt_dt.ODBCVer is null or spt_dt.ODBCVer = @ODBCVer)
			and isnull(spt_dt.AUTO_INCREMENT,0) = 0
			and not spt_dt.TYPE_NAME = 'smalldatetime'

	select
			TABLE_CAT,			TABLE_SCHEM,		TABLE_NAME,
			COLUMN_NAME,		DATA_TYPE,			TYPE_NAME,
			COLUMN_SIZE,		BUFFER_LENGTH,		DECIMAL_DIGITS,
			NUM_PREC_RADIX,		NULLABLE,			REMARKS,
			COLUMN_DEF,			SQL_DATA_TYPE,		SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH,	ORDINAL_POSITION,	IS_NULLABLE,
			SS_DATA_TYPE
		from #tmp_columns
		order by TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION

		drop table #tmp_columns

go
if (charindex('8.00', @@version) > 0)
	drop procedure sp_columns_ex
else
begin
	print ''
	print ''
	print 'Warning:'
	print 'you are installing the stored procedures '
	print 'on a pre 8.0 SQL Server.'
	print 'Ignore the following errors.'
end
go

/* 8.0 version */
raiserror(15339,-1,-1,'sp_columns_ex')
go
create procedure sp_columns_ex(
	@table_server		sysname,
	@table_name			sysname = null,
	@table_schema		sysname = null,
	@table_catalog		sysname = null,
	@column_name		sysname = null,
	@ODBCVer			int = 2)
as

	set nocount on
	declare
	@DBCOLUMNFLAGS_ISFIXEDLENGTH binary(1),	@DBCOLUMNFLAGS_ISLONG	binary(1),
	@DBCOLUMNFLAGS_ISROWVER	binary(2)

	select
	@DBCOLUMNFLAGS_ISFIXEDLENGTH	= 0x10,	@DBCOLUMNFLAGS_ISLONG	= 0x80,
	@DBCOLUMNFLAGS_ISROWVER	= 0x0200

	declare	
	@DBTYPE_I2 smallint,			@DBTYPE_I4 smallint,
	@DBTYPE_R4 smallint,			@DBTYPE_R8 smallint,
	@DBTYPE_CY smallint,			@DBTYPE_DATE smallint,
	@DBTYPE_BSTR smallint,			@DBTYPE_BOOL smallint,
	@DBTYPE_VARNUMERIC smallint,	@DBTYPE_DECIMAL smallint,
	@DBTYPE_UI1 smallint,			@DBTYPE_BYREF smallint,
	@DBTYPE_I1 smallint,			@DBTYPE_UI2 smallint,
	@DBTYPE_UI4 smallint,			@DBTYPE_I8 smallint,
	@DBTYPE_UI8 smallint,			@DBTYPE_GUID smallint,
	@DBTYPE_BYTES smallint,			@DBTYPE_STR smallint,
	@DBTYPE_WSTR smallint,			@DBTYPE_NUMERIC smallint,
	@DBTYPE_DBDATE smallint,		@DBTYPE_DBTIME smallint,
	@DBTYPE_DBTIMESTAMP smallint

	select
	@DBTYPE_I2			= 2,	@DBTYPE_I4			= 3,
	@DBTYPE_R4			= 4,	@DBTYPE_R8			= 5,
	@DBTYPE_CY			= 6,	@DBTYPE_DATE		= 7,
	@DBTYPE_BSTR		= 8,	@DBTYPE_BOOL		= 11,
	@DBTYPE_VARNUMERIC	= 139,	@DBTYPE_DECIMAL		= 14,
	@DBTYPE_UI1			= 17,	@DBTYPE_BYREF		= 16384,
	@DBTYPE_I1			= 16,	@DBTYPE_UI2			= 18,
	@DBTYPE_UI4			= 19,	@DBTYPE_I8			= 20,
	@DBTYPE_UI8			= 21,	@DBTYPE_GUID		= 72,
	@DBTYPE_BYTES		= 128,	@DBTYPE_STR			= 129,
	@DBTYPE_WSTR		= 130,	@DBTYPE_NUMERIC		= 131,
	@DBTYPE_DBDATE		= 133,	@DBTYPE_DBTIME		= 134,	
	@DBTYPE_DBTIMESTAMP	= 135

	declare	
	@ODS_SMALLINT_NOT_NULL tinyint,	@ODS_INT_NULL tinyint,
	@ODS_INT_NOT_NULL tinyint,		@ODS_TINYINT_NOT_NULL tinyint,
	@ODS_REAL_NOT_NULL tinyint,		@ODS_FLOAT_NULL tinyint,
	@ODS_FLOAT_NOT_NULL tinyint,	@ODS_MONEY_NULL tinyint,
	@ODS_MONEY_NOT_NULL tinyint,	@ODS_DATETIME_NULL tinyint,
	@ODS_DATETIME_NOT_NULL tinyint,	@ODS_TEXT tinyint,
	@ODS_BIT tinyint,				@ODS_DECIMAL tinyint,
	@ODS_NUMERIC tinyint,			@ODS_GUID tinyint,
	@ODS_IMAGE tinyint,				@ODS_TIMESTAMP tinyint,
	@ODS_BINARY_NULL tinyint,		@ODS_BINARY_NOT_NULL tinyint,
	@ODS_VARBINARY tinyint,			@ODS_CHAR_NULL tinyint,
	@ODS_CHAR_NOT_NULL tinyint,		@ODS_VARCHAR tinyint

	select 	
	@ODS_IMAGE = 34,			@ODS_TEXT = 35,
	@ODS_GUID = 36,				@ODS_BINARY_NULL = 37,			
	@ODS_VARBINARY = 37,		@ODS_INT_NULL = 38,
	@ODS_CHAR_NULL = 39,		@ODS_VARCHAR = 39,
	@ODS_TIMESTAMP = 45,		@ODS_BINARY_NOT_NULL = 45,
	@ODS_CHAR_NOT_NULL = 47,	@ODS_TINYINT_NOT_NULL = 48,
	@ODS_BIT = 50,				@ODS_SMALLINT_NOT_NULL = 52,	
	@ODS_INT_NOT_NULL = 56,		@ODS_REAL_NOT_NULL = 59,		
	@ODS_MONEY_NOT_NULL = 60,	@ODS_DATETIME_NOT_NULL = 61,	
	@ODS_FLOAT_NOT_NULL = 62,	@ODS_DECIMAL = 106,
	@ODS_NUMERIC = 108,			@ODS_FLOAT_NULL = 109,
	@ODS_MONEY_NULL = 110,		@ODS_DATETIME_NULL = 111

	declare 
	@ODBC_GUID smallint,		@ODBC_NTEXT smallint,
	@ODBC_NVARCHAR smallint,	@ODBC_NCHAR smallint,
	@ODBC_BIT smallint,			@ODBC_TINYINT smallint,
	@ODBC_IMAGE smallint,		@ODBC_VARBINARY smallint,
	@ODBC_TIMESTAMP smallint,	@ODBC_BINARY smallint,
	@ODBC_TEXT smallint,		@ODBC_CHAR smallint,
	@ODBC_NUMERIC smallint,		@ODBC_DECIMAL smallint,
	@ODBC_MONEY smallint,		@ODBC_INT smallint,		
	@ODBC_SMALLINT smallint,	@ODBC_FLOAT smallint,	
	@ODBC_REAL smallint,		@ODBC_VARCHAR smallint,
	@ODBC_DATETIME smallint

	select
	@ODBC_GUID		= -11,	@ODBC_NTEXT		= -10,
	@ODBC_NVARCHAR	= -9,	@ODBC_NCHAR		= -8,
	@ODBC_BIT		= -7,	@ODBC_TINYINT	= -6,
	@ODBC_IMAGE		= -4,	@ODBC_VARBINARY	= -3,
	@ODBC_TIMESTAMP	= -2,	@ODBC_BINARY	= -2,
	@ODBC_TEXT		= -1,	@ODBC_CHAR		= 1,
	@ODBC_NUMERIC	= 2,	@ODBC_DECIMAL	= 3,
	@ODBC_MONEY		= 3,	@ODBC_INT		= 4,		
	@ODBC_SMALLINT	= 5,	@ODBC_FLOAT		= 6,	
	@ODBC_REAL		= 7,	@ODBC_VARCHAR	= 12,
	@ODBC_DATETIME	=	
	case @ODBCVer
		when 2 then 11
		else 93
	end

	create table #tmp_columns
	(	TABLE_CAT sysname collate database_default NULL,
		TABLE_SCHEM sysname collate database_default NULL,
		TABLE_NAME sysname	collate database_default NOT NULL,
		COLUMN_NAME sysname collate database_default NULL,
		DATA_TYPE smallint NOT NULL,
		TYPE_NAME sysname  collate database_default NULL,
		COLUMN_SIZE int NULL,
		BUFFER_LENGTH int NULL,
		DECIMAL_DIGITS smallint NULL,
		NUM_PREC_RADIX smallint NULL,
		NULLABLE smallint NOT NULL,
		REMARKS nvarchar(255) collate database_default NULL,
        	COLUMN_DEF nvarchar(128) collate database_default NULL,
        	SQL_DATA_TYPE smallint null,
        	SQL_DATETIME_SUB smallint NULL,
		CHAR_OCTET_LENGTH int NULL,
		ORDINAL_POSITION smallint,
		IS_NULLABLE varchar(254) collate database_default NOT NULL,
		SS_DATA_TYPE tinyint null,
		COLUMN_FLAGS int NOT NULL)

	if ((isnull(charindex('%', @table_name),0) = 0) and
		(isnull(charindex('[', @table_name),0) = 0) and
		(isnull(charindex('_', @table_name),0) = 0))
	begin	/*	If no wild carding */
		insert into #tmp_columns
		select
			TABLE_CAT = c.TABLE_CATALOG,
			TABLE_SCHEM = c.TABLE_SCHEMA,
			TABLE_NAME = c.TABLE_NAME,
			COLUMN_NAME = c.COLUMN_NAME,
			DATA_TYPE =
			case c.DATA_TYPE & ~@DBTYPE_BYREF
				when @DBTYPE_I2				then @ODBC_SMALLINT
				when @DBTYPE_I4				then @ODBC_INT
				when @DBTYPE_R4				then @ODBC_REAL
				when @DBTYPE_R8				then @ODBC_FLOAT
				when @DBTYPE_CY				then @ODBC_MONEY
				when @DBTYPE_DATE			then @ODBC_DATETIME
				when @DBTYPE_DBDATE			then @ODBC_DATETIME
				when @DBTYPE_DBTIME			then @ODBC_DATETIME
				when @DBTYPE_DBTIMESTAMP	then @ODBC_DATETIME
				when @DBTYPE_BOOL			then @ODBC_BIT
				when @DBTYPE_DECIMAL		then @ODBC_DECIMAL
				when @DBTYPE_UI1			then @ODBC_TINYINT
				when @DBTYPE_I1				then @ODBC_NUMERIC
				when @DBTYPE_UI2			then @ODBC_NUMERIC
				when @DBTYPE_UI4			then @ODBC_NUMERIC
				when @DBTYPE_I8				then @ODBC_NUMERIC
				when @DBTYPE_UI8			then @ODBC_NUMERIC
				when @DBTYPE_NUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_VARNUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_GUID			then @ODBC_GUID
				when @DBTYPE_BYTES then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_IMAGE
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
								(c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
								 p.COLUMN_SIZE = 8
							then @ODBC_TIMESTAMP
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
							then @ODBC_BINARY
						else @ODBC_VARBINARY
					end
				when @DBTYPE_STR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_TEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_CHAR
						else @ODBC_VARCHAR
					end
				when @DBTYPE_WSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				when @DBTYPE_BSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				else @ODBC_NVARCHAR 	/*	Unknown OleDB datatype */
			end,
			TYPE_NAME = p.TYPE_NAME,
			COLUMN_SIZE =
				COALESCE(c.CHARACTER_MAXIMUM_LENGTH, c.NUMERIC_PRECISION, p.COLUMN_SIZE),
			BUFFER_LENGTH = c.CHARACTER_OCTET_LENGTH,
			DECIMAL_DIGITS = c.NUMERIC_SCALE,
			NUM_PREC_RADIX = NULL,
			NULLABLE = convert(smallint, c.IS_NULLABLE),
			REMARKS = convert(nvarchar(255),c.DESCRIPTION),
			COLUMN_DEF = c.COLUMN_DEFAULT,
			SQL_DATA_TYPE = NULL,
			SQL_DATETIME_SUB = convert(smallint, c.DATETIME_PRECISION),
			CHAR_OCTET_LENGTH = c.CHARACTER_OCTET_LENGTH,
			ORDINAL_POSITION = c.ORDINAL_POSITION,
			IS_NULLABLE =
			case c.IS_NULLABLE
				when 1 then 'YES'
				else 'NO'
			end,
			SS_DATA_TYPE = NULL,
			COLUMN_FLAGS = c.COLUMN_FLAGS
		from master.dbo.SYSREMOTE_COLUMNS <
					@table_server,
					@table_catalog,
					NULL,
					@table_name,
					NULL > c,
				master.dbo.SYSREMOTE_PROVIDER_TYPES <
					@table_server > p
					/* LUXOR/KAGERA don't support restricting DATA_TYPE */
			where c.DATA_TYPE = p.DATA_TYPE AND p.BEST_MATCH = 1 and
				(TABLE_SCHEMA like @table_schema
				or @table_schema is NULL or (TABLE_SCHEMA is NULL and @table_schema = N'%'))
				and (c.COLUMN_NAME like @column_name
				or	 @column_name is NULL)
	end
	else
	begin	/*	If wild carding */
		insert into #tmp_columns
		select
			TABLE_CAT = c.TABLE_CATALOG,
			TABLE_SCHEM = c.TABLE_SCHEMA,
			TABLE_NAME = c.TABLE_NAME,
			COLUMN_NAME = c.COLUMN_NAME,
			DATA_TYPE =
			case c.DATA_TYPE & ~@DBTYPE_BYREF
				when @DBTYPE_I2				then @ODBC_SMALLINT
				when @DBTYPE_I4				then @ODBC_INT
				when @DBTYPE_R4				then @ODBC_REAL
				when @DBTYPE_R8				then @ODBC_FLOAT
				when @DBTYPE_CY				then @ODBC_MONEY
				when @DBTYPE_DATE			then @ODBC_DATETIME
				when @DBTYPE_DBDATE			then @ODBC_DATETIME
				when @DBTYPE_DBTIME			then @ODBC_DATETIME
				when @DBTYPE_DBTIMESTAMP	then @ODBC_DATETIME
				when @DBTYPE_BOOL			then @ODBC_BIT
				when @DBTYPE_DECIMAL		then @ODBC_DECIMAL
				when @DBTYPE_UI1			then @ODBC_TINYINT
				when @DBTYPE_I1				then @ODBC_NUMERIC
				when @DBTYPE_UI2			then @ODBC_NUMERIC
				when @DBTYPE_UI4			then @ODBC_NUMERIC
				when @DBTYPE_I8				then @ODBC_NUMERIC
				when @DBTYPE_UI8			then @ODBC_NUMERIC
				when @DBTYPE_NUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_VARNUMERIC		then @ODBC_NUMERIC
				when @DBTYPE_GUID			then @ODBC_GUID
				when @DBTYPE_BYTES then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_IMAGE
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
								(c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
								 p.COLUMN_SIZE = 8
							then @ODBC_TIMESTAMP
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
							then @ODBC_BINARY
						else @ODBC_VARBINARY
					end
				when @DBTYPE_STR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG ) or (p.COLUMN_SIZE > 8000) then @ODBC_TEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_CHAR
						else @ODBC_VARCHAR
					end
				when @DBTYPE_WSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				when @DBTYPE_BSTR then
					case
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISLONG = @DBCOLUMNFLAGS_ISLONG) or (p.COLUMN_SIZE > 4000) then @ODBC_NTEXT
						when (c.COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH) then @ODBC_NCHAR
						else @ODBC_NVARCHAR
					end
				else @ODBC_NVARCHAR 	/*	Unknown OleDB datatype */
			end,
			TYPE_NAME = p.TYPE_NAME,
			COLUMN_SIZE =
				COALESCE(c.CHARACTER_MAXIMUM_LENGTH, c.NUMERIC_PRECISION, p.COLUMN_SIZE),
			BUFFER_LENGTH = c.CHARACTER_OCTET_LENGTH,
			DECIMAL_DIGITS = c.NUMERIC_SCALE,
			NUM_PREC_RADIX = NULL,
			NULLABLE = convert(smallint, c.IS_NULLABLE),
			REMARKS = convert(nvarchar(255),c.DESCRIPTION),
			COLUMN_DEF = c.COLUMN_DEFAULT,
			SQL_DATA_TYPE = NULL,
			SQL_DATETIME_SUB = convert(smallint, c.DATETIME_PRECISION),
			CHAR_OCTET_LENGTH = c.CHARACTER_OCTET_LENGTH,
			ORDINAL_POSITION = c.ORDINAL_POSITION,
			IS_NULLABLE =
			case c.IS_NULLABLE
				when 1 then 'YES'
				else 'NO'
			end,
			SS_DATA_TYPE = NULL,
			COLUMN_FLAGS = c.COLUMN_FLAGS
		from master.dbo.SYSREMOTE_COLUMNS <
					@table_server,
					@table_catalog,
					NULL,
					NULL,
					NULL > c,
				master.dbo.SYSREMOTE_PROVIDER_TYPES <
					@table_server > p
					/* LUXOR/KAGERA don't support restricting DATA_TYPE */
			where c.DATA_TYPE = p.DATA_TYPE AND p.BEST_MATCH = 1 and
				(TABLE_SCHEMA like @table_schema
				or @table_schema is NULL or (TABLE_SCHEMA is NULL and @table_schema = N'%'))
				and (c.COLUMN_NAME like @column_name
				or	 @column_name is NULL)
				and c.TABLE_NAME like @table_name
	end

	update #tmp_columns
	set SQL_DATA_TYPE = spt_dt.SQL_DATA_TYPE,
		SQL_DATETIME_SUB =
		case
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME then 3
			else #tmp_columns.SQL_DATETIME_SUB
		end,
		TYPE_NAME = 
		case 
			when #tmp_columns.DATA_TYPE = @ODBC_BINARY and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
					(COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
					BUFFER_LENGTH = 8
				then 'timestamp'
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and
					#tmp_columns.SQL_DATETIME_SUB = 0
				then 'smalldatetime'
			when #tmp_columns.DATA_TYPE = @ODBC_MONEY and
					#tmp_columns.COLUMN_SIZE = 10
				then 'smallmoney'
			when (#tmp_columns.DATA_TYPE in (@ODBC_BINARY, @ODBC_CHAR) and
					(COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH) or
				 #tmp_columns.DATA_TYPE in (@ODBC_TEXT, @ODBC_NTEXT, @ODBC_IMAGE)
				then spt_dt.TYPE_NAME collate database_default
			else isnull(#tmp_columns.TYPE_NAME, spt_dt.TYPE_NAME collate database_default)
		end,
		COLUMN_SIZE =
		case
			when #tmp_columns.DATA_TYPE IN (@ODBC_REAL, @ODBC_FLOAT) then /* app. numeric types */
				spt_dt.data_precision
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and
					#tmp_columns.SQL_DATETIME_SUB = 0
				then 16
			else #tmp_columns.COLUMN_SIZE
		end,
		BUFFER_LENGTH =
		case
			when #tmp_columns.DATA_TYPE IN (@ODBC_NUMERIC, @ODBC_DECIMAL) then	/* decimal/numeric types */
				COLUMN_SIZE+2
			when isnull (#tmp_columns.BUFFER_LENGTH,0) = 0 then spt_dt.length
			else #tmp_columns.BUFFER_LENGTH
		end,
		DECIMAL_DIGITS =
		case
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME
				then #tmp_columns.SQL_DATETIME_SUB
			else COALESCE (DECIMAL_DIGITS, spt_dt.numeric_scale)
		end,
		NUM_PREC_RADIX = spt_dt.RADIX,
		SS_DATA_TYPE = 
		case
			when #tmp_columns.DATA_TYPE in ( @ODBC_TINYINT, @ODBC_SMALLINT, @ODBC_INT ) 
				and #tmp_columns.NULLABLE = 1
					then @ODS_INT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_TINYINT and #tmp_columns.NULLABLE = 0 
				then @ODS_TINYINT_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_SMALLINT	and #tmp_columns.NULLABLE = 0
				then @ODS_SMALLINT_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_INT  and #tmp_columns.NULLABLE = 0
				then @ODS_INT_NOT_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_REAL, @ODBC_FLOAT) and #tmp_columns.NULLABLE = 1
				then @ODS_FLOAT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_REAL and #tmp_columns.NULLABLE = 0
				then @ODS_REAL_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_FLOAT and #tmp_columns.NULLABLE = 0
				then @ODS_FLOAT_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_MONEY and #tmp_columns.NULLABLE = 1 
				then @ODS_MONEY_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_MONEY and #tmp_columns.NULLABLE = 0 
				then @ODS_MONEY_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and #tmp_columns.NULLABLE = 1
				then @ODS_DATETIME_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_DATETIME and #tmp_columns.NULLABLE = 0
				then @ODS_DATETIME_NOT_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_NTEXT, @ODBC_TEXT) then @ODS_TEXT
			when #tmp_columns.DATA_TYPE = @ODBC_BIT then @ODS_BIT
			when #tmp_columns.DATA_TYPE = @ODBC_DECIMAL then  @ODS_DECIMAL	
			when #tmp_columns.DATA_TYPE = @ODBC_NUMERIC then  @ODS_NUMERIC
			when #tmp_columns.DATA_TYPE = @ODBC_GUID then @ODS_GUID
			when #tmp_columns.DATA_TYPE = @ODBC_IMAGE then  @ODS_IMAGE
			when #tmp_columns.DATA_TYPE = @ODBC_TIMESTAMP
				and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISROWVER) = @DBCOLUMNFLAGS_ISROWVER AND
					(COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH) = @DBCOLUMNFLAGS_ISFIXEDLENGTH and
					BUFFER_LENGTH = 8
				then @ODS_TIMESTAMP
			when #tmp_columns.DATA_TYPE = @ODBC_BINARY and #tmp_columns.NULLABLE =	1
				and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
				then  @ODS_BINARY_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_BINARY and #tmp_columns.NULLABLE =	0
				and (COLUMN_FLAGS & @DBCOLUMNFLAGS_ISFIXEDLENGTH = @DBCOLUMNFLAGS_ISFIXEDLENGTH)
				then @ODS_BINARY_NOT_NULL
			when #tmp_columns.DATA_TYPE = @ODBC_VARBINARY
				then @ODS_VARBINARY	
			when #tmp_columns.DATA_TYPE in (@ODBC_CHAR, @ODBC_NCHAR) and #tmp_columns.NULLABLE = 1
				then @ODS_CHAR_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_CHAR, @ODBC_NCHAR) and #tmp_columns.NULLABLE = 0
				then @ODS_CHAR_NOT_NULL
			when #tmp_columns.DATA_TYPE in (@ODBC_VARCHAR, @ODBC_NVARCHAR) then @ODS_VARCHAR
			else null
		end
		from master.dbo.spt_datatype_info spt_dt
		where spt_dt.DATA_TYPE = #tmp_columns.DATA_TYPE
			AND (spt_dt.ODBCVer is null or spt_dt.ODBCVer = @ODBCVer)
			and isnull(spt_dt.AUTO_INCREMENT,0) = 0
			and not spt_dt.TYPE_NAME = 'smalldatetime'

	select
			TABLE_CAT,			TABLE_SCHEM,		TABLE_NAME,
			COLUMN_NAME,		DATA_TYPE,			TYPE_NAME,
			COLUMN_SIZE,		BUFFER_LENGTH,		DECIMAL_DIGITS,
			NUM_PREC_RADIX,		NULLABLE,			REMARKS,
			COLUMN_DEF,			SQL_DATA_TYPE,		SQL_DATETIME_SUB,
			CHAR_OCTET_LENGTH,	ORDINAL_POSITION,	IS_NULLABLE,
			SS_DATA_TYPE
		from #tmp_columns
		order by TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION

