/*
12.5.4/EBF XXXXX/P/Sun_svr4/OS 5.8/ase125x/2087/32-bit/OPT/Thu Nov  9 01:43:28 2006

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

This software contains confidential and trade secret information of Sybase,
Inc.   Use,  duplication or disclosure of the software and documentation by
the  U.S.  Government  is  subject  to  restrictions set forth in a license
agreement  between  the  Government  and  Sybase,  Inc.  or  other  written
agreement  specifying  the  Government's rights to use the software and any
applicable FAR provisions, for example, FAR 52.227-19.
Sybase, Inc. One Sybase Drive, Dublin, CA 94568, USA
*/

if exists (select *
        from sysdatabases
                where name = 'sybsystemprocs')
	begin
        use sybsystemprocs
	end
else
        use master
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_is_dbo')
begin
	print "Dropping sp_is_dbo"
	drop procedure sp_is_dbo
end
go

print "Installing sp_is_dbo"
go


/*
** Description
** 	Finds if the user executing the procedure is the
**	database owner.
**
** Parameters
**	@currdbname	- database name
**
** Returns
** 	1 	- User is DBO or alias to DBO
**	0	- Otherwise
**
** Notes
**	It must be called as @currdbname.sp_is_dbo @currdbname
*/
create procedure sp_is_dbo(@currdbname	varchar(256)) 
as
begin
	declare	@dbo	int

	-- Initialize as non-DBO to handle all exit conditions.

	select @dbo = 0

	-- Check for caller's error. We should always call this sproc
	-- using @currdbname.dbo.<sprocname> so that we are looking up the
	-- correct sysusers. In case of an error in caller's calling
	-- convention, flag that by returning that user is not DBO in db.
	
	if (@currdbname != db_name())
	begin
		select @dbo = 0
	end

	-- Is this login the dbo of the current db?
	-- If a dbo has 'setuser' to some other user, we do not recognize
	-- him/her as DBO any longer. This is a minor restriction that we
	-- only allow a real DBO to perform any command, and not under setuser.
	
	else if exists (select 1 from sysusers
			where 	uid = 1 and suid = suser_id())
				and (user_id() = 1)
	begin
		select @dbo = 1
	end
	else
	begin
		-- Is this login the 'dbo' alias of the db, but w/o sa_role?
		
		if exists (select 1 from sysalternates
			   where suid = suser_id()
			     and altsuid = (select suid from sysusers
			     		    where uid = 1) )
		begin
			select @dbo = 1
		end
	end

	return @dbo
end
go
exec sp_procxmode 'sp_is_dbo', 'anymode'
go
grant execute on sp_is_dbo to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go


if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_help')
begin
	print "Dropping sp_ddlgen_help"
	drop procedure sp_ddlgen_help
end
go

print "Installing sp_ddlgen_help"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:12 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen_help [Total 1]
**
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen_help [Total 1]
**
** 18954, "Usage:"
*/
/*
** End spgenmsgs.pl output.
*/

exec sp_dbxt_recreate_proc sp_ddlgen_help
go

/*
** sp_ddlgen_help
**
**	Generate usage/help information for this sproc interface.
**
** Parameters:
**	@objtype	- Type of object to get more help on using sp_ddlgen.
*/
create procedure sp_ddlgen_help(
			  @objtype		varchar(30)	= NULL
			, @valid_objtypes	varchar(256)	= NULL
) as
begin
	declare @msg	varchar(256)
	      , @usage	varchar(10)

	exec sp_getmessage 18954, @usage output

	-- If user didn't request for a particular object type, generate
	-- basic help information.
	--
	if (@objtype IS NULL)
	begin
		select @msg = @usage + " sp_ddlgen [ 'help' ]"
		print @msg

		-- Show basic help usage info.
		select @msg = @usage + " sp_ddlgen 'help' [, %1! ]"
		print @msg, @valid_objtypes

		-- Show basic ddl gen usage for all object types.
		select @msg = @usage + " sp_ddlgen {" + @valid_objtypes + '}'
				     + ", @objname"
		print @msg

		return 0
	end

	-- Generate usage information for each object type.
	--
	if (@objtype = 'database')
	begin
		select @msg = @usage + " sp_ddlgen 'database' [, @dbname ]"
		print @msg

		-- Show individual examples...
		select @msg = @usage + " sp_ddlgen 'database'"
		print @msg

		select @msg = @usage + " sp_ddlgen 'database', 'master'"
		print @msg

		select @msg = @usage + " sp_ddlgen 'database', 'mydb%%'"
		print @msg

		select @msg = @usage + " sp_ddlgen 'database', '%%'"
		print @msg
	end
	else
	begin
		raiserror 19194, @objtype, @valid_objtypes
		return 1
	end


	return 0
end
go

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


go
exec sp_procxmode 'sp_ddlgen_help', 'anymode'
go
grant execute on sp_ddlgen_help to public
go
dump tran master with truncate_only
go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_permissions')
begin
	print "Dropping sp_ddlgen_permissions"
	drop procedure sp_ddlgen_permissions
end
go

print "Installing sp_ddlgen_permissions"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:12 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen_permissions [Total 0]
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen_permissions [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

exec sp_dbxt_recreate_proc sp_ddlgen_permissions
go

/*
** sp_ddlgen_permissions
**
**	Common sproc to implement permissions checking for all DDL gen commands.
**	For now we implement a simple rule that user has to have 'sa_role' to
**	generate DDL. In future if/when object-level DDL generation is allowed,
**	we have to make this permission checking more flexible by pushing it
**	into each @objtype-DDL-generating sproc.
**
** Object-type specific permission checks:
**
**  database:
**	. If wild-cards are used for @objname, need sa_role privilege.
**	  (This can probably be improved in the future to allow DBO of a
**	   set of dbs named 'mydb%' to run this sproc w/o sa_role.)
**	. If a single-db name is provided, you need either sa_role or DBO.
**
** Parameters:
**	@objtype	- Type of object for which DDL is being generated.
**	@objname	- Name of the object.
**
** Returns:
**	0		- Permissions failed.
**	Non-zero	- Otherwise.
*/
create procedure sp_ddlgen_permissions(
			  @objtype		varchar(30)
			, @objname		varchar(30)
) as
begin
	declare @retval		int
	      , @procname	varchar(45)
	      , @lcl_sarole	int

	select @retval = 0

	if (@objtype = 'database')
	begin
		-- If dbname w/o patterns was specified, check if user is
		-- DBO. If so, we are done.
		--
		if (charindex('%', @objname) = 0)
		begin
			select @procname = @objname + "..sp_is_dbo"
			exec @retval = @procname @objname

			-- Return an error/failure if the sub-proc were not
			-- to be found.
			if (@@error!= 0)
				return 0
		end

		if (@retval = 0)
		begin
			select @lcl_sarole = proc_role("sa_role")

			-- Translate sa_role's value to a return code from here
			select @retval = case 
					  WHEN (@lcl_sarole > 0) THEN 1
					  ELSE 0
					 end
		end

	end

	return @retval
end
go

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


dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_db_print_alterdb')
begin
	print "Dropping sp_ddlgen_db_print_alterdb"
	drop procedure sp_ddlgen_db_print_alterdb
end
go
print "Installing sp_ddlgen_db_print_alterdb"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:11 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen_database [Total 2]
**
** 18322, "There is not a database named '%1!'."
** 19475, "%1! not supported for archive databases. One or more of the databases named in this operation is an archive database."
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen_database [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

-- *************************************************************************** 
exec sp_dbxt_recreate_proc sp_ddlgen_db_print_alterdb
go

/*
** sp_ddlgen_db_print_alterdb
**
**	Print the ALTER DATABASE clause, with the given parameters. The caller
** 	has already decided that there is a change in disk pieces thta needs
**	a new ALTER DATABASE to be issued.
**
** Parameters:
**	@dbname		- Name of db for which DDL is being generated.
**	@archivedb	- Boolean; whether it's an archive db.
**	@alterdb_sql	- SQL for 'ALTER DATABASE'
**	@segment	- Segment's characteristics
**	@with_override	- Boolean; whether WITH OVERRIDED should be generated.
**	@prefix		- Prefix string, for formatting.
**
** Returns:	0, always.
*/
create procedure sp_ddlgen_db_print_alterdb(
			  @dbname		varchar(30)
			, @archivedb		tinyint
			, @alterdb_sql		varchar(15)
			, @segment		varchar(12)
			, @trace		int
			, @reason		varchar(30)
			, @with_override	tinyint		output
			, @prefix		varchar(10)	output
) as
begin
	declare @newline	char(1)
	      , @tabchar	char(1)
	      , @comment	char(3)
	      , @retval		int
	      , @override_sql	varchar(13)
	      , @printfmt	varchar(10)	-- Check its length before use.
	      , @indent		varchar(10)

	select @newline		= char(10)
	     , @tabchar		= char(9)
	     , @comment		= "-- "
	     , @override_sql	= "WITH OVERRIDE"
	     , @indent		= space(@@nestlevel * 2)


	-- If any disk piece in the current block of rows
	-- had a WITH OVERRIDE setting, then generate that
	-- clause here.

	if (@with_override = 1)
	begin
		select @printfmt = case @archivedb
					when 1 then "%1!-- %2!"
					else 	    "%1!%2!"
				   end
		print @printfmt, @tabchar, @override_sql
	end

	print "go%1!%2!", @newline, @newline

	if (@trace = 2)
	begin
		print " "
		print "%1!---- Trace sp_ddlgen_db_print_alterdb ----", @indent
		print "%1!Generate '%2! %3!' because %4!. @archivedb=%5! @segment='%6!' @with_override=%7!"
			, @indent
			, @alterdb_sql, @dbname, @reason
			, @archivedb, @segment, @with_override
		print "%1!---- End Trace sp_ddlgen_db_print_alterdb ----"
			, @indent
		print " "
	end

	-- print: ALTER DATABASE <dbname>
	print "%1! %2!", @alterdb_sql, @dbname

	-- We are restarting a newblock of disk pieces that
	-- will be investigated. Reset 'prev' variables,
	-- and other variables.
	--
	select @with_override = 0

	select @prefix = @tabchar + case @segment when "log only"
						  then "LOG ON "
						  else "    ON "
				    end
	return 0
end
go

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

-- *************************************************************************** 
exec sp_dbxt_recreate_proc sp_ddlgen_database
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen_database')
begin
	print "Dropping sp_ddlgen_database"
	drop procedure sp_ddlgen_database
end
go

print "Installing sp_ddlgen_database"
go

/*
** sp_ddlgen_database
**
**	Entry-point for generating DDL for a database. Currently all we support
**	is the basic create/alter database syntax. Subsequent sp_dboption etc.
**	are not [ to be ] supported. The expectation is that the DDLGen tool
**	will provide those value-adds.
**
** Parameters:
**	@dbname		- Name of db to generate DDL for. Supports wild-cards.
**	@trace		- Trace options (internal use.)
**
** Trace Levels:
** ------------
**	1	- Basic tracing of code flow.
**	2	- Trace alter db SQL generation.
**	1192	- Pretend that this is a 119x server, and ignore the code/data
**		  pieces that exist in 12.5.x, or later, but not in 11.9.x.
**	120	- Pretend that this is a 120.x server, and ignore the code/data
**		  pieces that exist in 12.5.x, or later, but not in 12.0.x.
**		  [ By running in this older-server mode, you can test that
**		    this sproc will correctly collapse multiple alter dbs into
**		    one when possible (ignoring 'crdate'), and will generate
**		    the syntax corectly without unit-specifiers. ]
*/
create procedure sp_ddlgen_database(
			  @dbname	varchar(255)	= NULL
			, @trace	int		= 0
) as
begin
	declare @newline	char(1)
	      , @tabchar	char(1)
	      , @retval		int
	      , @objtype	varchar(10)
	      , @objtype_lower	varchar(10)
	      , @prev_dbname	varchar(30)
	      , @devname	varchar(255)
	      , @segment	varchar(12)	-- of current disk piece
	      , @prev_segment	varchar(20)	-- of previous disk piece
	      , @lstart		int
	      , @size_pages	int
	      , @status3	int		-- sysdatabases.status3
	      , @size_str	varchar(20)	-- size as a string.
	      , @size_comments	varchar(255)	-- size in comments (and other
	      					-- diag info if tracing is ON).
	      , @size_mb	varchar(10)
	      , @prefix		varchar(10)

	      , @create_sql	varchar(6)
	      , @alterdb_sql	varchar(15)
	      , @override_sql	varchar(13)
	      , @tempdb_sql	varchar(11)
	      , @tempdb_ph	varchar(30)	-- used to point to this above.
	      , @archive_sql	varchar(30)
	      , @archivedb	tinyint

	      -- # of dbids for which we didn't generate the right #s of rows 
	      -- in the #temp table when compared to the # of rows that exist
	      -- for that db in sysusages.
	      --
	      , @count_failed_dbids	int	

	      -- To account for >2k logical page sizes
	      , @numpgsmb	float


		-- Various status bits in catalogs for re-use.
	      , @stat3_usertempdb	int
	      , @stat3_archivedb	int
		
	        -- Version sub-string to check against running server.
	      , @ase_1192_str	varchar(30)
	      , @ase_120x_str	varchar(30)
	      , @ase_150x_str	varchar(30)

	       -- Are we runningin a 12.5x or later server?
	      , @ase_125x_or_gt	tinyint
	      , @ase_150x_or_gt	tinyint

	      , @sqlstmt	varchar(255)
	      , @indent		varchar(32)
	      , @archivedb_comm	varchar(255)

	      , @comment	char(3)
	      , @pages		char(6)
	      , @crdate		datetime
	      , @prev_crdate	datetime	-- of previous disk piece
	      , @use_crdate	tinyint		-- whether server supports this
	      , @override	tinyint		-- setting of current disk piece
	      , @with_override	tinyint		-- whether we need to set this
	      					-- for this set of disk pieces.
	      , @units_ok	tinyint		-- does server support
	      					-- unit specifiers.

	select @newline		= char(10)
	     , @tabchar		= char(9)
	     , @comment		= "-- "
	     , @pages		= " pages"
	     , @objtype		= "DATABASE"
	     , @indent		= space(@@nestlevel * 2)
	     , @retval		= 0

	select @objtype_lower	= lower(@objtype)

	     -- SQL fragments that we will reuse.
	     , @create_sql	= "CREATE"
	     , @alterdb_sql	= "ALTER DATABASE"
	     , @override_sql	= "WITH OVERRIDE"
	     , @tempdb_sql	= " TEMPORARY "
	     , @archive_sql	= " TEMPLATE SQL FOR ARCHIVE "

	     -- Version parsing related variables.
	     , @ase_1192_str 	= "%Enterprise/11.9%"
	     , @ase_120x_str	= "%Enterprise/12.0%"
	     , @ase_150x_str	= "%Enterprise/15.0%"

	     -- Build special-use comment for archive dbs.
	     --
	     , @archivedb_comm = @newline + 
+ "-- This is a template DDL for an archive database. Fill in the logical"
+ @newline
+ "-- device names based on the devices existing in your installation,"
+ @newline
+ "-- and uncomment the WITH OVERRIDE clause, as necessary."

	     , @ase_125x_or_gt	= 1	-- Assume it's 12.5.x or later till
	     				-- we find out otherwise.

	     , @ase_150x_or_gt	= 0	-- Assume it's *not* 15.0.x or later
	     				-- till we find out otherwise.

	       -- Initialize 'prev' values that are used later for comparing
	       -- whether disk piece info changed across rows.
	       --
	     , @prev_dbname	= NULL
	     , @prev_segment	= NULL
	     , @prev_crdate	= NULL

	     -- Assume server does have this column. (We can't do matching
	     -- based on 'sysusages.crdate', till we are at 12.5x. or later.)
	     , @use_crdate	= 0
	     				

	     , @override	= 0		-- Assume no WITH OVERRIDE
	     , @with_override	= 0

	     -- Initialize various system catalog status bits
	     , @stat3_usertempdb	= 256
	     , @stat3_archivedb		= 4194304

	     
	select @numpgsmb = (1048576. / v.low)
	from master.dbo.spt_values v
	where v.number = 1
	  and v.type = "E"

	if (@objtype IS NULL)
		select @objtype = "DATABASE"

	-- Validate that the db exists, first, if only one was requested.
	if (charindex("%", @dbname) = 0) and (db_id(@dbname) IS NULL)
	begin
		raiserror 18322, @dbname
		return 1
	end

	-- Identify the server version we are running on.
	--
	if (@@version like @ase_1192_str) or (@@version like @ase_120x_str)
	begin
		select @ase_125x_or_gt 	= 0
	end
	else if (@@version like @ase_150x_str)
	begin
		select @ase_150x_or_gt 	= 1
	end

	-- Support masquerading as an older server.
	--
	if (@trace in (1192, 120))
	begin
		select @ase_125x_or_gt	= 0
		     , @ase_150x_or_gt	= 1
	end

	-- Some features are only usable 12.5.x onwards:
	-- 	. unit-specifiers 
	--	. 'sysusages.crdate'
	--
	select @units_ok 	= @ase_125x_or_gt
	     , @use_crdate	= @ase_125x_or_gt

	-- ###################################################################
	-- Stash away the segment info into a #temp table for processing.
	--
	select 	  u.dbid
		, dbname = d.name

		-- Remember whether this usages entry is for an archivedb.
		, archivedb = 0
		, d.status3
		, u.lstart
		, u.segmap
		, segment = case 
				WHEN ((u.segmap & 4) = 0) then 'data only'
				WHEN (u.segmap = 4) then 'log only'
				ELSE 'data and log'
			    end
		, size = convert(int, u.size)
		-- , sizeMb = ltrim(rtrim(str(u.size/512.0))) + 'M'
		, sizeMb = ltrim(rtrim(str(u.size/@numpgsmb ))) + 'M'
		, vdevno = convert(tinyint, substring(convert(binary(4), v.low), 1, 1))
		-- , vdevno = u.vdevno	-- use this directly in 15.0 onwards.
		, override = 0		-- whether this is a shared device that
					-- needs WITH OVERRIDE clause to be
					-- generated.
		, devname = v.name

		-- The sysusages entries fabricated from the dump for an
		-- archive db don't have the original 'crdate' (if exists)
		-- from the db dump. Fabricate current date, as a placeholder.
		--
		, crdate = getdate()	
	into #seginfo
	from 	  master.dbo.sysusages u
		, master.dbo.sysdevices v
		, master.dbo.sysdatabases d
	where 1 = 1
	  and d.name like @dbname		-- support for '%mydb%'
	  and d.dbid = u.dbid
	  and ((d.status3 & @stat3_archivedb) != @stat3_archivedb)
	  					-- skip archive dbs for now
	  					-- We'll get them a bit later.

	  and u.vstart between v.low and v.high	-- Use this for pre-15.0
	  -- and u.vdevno = v.vdevno		-- Use this for 15.0 onwards.

	  and v.status & 2 = 2    		-- Only get physical devices

	-- ###################################################################
	-- Validate that the above SQL captured exactly one row for each
	-- sysusages entry for a db. If not, we will be generating wrong
	-- data, as there is some cross-product join happening.
	-- If the validation fails, error out. [ This came about as during
	-- testing some wrong WHERE clause was used in 15.0.x from a version
	-- of this sproc meant for 12.5.x. Add this validation to trap
	-- future errors.]
	--
	select @count_failed_dbids = (select count(1)
	from (	select dbid, numrows = count(*)
		from #seginfo group by dbid) 			V1
	   , (	select dbid, numrows = count(*)
	   	from master.dbo.sysusages group by dbid)	V2
	where V1.dbid = V2.dbid
	  and V1.numrows != V2.numrows
	  )

	if (@count_failed_dbids != 0)
	begin
		print "Found %1! dbids with wrong number of rows cached in '%2!' v/s the rows in '%3!'"
			, @count_failed_dbids
			, '#seginfo'
			, 'master.dbo.sysusages'

		-- Display the dbids for which we failed, if tracing is ON.
		-- RESOLVE: This code will probably not work in 12.0, or
		-- 11.9.x. Need to maintain a different version of this
		-- sproc for those codelines.
		--
		if (@trace = 1)
		begin
			select    V1.dbid
				, dbname = db_name(V1.dbid)
				, expected_in_sysusages = V2.numrows
				, actual_in_#seginfo = V1.numrows
				, status = case V1.numrows
						when V2.numrows
						then "ok"
						else "not ok"
					   end
			into #failed_dbids
			from (	select dbid, numrows = count(*)
				from #seginfo group by dbid) 		 V1
			   , (	select dbid, numrows = count(*)
				from master.dbo.sysusages group by dbid) V2
				where V1.dbid = V2.dbid

			  -- Skip this clause, so that we can see all rows.
			  -- and V1.numrows != V2.numrows

			-- See the 'not ok' rows at the top.
			exec sp_autoformat @fulltabname = #failed_dbids
					 , @orderby = "order by status asc"
		end

		return @count_failed_dbids
	end

	-- exec sp_autoformat #seginfo

	-- ###################################################################
	-- Of the dbs named by the user by the @dbname argument, if there is
	-- even one archive db, fork off control to a sub-proc that knows how
	-- to gather and process sysusages entries for archive dbs.
	--
	if exists (select 1 from master.dbo.sysdatabases d
		   where d.name like @dbname
		     and ((d.status3 & @stat3_archivedb) = @stat3_archivedb) )
	begin
		-- Reuse @devname to raise an error message.
		select @devname = """sp_ddlgen 'database', " + @dbname + '"'
		raiserror 19475, @devname
		return 1
	end


	-- ###################################################################
	-- Depending on the version of ASE, we might / not have 'crdate'
	-- column in sysusages. If we do, copy that into the #temp table,
	-- using execute immediate. Seems straightforward, but there is an
	-- issue here if archive dbs are involved. In that case, master..
	-- sysusages has only a 'stub' entry for the db, whereas the #temp
	-- table would have been populated with possibly multiple rows from
	-- <scratchdb>..sysaltusages. In that case, we can't do a row-to-row
	-- update from master..sysusages.crdate to #seginfo.crdate as there
	-- won't be matching rows in master..sysusages.
	--
	if (@ase_125x_or_gt = 1)
	begin
		if (@trace = 1)
		begin
			-- The UPDATE below sometimes fails. Run the query
			-- to see what the actual results are like, using
			-- data from the temp table.
			--
			select u.dbid, u.crdate
			from master.dbo.sysusages u,
			     #seginfo t
			where u.dbid = t.dbid
			  and u.lstart = t.lstart

			print "%1!---- End Trace update ----%2!"
				, @indent , @newline
			if (@retval != 0)
				return @retval
		end

		-- First only update for non-archive db rows.
		--
		update #seginfo
		set crdate = (select u.crdate
			      from master.dbo.sysusages u
			      where u.dbid = t.dbid
			        and u.lstart = t.lstart)
		from #seginfo t
		where t.archivedb = 0

		select @retval = @@error

		if (@retval != 0)
		begin
			if (@trace = 1)
				print "Error updating #seginfo.crdate using sysusages.crdate"

			return @retval
		end
	end

	-- ###################################################################
	-- Go back and check each disk piece to see if it has data segment
	-- created on the device when the device was a log-only device.
	-- If so, the user would have had to create this with WITH OVERRIDE
	-- clause. Note that here, and we will re-gen the DDL accordingl.
	-- [ NOTE: This will update 'override' to 1 for all usages entries
	-- for an archive db, as the 'vdevno' is the same for all entries.
	-- That is ok, here as then we comment out the WITH OVERRIDE clause for
	-- the DDL for an archive db.
	--
	update #seginfo
	set override = 1
	from #seginfo o				-- outer table
	where segment IN ("data only", "log only")
	and exists (select 1 from #seginfo i	-- inner table

		         -- ignore this very disk piece from the outer table,
			 -- and search for other disk pieces with a higher
			 -- lstart (i.e. the ones that were created -after-
			 -- the outer disk piece.
			 --
		    where i.lstart < o.lstart
		      and i.dbid = o.dbid
		      and i.vdevno = o.vdevno
		      and i.segment != "data and log"
		      and i.segment != o.segment)


	declare diskcur cursor for
	select	  dbname, devname, segment, size, sizeMb, override, crdate
		, status3
		, lstart
		, archivedb
	from #seginfo
	order by dbid, lstart asc
	for read only

	select @retval = @@error
	if (@retval != 0)
		return @retval

	open diskcur
	select @retval = @@error
	if (@retval != 0)
		return @retval

	while (1 = 1)
	begin	
		fetch diskcur into @dbname
				  , @devname
				  , @segment
				  , @size_pages
				  , @size_mb
				  , @override
				  , @crdate
				  , @status3
				  , @lstart
				  , @archivedb

		select @retval = @@error
		if (@@sqlstatus != 0) OR (@retval != 0)
			break

		-- We are beginning the processing for sysusages entries
		-- for a new database. Initialize the SQL fragments...
		--
		if (@prev_dbname != @dbname)
		begin	

			-- Terminate the last statement in previous batch 
			if (@prev_dbname IS NOT NULL)
				print "go%1!%2!", @newline, @newline

			else if (@prev_dbname IS NULL)
			begin
				print "USE master%1!go%2!", @newline, @newline

			end

			-- Reset for every db that we'll process in a loop.

			if ((@status3 & @stat3_usertempdb) = @stat3_usertempdb)
			begin
				select @tempdb_ph = @tempdb_sql
			end

			else if ((@status3 & @stat3_archivedb) = @stat3_archivedb)
			begin
				select @tempdb_ph = @archive_sql
			end

			else
				select @tempdb_ph = " "

			-- Generate the DROP syntax first.
			--
			print "%1!PRINT ""<<<< %2!%3!%4! %5! >>>>""%6!go%7!%8!"
				, @newline
				, @create_sql
				, @tempdb_ph
				, @objtype
				, @dbname
				, @newline, @newline, @newline

			print "IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases"
			print "	   WHERE name = '%1!')", @dbname
			print "	DROP %1! %2!", @objtype, @dbname
			print "go%1!%2!", @newline, @newline

			print "IF (@@error != 0)%1!BEGIN", @newline
			print "	PRINT ""Error dropping %1! '%2!'"""
				, @objtype_lower, @dbname
			print "	SELECT syb_quit()%1!END%2!go%3!%4!"
				, @newline, @newline, @newline, @newline

			-- Reset loop variables that are only to be used for
			-- rows for one db.
			--
			select @prev_segment 	= NULL
			     , @prev_crdate 	= NULL

			       -- Note that we are currently processing this db.
			     , @prev_dbname	= @dbname

			-- We don't want to generate CREATE ARCHIVE DATABASE,
			-- so reset the phrase, in a way to suppress that.
			--
			if (@tempdb_ph = @archive_sql)
				select @tempdb_ph = " "

			-- Display special-case comments for archive db's DDL.
			if (@archivedb = 1)
			begin
				print @archivedb_comm
			end

			print "%1!%2!%3! %4!"
				, @create_sql, @tempdb_ph
				, @objtype, @dbname
		end	-- }

		if (@prev_segment IS NULL)
			select @prefix = @tabchar + "    ON "

		else if (@use_crdate = 1) and (@prev_crdate != @crdate)
		begin	

			-- State change in segment defn. Move to ALTER DB SQL
			exec sp_ddlgen_db_print_alterdb
					  @dbname
					, @archivedb
					, @alterdb_sql
					, @segment
					, @trace
					, 'dates are different'
					, @with_override output
					, @prefix 	 output
		end	-- }

		else if (@prev_segment = @segment)
		begin
			select @prefix = @tabchar + "     , "
		end

		else if (    (@prev_segment != "data and log")
			 and (@segment = "log only"))

			select @prefix = @tabchar + "LOG ON "

		else
		begin	

			-- State change in segment defn. Move to ALTER DB SQL
			exec sp_ddlgen_db_print_alterdb
					  @dbname
					, @archivedb
					, @alterdb_sql
					, @segment
					, @trace
					, 'segments are different'
					, @with_override output
					, @prefix 	 output
		end	-- }

		-- Depending on whether the server supports unit-specifiers,
		-- pick the way 'size' is printed. If the server supports
		-- unit-specifiers, report using units, and report the # of
		-- pages in comments. Otherwise, do the opposite.
		--
		if (@units_ok = 1)
		begin
			select @size_str = "'" + @size_mb + "'"
			     , @size_comments = @comment
			     		      + convert(varchar, @size_pages)
					      + @pages
		end
		else
		begin
			select @size_str = convert(varchar, @size_pages)
			     , @size_comments = @comment + @size_mb
		end

		if (@trace = 1)
		begin
			select @size_comments = @size_comments
					      +  " ["
					      + @segment

					      + ",lstart="
					      + convert(varchar, @lstart)

					      + ",override="
					      + convert(varchar, @override)

					      + ","
					      + convert(varchar, @crdate)
					      +  "]"
		end

		-- Remember that we found at least one disk piece in this 
		-- chunk of disk pieces that needs a WITH OVERRIDE syntax.
		--
		if (@override = 1)
			select @with_override = 1

		print "%1!%2! = %3! %4!"
			, @prefix, @devname, @size_str
			, @size_comments

		-- Store this disk piece's values, for comparison with those
		-- of the next piece.
		select @prev_segment 	= @segment
		     , @prev_crdate	= @crdate

	end	-- }
	close diskcur
	deallocate cursor diskcur

	if (@retval != 0)
		return @retval

	-- Handle the case that the very last disk piece might need this clause.
	if (@with_override = 1)
	begin
		print "%1!%2!", @tabchar, @override_sql
	end
	print "go%1!", @newline

	return @retval
end
go

go
dump transaction sybsystemprocs with truncate_only
go

if exists (select *
	from sysobjects
		where sysstat & 7 = 4
			and name = 'sp_ddlgen')
begin
	print "Dropping sp_ddlgen"
	drop procedure sp_ddlgen
end
go

print "Installing sp_ddlgen"
go

/*
** Generated by spgenmsgs.pl on Sun Aug 27 22:54:10 2006 
*/
/*
** raiserror Messages for /calm/svr/sql/generic/sproc/ddlgen [Total 1]
**
** 19194, "Argument '%1!' is either invalid or non-unique. Valid arguments are: %2!"
*/
/*
** sp_getmessage Messages for /calm/svr/sql/generic/sproc/ddlgen [Total 0]
*/
/*
** End spgenmsgs.pl output.
*/

exec sp_dbxt_recreate_proc sp_ddlgen
go

/*
** sp_ddlgen
**
**
**	Minimalist shell sproc to drive DDL generation for base object types.
**	This is currently only supporting DDL generation for databases.
**
** Parameter:
**	@objtype	- Type of object ('database', 'table' etc.)
**	@objname	- Name of the object
**	@trace		- Trace leve; for internal use only.
*/
create procedure sp_ddlgen(
			  @objtype	varchar(30)	= NULL
			, @objname	varchar(255)	= NULL
			, @trace	int		= NULL
) as
begin
	declare @retval		int
	      , @baseprocname	varchar(60)
	      , @procname	varchar(60)

	      , @obj_db		varchar(8)
	      , @valid_objtypes	varchar(255)

	select @baseprocname = 'sybsystemprocs.dbo.sp_ddlgen_'

	     -- Start listing the names of entities that we support.
	     , @obj_db	= 'database'
	     , @retval	= 0

	select @valid_objtypes = "'" + @obj_db + "'"

	if (@objtype IS NULL) or (@objtype = 'help')
	begin
		select @procname = @baseprocname + 'help'
		exec @retval = @procname @objname, @valid_objtypes
		return @retval
	end

	-- Validate object type, to avoid junk error-checking downstream.
	if (@objtype NOT IN (  @obj_db
			    ) )

	begin
		raiserror 19194, "@objtype", @valid_objtypes
		return 1
	end

	-- Handle NULL objname input:
	--  . For databases, generate DDL for the current db of user.
	--
	if ((@objtype = @obj_db) and (@objname IS NULL))
		select @objname = db_name()

	-- Name the permission checking sub-proc for generating the DDL.
	select @procname = @baseprocname + 'permissions'
	exec @retval = @procname @objtype, @objname
	if (@retval = 0)	-- Check for failure in permissions checks
		return 1

	-- Name the sub-proc generating the DDL.
	select @procname = @baseprocname + @objtype

	-- Fork off control to the sub-proc, if we got the right objtype.
	if (@objtype IN (  'database'
			  --, add a new entry here in the future.
	   		) )
	begin
		exec @retval = @procname @objname, @trace
	end


	return @retval
end	-- }
go

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

go
exec sp_procxmode 'sp_ddlgen', 'anymode'
go
grant execute on sp_ddlgen to public
go
